WebRTC記錄音視頻流(web技術(shù)分享)
51CTO博客 發(fā)布時(shí)間:2022-02-23 10:16:39 作者:anyRTC
我要評(píng)論

這篇文章主要給大家介紹了web技術(shù)中的WebRTC記錄音視頻流,文章內(nèi)容圍繞主題展相關(guān)資料,需要的小伙伴可以參考一下,希望對(duì)你有所幫助
一、監(jiān)聽開始事件
- EventTarget.addEventListener() 方法將指定的監(jiān)聽器注冊(cè)到
EventTarget
上,當(dāng)該對(duì)象觸發(fā)指定的事件時(shí),指定的回調(diào)函數(shù)就會(huì)被執(zhí)行。 事件目標(biāo)可以是一個(gè)文檔上的元素Element
,Document
和Window
或者任何其他支持事件的對(duì)象 (比如 XMLHttpRequest)。 addEventListener()
的工作原理是將實(shí)現(xiàn)EventListener的函數(shù)或?qū)ο筇砑拥秸{(diào)用它的EventTarget上的指定事件類型的事件偵聽器列表中。
document.querySelector('button#start').addEventListener('click', async () => { document.querySelector('button#start').disabled = true; const constraints = { audio: {}, video: { width: 1280, height: 720 } }; await init(constraints); });
二、獲取音視頻軌道
MediaDevices.getUserMedia()
會(huì)提示用戶給予使用媒體輸入的許可,媒體輸入會(huì)產(chǎn)生一個(gè)MediaStream,里面包含了請(qǐng)求的媒體類型的軌道。此流可以包含一個(gè)視頻軌道(來自硬件或者虛擬視頻源,比如相機(jī)、視頻采集設(shè)備和屏幕共享服務(wù)等等)、一個(gè)音頻軌道(同樣來自硬件或虛擬音頻源,比如麥克風(fēng)、A/D轉(zhuǎn)換器等等),也可能是其它軌道類型。- 它返回一個(gè) Promise 對(duì)象,成功后會(huì)resolve回調(diào)一個(gè)
MediaStream
對(duì)象。若用戶拒絕了使用權(quán)限,或者需要的媒體源不可用,promise會(huì)reject回調(diào)一個(gè) PermissionDeniedError 或者NotFoundError
。
async function init(constraints) { try { const stream = await navigator.mediaDevices.getUserMedia(constraints); handleSuccess(stream); } catch (e) { console.error('navigator.getUserMedia error:', e); } }
HTMLMediaElement
接口的 srcObject 屬性設(shè)定或返回一個(gè)對(duì)象,這個(gè)對(duì)象提供了一個(gè)與HTMLMediaElement關(guān)聯(lián)的媒體源,這個(gè)對(duì)象通常是 MediaStream ,但根據(jù)規(guī)范可以是 MediaSource, Blob 或者 File。
function handleSuccess(stream) { recordButton.disabled = false; window.stream = stream; const gumVideo = document.querySelector('video#gum'); gumVideo.srcObject = stream; }
三、錄制媒體流
MediaRecorder()
構(gòu)造函數(shù)會(huì)創(chuàng)建一個(gè)對(duì)指定的MediaStream
進(jìn)行錄制的MediaRecorder
對(duì)象MediaRecorder.ondataavailable
事件處理程序API處理dataavailable
事件,在響應(yīng)運(yùn)行代碼Blob數(shù)據(jù)被提供使用。dataavailable
當(dāng)MediaRecorder
將媒體數(shù)據(jù)傳遞到您的應(yīng)用程序以供使用時(shí),將觸發(fā)該事件。數(shù)據(jù)在包含數(shù)據(jù)的Blob對(duì)象中提供。
這在四種情況下發(fā)生:
- 媒體流結(jié)束時(shí),所有尚未傳遞到
ondataavailable
處理程序的媒體數(shù)據(jù)都將在單個(gè)Blob中傳遞。 - 當(dāng)調(diào)用
MediaRecorder.stop() (en-US)
時(shí),自記錄開始或dataavailable事件最后一次發(fā)生以來已捕 獲的所有媒體數(shù)據(jù)都將傳遞到Blob中;此后,捕獲結(jié)束。 - 調(diào)用
MediaRecorder.requestData() (en-US) dataavailable
時(shí),將傳遞自記錄開始或事件最后一次發(fā)生以來捕獲的所有媒體數(shù)據(jù);然后Blob創(chuàng)建一個(gè)新文件,并將媒體捕獲繼續(xù)到該blob中。 - 如果將
timeslice
屬性傳遞到開始媒體捕獲的MediaRecorder.start() (en-US)
方法中,dataavailable則每timeslice毫秒觸發(fā)一次事件。這意味著每個(gè)Blob都有特定的持續(xù)時(shí)間(最后一個(gè)Blob除外,后者可能更短,因?yàn)樗鼘⑹亲陨洗问录詠硎O碌乃袞|西)。
let mediaRecorder; const recordButton = document.querySelector('button#record'); recordButton.addEventListener('click', () => { if (recordButton.textContent === '開始記錄') { startRecording(); } else { stopRecording(); recordButton.textContent = '開始記錄'; playButton.disabled = false; } }); function startRecording() { recordedBlobs = []; try { mediaRecorder = new MediaRecorder(window.stream); } catch (e) { console.error('創(chuàng)建MediaRecorder時(shí)異常:', e); } recordButton.textContent = '停止記錄'; playButton.disabled = true; mediaRecorder.ondataavailable = handleDataAvailable; mediaRecorder.start(); } function stopRecording() { mediaRecorder.stop(); } function handleDataAvailable(event) { if (event.data && event.data.size > 0) { recordedBlobs.push(event.data); } }
四、播放媒體流
URL.createObjectURL()
靜態(tài)方法會(huì)創(chuàng)建一個(gè)DOMString
,其中包含一個(gè)表示參數(shù)中給出的對(duì)象的URL。這個(gè) URL 的生命周期和創(chuàng)建它的窗口中的 document 綁定。這個(gè)新的URL 對(duì)象表示指定的 File 對(duì)象或 Blob 對(duì)象。
let recordedBlobs; const recordedVideo = document.querySelector('video#recorded'); const playButton = document.querySelector('button#play'); playButton.addEventListener('click', () => { const superBuffer = new Blob(recordedBlobs, { type: 'video/webm' }); recordedVideo.src = null; recordedVideo.srcObject = null; recordedVideo.src = window.URL.createObjectURL(superBuffer); recordedVideo.controls = true; recordedVideo.play(); });
HTML:
<link rel="stylesheet" href="./index.css"> <video id="gum" autoplay></video> <video id="recorded"></video> <div> <button id="start">開始</button> <button id="record" disabled>開始記錄</button> <button id="play" disabled>Play</button> </div> <script src="./index.js"></script>
CSS:
button { margin: 0 3px 10px 0; padding-left: 2px; padding-right: 2px; width: 99px; } button:last-of-type { margin: 0; } video { vertical-align: top; --width: 25vw; width: var(--width); height: calc(var(--width) * 0.5625); } video:last-of-type { margin: 0 0 20px 0; } video#gumVideo { margin: 0 20px 20px 0; }
JavaScript:
let mediaRecorder; let recordedBlobs; const recordedVideo = document.querySelector('video#recorded'); const recordButton = document.querySelector('button#record'); recordButton.addEventListener('click', () => { if (recordButton.textContent === '開始記錄') { startRecording(); } else { stopRecording(); recordButton.textContent = '開始記錄'; playButton.disabled = false; } }); const playButton = document.querySelector('button#play'); playButton.addEventListener('click', () => { const superBuffer = new Blob(recordedBlobs, { type: 'video/webm' }); recordedVideo.src = null; recordedVideo.srcObject = null; recordedVideo.src = window.URL.createObjectURL(superBuffer); recordedVideo.controls = true; recordedVideo.play(); }); function handleDataAvailable(event) { if (event.data && event.data.size > 0) { recordedBlobs.push(event.data); } } function startRecording() { recordedBlobs = []; try { mediaRecorder = new MediaRecorder(window.stream); } catch (e) { console.error('創(chuàng)建MediaRecorder時(shí)異常:', e); } recordButton.textContent = '停止記錄'; playButton.disabled = true; mediaRecorder.ondataavailable = handleDataAvailable; mediaRecorder.start(); } function stopRecording() { mediaRecorder.stop(); } function handleSuccess(stream) { recordButton.disabled = false; window.stream = stream; const gumVideo = document.querySelector('video#gum'); gumVideo.srcObject = stream; } async function init(constraints) { try { const stream = await navigator.mediaDevices.getUserMedia(constraints); handleSuccess(stream); } catch (e) { console.error('navigator.getUserMedia error:', e); } } document.querySelector('button#start').addEventListener('click', async () => { document.querySelector('button#start').disabled = true; const constraints = { audio: {}, video: { width: 1280, height: 720 } }; await init(constraints); });
到此這篇關(guān)于WebRTC記錄音視頻流(web技術(shù)分享)的文章就介紹到這了,更多相關(guān)WebRTC記錄音視頻流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
相關(guān)文章
響應(yīng)式Web之流式網(wǎng)格系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了響應(yīng)式Web之流式網(wǎng)格系統(tǒng)的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-07-04