js實行原生錄像

js實行原生錄像

公司須要一個js原生的視頻錄像功能,以前沒用作了,寫個筆記記錄下。html

1、獲取攝像頭

既然要錄像,就要獲取攝像頭權限。那咱們就先實現這一步再說。經過參閱一些資料得知,js可使用navigator.mediaDevices來獲取攝像頭。node

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>demo</title>
</head>

<body>
    <video id="video"></video>
    <button id="button">開始</button>
</body>
<script>
    const video = document.getElementById("video")
    button.addEventListener("click", function() {
        openCam()
    })
    // 打開攝像頭
    const openCam = function() {
        const constraints = {
            video: true,
            audio: false
        };

        navigator.mediaDevices.getUserMedia(constraints)
            .then(function(stream) {
                /* 使用這個stream stream */
                video.src = stream
                video.play()
            })
            .catch(function(err) {
                console.log(err)
                /* 處理error */
            });
    }
</script>

</html>

在手機運行demo,會發現navigator.mediaDevices老是undefined,緣由是navigator.mediaDevices() 只有在如下三種環境中才能獲取到:git

一、localhost 域
二、開啓了 HTTPS 的域
三、使用 file:// 協議打開的本地文件

由於我是用的pc開發,也沒有攝像頭,手機沒發用localhost訪問,就用node搭建了一個https服務
a、生成證書文件github

一、打開git bash檢測openssl是否安裝:openssl version -a
二、生成私鑰key文件:openssl genrsa -out privatekey.pem 1024
三、經過私鑰生成CSR證書籤名:openssl req -new -key privatekey.pem -out certrequest.csr
四、經過私鑰和證書籤名生成證書文件:openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem

b、編寫node代碼web

let https = require('https');
let fs = require('fs');
let express = require('express');

let app = express();
app.use(express.static('./public'));

let options = {
    key: fs.readFileSync('./privatekey.pem'),
    cert: fs.readFileSync('./certificate.pem')
}

let https_server = https.createServer(options, app);
https_server.listen(8089)

對於使用筆記本的同窗來講,直接用手機訪問localhost就能夠了。下面在提供一種在Chrome中使用http訪問的方法,在手機端測試下貌似不行,只有在pc上能夠。chrome

打開 chrome://flags/#unsafely-treat-insecure-origin-as-secure
將該 flag 切換成 enable 狀態
輸入框中填寫須要開啓的域名,譬如 http://example.com",多個以逗號分隔。

可是這是咱們並不能正常運行代碼,點擊開是會獲得一條報錯:8089/[object%20MediaStream] 404 (Not Found)。將then方法替換爲下面的代碼就好了express

.then(function(stream) {
    // 將攝像頭拍到的東西,經過video展示出來
    video.srcObject = stream;
    video.onloadedmetadata = function(e) {
        video.play();
    };
})

2、打開後置攝像頭

如今咱們能正常調起攝像頭了,可是默認打開的是後置攝像頭,只須要修改constraints就能夠了canvas

//修改constraints
const constraints = {
    video: {
        facingMode: 'environment',
    },
    audio: false,
};

根據需求還須要一個轉換攝像頭的按鈕。總體思路比較簡單,當點擊按鈕是就關閉當前媒體,再從新打開一個相反的攝像頭bash

const change = document.getElementById('change')
// environment:後置 user:前置
let facingMode = "environment"
// 保存媒體流
let currentStream = null
change.addEventListener("click", function() {
    facingMode = facingMode === "user" ? "environment" : "user"
    openCam()
})
// 中止全部的媒體
function stopMediaTracks(stream) {
    stream.getTracks().forEach(track => {
        track.stop();
    });
}
// 修改openCam
function openCam() {
    if (currentStream) stopMediaTracks(currentStream);
    const constraints = {
        video: {
            facingMode: facingMode,
        },
        audio: false,
    };
    navigator.mediaDevices.getUserMedia(constraints)
        .then(function(stream) {
                currentStream = stream
                    ......
            }
        }

3、開始錄像

基本的事情咱們都作到了,接下來就要錄製視屏, 代碼實現app

let allChunks = [];
// 捕捉canvas的內容,轉化爲MediaStream對象
const stream2 = canvas.captureStream(60);
// 建立一個錄製MediaRecorder 對象
const recorder = new MediaRecorder(stream2, {
    mimeType: 'video/webm;codecs=vp9'
});
//開始錄製
function startRecording() {
    // 每10ms記錄一次,也就是執行ondataavailable
    recorder.start(10);
}
// 中止錄製
function stopAndblobDownload() {
    recorder.stop();
    // 將錄製的數據流轉化爲Blob
    const fullBlob = new Blob(allChunks);
    // 生成一個路徑,可上傳下載
    const downloadUrl = window.URL.createObjectURL(fullBlob);
}
// 將錄製的數據流保存起來
recorder.ondataavailable = e => {
    allChunks.push(
        e.data
    );
}

function openCam() {
    ......
    then(res => {
        navigator.mediaDevices.getUserMedia(constraints)
            .then(function(stream) {
                    ......
                    // 把video寫入到canvas中
                    setInterval(() => {
                        context.drawImage(video, 0, 0, 640, 480);
                    }, Math.floor(1000 / 60));
                }
            }
    })
}

以上就基本實現了錄製視頻功能。

4、思路總結

首先咱們得用navigator.mediaDevices.getUserMedia獲取攝像頭權限,這裏注意mediaDevices使用的條件。將getUserMedia的成功回調函數(then)中獲得的媒體流,用video呈現,再用canvas(drawImage API)繪製vidoe。轉換(captureStream API)canvas爲MediaStream對象。經過MediaRecorder對象進行錄製。其實captureStream是HTMLMediaElement原型上的方法,全部HTMLMediaElement都能調用,也就是說video能直接轉換爲MediaStream對象。修改代碼:

//  const stream2 = canvas.captureStream(60); 
  const stream2 = video.captureStream(60);
  ...
  // setInterval(() => {
  //   context.drawImage(stream, 0, 0, 640, 480);
  // }, Math.floor(1000 / 60));
  ...

這樣咱們就不須要canvas。

結束語

第一次寫這種東西,不喜勿噴。完成demo

相關文章
相關標籤/搜索