web技術分享| WebRTC記錄音影片流
-
EventTarget.addEventListener() 方法將指定的監聽器註冊到
EventTarget
上,當該物件觸發指定的事件時,指定的回撥函式就會被執行。 事件目標可以是一個文件上的元素Element
,Document
和Window
或者任何其他支援事件的物件 (比如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
資料被提供使用。 -
dataavailable
當MediaRecorder將媒體資料傳遞到您的應用程式以供使用時,將觸發該事件。資料在包含資料的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.>
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.>
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);
});
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70013909/viewspace-2856074/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- WebRTC錄音功能 | 掘金技術徵文Web
- web技術支援| Web 客戶端實現錄音、錄影Web客戶端
- WebRTC 音訊抗弱網技術(上)Web音訊
- WebRTC 音訊抗弱網技術(下)Web音訊
- web技術分享| WebRTC控制攝像機平移、傾斜和縮放Web
- 技術分享| anyRTC音影片與微信小程式互通實踐微信小程式
- 基於webRTC技術 音訊和視訊,IM解Web音訊
- 音影片技術原理及應用
- fms 流媒體影片技術介紹
- 音影片處理技術中的IP組播技術
- 技術分享| 影片傳輸Simulcast與SvcAST
- 技術分享| anyRTC 影片監控融合方案
- 探索基於WebRTC的有感錄屏技術開發流程Web
- WebRTC本地分享螢幕,錄製螢幕Web
- 技術點滴記錄
- 技術問題記錄
- Android 聲網音視訊體驗記錄|掘金技術徵文Android
- web技術分享| 虛擬列表實現Web
- 技術乾貨 | WebRTC 技術解析之 Android VDMWebAndroid
- 淺析WebRTC技術在智慧園區影片管理場景中的應用Web
- 技術分享:記憶體管理記憶體
- apache kafka技術分享系列(目錄索引)ApacheKafka索引
- WebRTC環境搭建| 掘金技術徵文Web
- ibeacon 技術記錄
- web前端技術分享Electron之Renderer Process APIWeb前端API
- web前端技術分享Electron之IPC 通訊Web前端
- web前端技術分享:常用JavaScript框架有哪些?Web前端JavaScript框架
- UDP實現音訊影片流傳輸UDP音訊
- 技術分享| 快對講影片排程功能說明
- 實時音視訊互動系列(下):基於 WebRTC 技術的實戰解析Web
- Flutter之聲網Agore實現音訊體驗記錄 | 掘金技術徵文FlutterGo音訊
- WebRTC與音訊音量Web音訊
- 技術分享| 小程式實現音視訊通話
- web前端技術分享之頁面元素水平居中Web前端
- 記錄兩個群音影片開源框架LiveKit和mediasoup框架
- 公司技術大咖分享會--後記
- 我用ChatGPT做WebRTC音影片效能最佳化,主打一個高效ChatGPTWeb
- web前端技術分享:使用react實現簡易路由Web前端React路由