js的視頻和音頻採集
- 今天要寫的,不是大家平時會用到的東西。因爲兼容性實在不行,只是爲了說明下前端原來還能幹這些事。
大家能想象前端是能將攝像頭和麥克風的視頻流和音頻流提取出來,再爲所欲爲的麼。或者說我想把我canvas畫板的內容錄製成一個視頻,這些看似js應該做不到的事情,其實都是可以做到的,不過兼容性不好。我在這裏都是以chrome瀏覽器舉的例子。
這裏先把用到的api列一下:
- getUserMedia:打開攝像頭和麥克風的接口(文檔鏈接)
- MediaRecorder:採集音視頻流(文檔鏈接)
- srcObject:video標籤可直接播放視頻流,這是一個大家應該很少用到其實兼容性很好的屬性,推薦大家瞭解(文檔鏈接)
captureStream:可以將canvas輸出流,其實不單單是canvas這裏只是舉有這個功能,具體的可以看文檔(文檔鏈接)
1、從攝像頭展示視頻
一、打開攝像頭
// 這裏是打開攝像頭和麥克設備(會返回一個Promise對象)
navigator.mediaDevices.getUserMedia({
audio: true,
video: true
}).then(stream => {
console.log(stream) // 放回音視頻流
}).catch(err => {
console.log(err) // 錯誤回調
})
上面我們成功打開了攝像頭和麥克風,並獲取到視頻流。那接下來就是要把流呈現到交互界面中了。
二、展示視頻
<!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>Document</title>
</head>
<body>
<video id="video" width="500" height="500" autoplay></video>
</body>
<script>
var video = document.getElementById('video')
navigator.mediaDevices.getUserMedia({
audio: true,
video: true
}).then(stream => {
// 這裏就要用到srcObject屬性了,可以直接播放流資源
video.srcObject = stream
}).catch(err => {
console.log(err) // 錯誤回調
})
</script>
效果如下圖:
到這裏爲止我們已經成功的將我們的攝像頭在頁面展示了。下一步就是如何將採集視頻,並下載視頻文件。
2、從攝像頭採集視頻
這裏用到的是MediaRecorder對象:
- 創建一個新的MediaRecorder對象,返回一個MediaStream 對象用來進行錄製操作,支持配置項配置容器的MIME type (例如"video/webm" or "video/mp4")或者音頻的碼率視頻碼率
MediaRecorder接收兩個參數第一個是stream音視頻流,第二個是option配置參數。下面我們可以把上面攝像頭獲取的流加入MediaRecorder中。
var video = document.getElementById('video')
navigator.mediaDevices.getUserMedia({
audio: true,
video: true
}).then(stream => {
// 這裏就要用到srcObject屬性了,可以直接播放流資源
video.srcObject = stream
var mediaRecorder = new MediaRecorder(stream, {
audioBitsPerSecond : 128000, // 音頻碼率
videoBitsPerSecond : 100000, // 視頻碼率
mimeType : 'video/webm;codecs=h264' // 編碼格式
})
}).catch(err => {
console.log(err) // 錯誤回調
})
在上面我們創建了MediaRecorder的實例mediaRecorder。接下來就是控制mediaRecorder的開始採集和停止採集的方法了。
MediaRecorder提供了一些方法和事件供我們使用:
- MediaRecorder.start(): 開始錄製媒體,這個方法調用時可以通過給timeslice參數設置一個毫秒值,如果設置這個毫秒值,那麼錄製的媒體會按照你設置的值進行分割成一個個單獨的區塊, 而不是以默認的方式錄製一個非常大的整塊內容.
- MediaRecorder.stop(): 停止錄製. 同時觸發dataavailable事件,返回一個存儲Blob內容的錄製數據.之後不再記錄
- ondataavailable事件: MediaRecorder.stop觸發該事件,該事件可用於獲取記錄的媒體(Blob在事件的data屬性中可用作對象)
// 這裏我們增加兩個按鈕控制採集的開始和結束
var start = document.getElementById('start')
var stop = document.getElementById('stop')
var video = document.getElementById('video')
navigator.mediaDevices.getUserMedia({
audio: true,
video: true
}).then(stream => {
// 這裏就要用到srcObject屬性了,可以直接播放流資源
video.srcObject = stream
var mediaRecorder = new MediaRecorder(stream, {
audioBitsPerSecond : 128000, // 音頻碼率
videoBitsPerSecond : 100000, // 視頻碼率
mimeType : 'video/webm;codecs=h264' // 編碼格式
})
// 開始採集
start.onclick = function () {
mediaRecorder.start()
console.log('開始採集')
}
// 停止採集
stop.onclick = function () {
mediaRecorder.stop()
console.log('停止採集')
}
// 事件
mediaRecorder.ondataavailable = function (e) {
console.log(e)
// 下載視頻
var blob = new Blob([e.data], { 'type' : 'video/mp4' })
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = `test.mp4`
a.click()
}
}).catch(err => {
console.log(err) // 錯誤回調
})
ok,現在執行一波操作;
上圖可以看到結束採集後ondataavailable事件返回的數據中有一個Blob對象,這就是視頻資源了,再接下來我們就可以通過URL.createObjectURL()方法將Blob爲url下載到本地了。視頻的採集到下載就結束了,很簡單粗暴。
上面是視頻採集下載的例子,如果只要音頻採集的,同樣道理的設置“mimeType”就好了。這裏我就不舉例了。下面我在介紹將canvas錄製爲一個視頻文件
2、canvas輸出視頻流
- 這裏用到的是captureStream方法,將canvas輸出流,再用video展現,或者用MediaRecorder採集資源也是可以的。
// 這裏就閒話少說直接上重點了因爲和上面視頻採集的是一樣的道理的。
<!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>Document</title>
</head>
<body>
<canvas width="500" height="500" id="canvas"></canvas>
<video id="video" width="500" height="500" autoplay></video>
</body>
<script>
var video = document.getElementById('video')
var canvas = document.getElementById('canvas')
var stream = $canvas.captureStream(); // 這裏獲取canvas流對象
// 接下來你先爲所欲爲都可以了,可以參考上面的我就不寫了。
</script>
下面我再貼一個gif(這是結合我上次寫的canvas事件的demo結合這次視頻採集的結合)傳送門(Canvas事件綁定)
- 希望大家可以實現下面的效果,其實還可以在canvas視頻裏插入背景音樂什麼的,這些都比較簡單。