web技术支持| Web 客户端实现录音、录像
Web 實(shí)現(xiàn)客戶端錄音或錄像的流程大致分為:
- 采集音頻/視頻
- 開始錄制并監(jiān)聽回調(diào)
- 下載 Or 轉(zhuǎn)碼
采集音頻/視頻
瀏覽器兼容
注意事項(xiàng)
- 除 127.0.0.1、localhost URL 以外,網(wǎng)站必須配置 SSL 證書,也就是網(wǎng)站需要 https 環(huán)境
- 需要音頻/視頻輸入媒體設(shè)備,例如:麥克風(fēng)、攝像頭,包含內(nèi)置。
開始采集
利用 navigator.mediaDevices 對(duì)象的 getUserMedia 方法采集音頻和視頻媒體流。
// 老的瀏覽器可能根本沒有實(shí)現(xiàn) mediaDevices,所以我們可以先設(shè)置一個(gè)空的對(duì)象 if (navigator.mediaDevices === undefined) {navigator.mediaDevices = {}; }// 一些瀏覽器部分支持 mediaDevices。我們不能直接給對(duì)象設(shè)置 getUserMedia // 因?yàn)檫@樣可能會(huì)覆蓋已有的屬性。這里我們只會(huì)在沒有g(shù)etUserMedia屬性的時(shí)候添加它。 if (navigator.mediaDevices.getUserMedia === undefined) {navigator.mediaDevices.getUserMedia = function(constraints) {// 首先,如果有g(shù)etUserMedia的話,就獲得它var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;// 一些瀏覽器根本沒實(shí)現(xiàn)它 - 那么就返回一個(gè)error到promise的reject來保持一個(gè)統(tǒng)一的接口if (!getUserMedia) {return Promise.reject(new Error('getUserMedia is not implemented in this browser'));}// 否則,為老的navigator.getUserMedia方法包裹一個(gè)Promisereturn new Promise(function(resolve, reject) {getUserMedia.call(navigator, constraints, resolve, reject);});} }// 開始采集輸入媒體 navigator.mediaDevices.getUserMedia({// 采集音頻audio: true,// 采集視頻video: true }) .then(function(stream) {// TODO }) .catch(function(err) {console.log(err.name + ": " + err.message); });錄制
創(chuàng)建錄制實(shí)例
利用 new 指令 創(chuàng)建一個(gè) MediaRecorder 對(duì)象。
// 定義錄制的編碼格式 const options = {mimeType: "video/webm;codecs=opus" }; // 錄制實(shí)例 const mediaRecorder = new MediaRecorder(audioStream, options);監(jiān)聽錄制回調(diào)事件
// 創(chuàng)建一個(gè)集合存儲(chǔ)錄制的數(shù)據(jù) const recordedBlobs = [];// 監(jiān)聽錄制錯(cuò)誤 mediaRecorder.onerror = async (event) => {// TODO }// 監(jiān)聽錄制開始 mediaRecorder.onstart = async (event) => {// TODO }// 監(jiān)聽錄制結(jié)束或者中斷的回調(diào) mediaRecorder.onstop = async (event) => {// 這里我們可以將錄制的數(shù)據(jù),進(jìn)行處理之后,存儲(chǔ)至服務(wù)端,例如:上傳 OSS }// 監(jiān)聽錄制暫停 mediaRecorder.onpause = async (event) => {// TODO }// 監(jiān)聽錄制恢復(fù) mediaRecorder.onstart = async (event) => {// TODO }// 監(jiān)聽錄制過程中返回?cái)?shù)據(jù) mediaRecorder.ondataavailable = (event) => {console.log('handleDataAvailable', event);if (event.data && event.data.size > 0) {recordedBlobs.push(event.data);} }檢測(cè)編碼類型是否支持
利用 isTypeSupported 方法,我們可以檢測(cè)出是否支持我們想要錄制的音頻編碼或者視頻編碼。
var types = ["video/webm","audio/webm","video/webm\;codecs=vp8","video/webm\;codecs=daala","video/webm\;codecs=h264","audio/webm\;codecs=opus","video/mpeg"];for (var i in types) {console.log( "Is " + types[i] + " supported? " + (MediaRecorder.isTypeSupported(types[i]) ? "Maybe!" : "Nope :(")); }開始錄制
// 一直錄 mediaRecorder.start(); // 錄制置頂時(shí)間,單位為浩渺 mediaRecorder.start(60000); // 錄制 60秒暫停錄制
mediaRecorder.pause();恢復(fù)錄制
mediaRecorder.resume();結(jié)束錄制
mediaRecorder.stop();定時(shí)獲取錄制數(shù)據(jù)
上面我們監(jiān)聽錄制數(shù)據(jù)回調(diào) ondataavailable,只會(huì)在 stop、pause 時(shí)才會(huì)觸發(fā),如果錄制的時(shí)間很長(zhǎng),那么對(duì)應(yīng)處理的數(shù)據(jù)量也越大,因此,錄制實(shí)例還提供了一個(gè)方法 requestData 方便我們獲取數(shù)據(jù)。
需要注意的是:當(dāng)前錄制狀態(tài)必須為正在錄制中,否則會(huì)報(bào)錯(cuò)。
captureMedia.onclick = function() {mediaRecorder.requestData();// makes snapshot available of data so far// ondataavailable fires, then capturing continues// in new Blob }下載 Or 轉(zhuǎn)碼
下載
// 模擬下載按鈕點(diǎn)擊實(shí)現(xiàn)下載 function download () {const blob = new Blob(recordedBlobs, {type: 'video/webm'});const url = window.URL.createObjectURL(blob);const a = document.createElement('a');a.style.display = 'none';a.href = url;a.download = 'test.webm';document.body.appendChild(a);a.click();setTimeout(() => {document.body.removeChild(a);window.URL.revokeObjectURL(url);}, 100); });轉(zhuǎn)碼
我們可以將數(shù)據(jù)發(fā)送至服務(wù)端(或 OSS),由服務(wù)端轉(zhuǎn)碼,感興趣的同學(xué)也可以去試試 ffmpeg。
Ending
我們可以對(duì)采集或者錄制之后音頻、視頻數(shù)據(jù)進(jìn)行很多處理,例如對(duì)視頻數(shù)據(jù)的處理,感興趣的小伙伴們可以查看以下文章:
一篇前端圖像處理秘籍
前端秘籍之“易容”術(shù)
總結(jié)
以上是生活随笔為你收集整理的web技术支持| Web 客户端实现录音、录像的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 消息队列 MQ 入门理解
- 下一篇: 2008年计算机语言排行榜如下: