WebRTC記錄音視頻流(web技術分享)

51CTO博客   發布時間:2022-02-23 10:16:39   作者:anyRTC   我要評論
這篇文章主要給大家介紹了web技術中的WebRTC記錄音視頻流,文章內容圍繞主題展相關資料,需要的小伙伴可以參考一下,希望對你有所幫助

一、監聽開始事件

  • EventTarget.addEventListener() 方法將指定的監聽器注冊到 EventTarget 上,當該對象觸發指定的事件時,指定的回調函數就會被執行。 事件目標可以是一個文檔上的元素 Element,DocumentWindow或者任何其他支持事件的對象 (比如 XMLHttpRequest)。
  • addEventListener()的工作原理是將實現EventListener的函數或對象添加到調用它的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() 會提示用戶給予使用媒體輸入的許可,媒體輸入會產生一個MediaStream,里面包含了請求的媒體類型的軌道。此流可以包含一個視頻軌道(來自硬件或者虛擬視頻源,比如相機、視頻采集設備和屏幕共享服務等等)、一個音頻軌道(同樣來自硬件或虛擬音頻源,比如麥克風、A/D轉換器等等),也可能是其它軌道類型。
  • 它返回一個 Promise 對象,成功后會resolve回調一個 MediaStream 對象。若用戶拒絕了使用權限,或者需要的媒體源不可用,promise會reject回調一個 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 屬性設定或返回一個對象,這個對象提供了一個與HTMLMediaElement關聯的媒體源,這個對象通常是 MediaStream ,但根據規范可以是 MediaSource, Blob 或者 File。
function handleSuccess(stream) {

    recordButton.disabled = false;

    window.stream = stream;

    const gumVideo = document.querySelector('video#gum');

    gumVideo.srcObject = stream;

}

三、錄制媒體流

  • MediaRecorder() 構造函數會創建一個對指定的 MediaStream 進行錄制的 MediaRecorder 對象
  • MediaRecorder.ondataavailable 事件處理程序API處理dataavailable事件,在響應運行代碼Blob數據被提供使用。
  • dataavailableMediaRecorder將媒體數據傳遞到您的應用程序以供使用時,將觸發該事件。數據在包含數據的Blob對象中提供。

這在四種情況下發生:

  • 媒體流結束時,所有尚未傳遞到ondataavailable處理程序的媒體數據都將在單個Blob中傳遞。
  • 當調用MediaRecorder.stop() (en-US)時,自記錄開始或dataavailable事件最后一次發生以來已捕 獲的所有媒體數據都將傳遞到Blob中;此后,捕獲結束。
  • 調用MediaRecorder.requestData() (en-US) dataavailable時,將傳遞自記錄開始或事件最后一次發生以來捕獲的所有媒體數據;然后Blob創建一個新文件,并將媒體捕獲繼續到該blob中。
  • 如果將timeslice屬性傳遞到開始媒體捕獲的MediaRecorder.start() (en-US)方法中,dataavailable則每timeslice毫秒觸發一次事件。這意味著每個Blob都有特定的持續時間(最后一個Blob除外,后者可能更短,因為它將是自上次事件以來剩下的所有東西)。
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('創建MediaRecorder時異常:', 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() 靜態方法會創建一個 DOMString,其中包含一個表示參數中給出的對象的URL。這個 URL 的生命周期和創建它的窗口中的 document 綁定。這個新的URL 對象表示指定的 File 對象或 Blob 對象。
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('創建MediaRecorder時異常:', 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);

});

到此這篇關于WebRTC記錄音視頻流(web技術分享)的文章就介紹到這了,更多相關WebRTC記錄音視頻流內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章,希望大家以后多多支持腳本之家!

相關文章

  • 響應式Web之流式網格系統

    這篇文章主要為大家詳細介紹了響應式Web之流式網格系統的相關資料,感興趣的小伙伴們可以參考一下
    2016-07-04

最新評論

免费人成视频在线观看