MediaRecorderAPI簡介[譯]

NO IMAGE

在網絡上,我們可以從用戶的相機、麥克風甚至桌面捕獲媒體流。我們可以使用這些媒體流通過 WebRTC 進行實時視頻聊天,通過 MediaRecorder API 我們還可以直接在瀏覽器中記錄和保存用戶的音頻或視頻。

下面我們使用 HTML、CSS 和 JavaScript 構建一個簡單的錄音機應用來了解一下 MediaRecorder API 。在撰寫本文時,支持的瀏覽器包括 Firefox,Chrome 和Opera。Edge 和 Safari 後續也會支持。
我們先來創建一個文件夾,再創建一個 HTML 文件及 CSS 文件供我們使用。
開始
要構建此應用,我們只需要一個文本編輯器和一個支持 MediaRecorded API 的瀏覽器。我們將 CSS 文件命名為 web-recorder-style.css

HTML 代碼:

<!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>Web Recorder</title>
<link rel="stylesheet" href="./web-recorder-style.css" />
</head>
<body>
<header>
<h1>Web Recorder</h1>
</header>
<main>
<div class="controls">
<button type="button" id="mic">Get Microphone</button>
<button type="button" id="record" hidden>Record</button>
</div>
<ul id="recordings"></ul>
</main>
<script></script>
</body>
</html>

CSS 代碼:

*{box-sizing: border-box;}
html,
body{min-height: 100vh; margin: 0; padding: 0;}
body{font-family: Helvetica, Arial, sans-serif; color: #0d122b; display: flex; flex-direction: column; padding-left: 1em; padding-right: 1em;}
h1{text-align: center; font-weight: 100;}
header{border-bottom: 1px solid #0d122b; margin-bottom: 2em;}
main{flex-grow: 2;}
.controls{text-align: center;}
button{font-size: 18px; font-weight: 200; padding: 1em; width: 200px; background: transparent; border: 4px solid #f22f46; border-radius: 4px; transition: all 0.4s ease 0s; cursor: pointer; color: #f22f46; margin-bottom: 2em;}
button:hover,
button:focus{background: #f22f46; color: #fff;}
#recordings{list-style-type: none; text-align: center; padding: 0; max-width: 600px; margin: 0 auto;}
#recordings li{display: flex; flex-direction: column; margin-bottom: 1em;}
#recordings audio{border-radius: 4px; margin: 0 auto 0.5em;}
a{color: #0d122b;}
.error{color: #f22f46; text-align: center;}

在瀏覽器打開頁面你會看到如下內容:

MediaRecorderAPI簡介[譯]

現在讓我們來看看 MediaRecorder API。

MediaRecorder API

在使用 MediaRecorder API 時需要有媒體流。我們可以從 <video><audio> 中獲取,也可以通過調用 getUserMedia 來捕獲用戶的攝像頭和麥克風。一旦獲得流信息,便可以初始化 MediaRecorder

在錄音過程中,MediaRecorder 會廣播 dataavailable 事件,並將記錄的數據作為事件的一部分。我們可以監聽這些事件並將數據塊存放在數組中。錄音完成後,可以將數組裡的數據合成 Blob 對象。通過調用 MediaRecorder 對象上的 startstop 來控制錄製的開始和結束。

下面,就讓我們來實踐一下。

getUserMedia

首先,我們與頁面結合起來,通過按鈕來獲取用戶的麥克風媒體流。在頁面 <script> 標籤裡寫上以下內容

window.addEventListener('DOMContentLoaded', () => {
const getMic = document.getElementById('mic');
const recordButton = document.getElementById('record');
const list = document.getElementById('recordings');
});

接下來,我們要檢查瀏覽器是否支持。如果不支持,我們在頁面顯示提示信息。

  window.addEventListener('DOMContentLoaded', () => {
const getMic = document.getElementById('mic');
const recordButton = document.getElementById('record');
const list = document.getElementById('recordings');
if ('MediaRecorder' in window) {
// everything is good, let's go ahead
} else {
renderError("Sorry, your browser doesn't support the MediaRecorder API, so this demo will not work.");
}
});

在事件之後,我們添加 renderErro 方法。

function renderError(message) {
const main = document.querySelector('main');
main.innerHTML = `<div class="error"><p>${message}</p></div>`;
}

如果可以訪問 MediaRecorder ,那麼我們需要麥克風權限來進行錄製。這裡會用到 getUserMedia API。我們不會直接請求麥克風,而是由用戶點擊按鈕來使用麥克風並進行授權。

if ('MediaRecorder' in window) {
getMic.addEventListener('click', async () => {
getMic.setAttribute('hidden', 'hidden');
try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: false
});
console.log(stream);
} catch {
renderError(
'You denied access to the microphone so this demo will not work.'
);
}
});
} else {

調用 navigator.mediaDevices.getUserMedia 將返回一個 promise ,如果用戶允許訪問,我們便可以成功獲取媒體流。

用戶可能會禁止訪問麥克風,我們使用 try/catch 處理異常。如果用戶禁止則會執行 catch 裡的 renderError 方法。

保存文件並在瀏覽器裡打開。點擊「Get Microphone」按鈕。會顯示是否允許使用麥克風的提示,允許後在控件臺會看到打印出的 MediaStream 信息。

MediaRecorderAPI簡介[譯]

錄音

現在我們獲得了麥克風的使用權限,下來我們要定義一些變量供後面使用。首先,MIME 類型使用 auto/webm ,這個類型被瀏覽器廣泛支持。我們還需要創建一個名為 chunks 的數組用來保存錄音中的數據。

MediaRecorder 通過用戶麥克風獲取的媒體流及我們定義的 MIME 類型選項進行初始化。我們把之前的 console.log 替換掉:

try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: false
});
const mimeType = 'audio/webm';
let chunks = [];
const recorder = new MediaRecorder(stream, { type: mimeType });

我們為創建好的 MediaRecorder 設置一些監聽事件。錄音機會廣播很多不同的事件,很多與它本身的交互有關,所以我們可以監聽到開始、暫停、恢復和停止的事件。最主要的事件是 dataavailable,它會在錄音過程中定期廣播,這個事件中包含一段錄音,我們可以把他存到定義好的 chunks 數組中。

const recorder = new MediaRecorder(stream, { type: mimeType });
recorder.addEventListener('dataavailable', event => {
if (typeof event.data === 'undefined') return;
if (event.data.size === 0) return;
chunks.push(event.data);
});
recorder.addEventListener('stop', () => {
const recording = new Blob(chunks, {
type: mimeType
});
renderRecording(recording, list);
chunks = [];
});

我們很快就會實現 renderRecording 方法。現在我們需要實現按鈕的開始和停止。

我們需要取消隱藏錄製按鈕,然後在點擊時啟動或停止錄製,具體取決於錄音機的狀態。代碼如下:

   chunks = [];
});
recordButton.removeAttribute('hidden');
recordButton.addEventListener('click', () => {
if (recorder.state === 'inactive') {
recorder.start();
recordButton.innerText = 'Stop';
} else {
recorder.stop();
recordButton.innerText = 'Record';
}
});

我們將把錄音在 <audio> 元素上呈現並提供下載鏈接,以便用戶可以將他們的錄音下載下來。我們可以使用 URL.createObjectUrl 方法將 Blob 轉成 URL。轉成的 URL 可以做為 <audio>src 及錨點元素的 href 使用。為保證文件能夠下載,我們設置 download 屬性。

renderRecording 方法主要創建 DOM 元素及在錄製時創建文件名。我們將它放到 renderError 方法下面。

  function renderRecording(blob, list) {
const blobUrl = URL.createObjectURL(blob);
const li = document.createElement('li');
const audio = document.createElement('audio');
const anchor = document.createElement('a');
anchor.setAttribute('href', blobUrl);
const now = new Date();
anchor.setAttribute(
'download',
`recording-${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDay().toString().padStart(2, '0')}--${now.getHours().toString().padStart(2, '0')}-${now.getMinutes().toString().padStart(2, '0')}-${now.getSeconds().toString().padStart(2, '0')}.webm`
);
anchor.innerText = 'Download';
audio.setAttribute('src', blobUrl);
audio.setAttribute('controls', 'controls');
li.appendChild(audio);
li.appendChild(anchor);
list.appendChild(li);
}

MediaRecorderAPI簡介[譯]

測試

在瀏覽器中打開頁面並點擊「Get Microphone」按鈕。在權限對話框點擊「允許」,然後點擊「Record」。自己錄一段信息並播放。

WebM 文件

如果您下載了其中一個錄音,您可能會發現沒有能夠播放 WebM 文件的媒體播放器。WebM 是音頻和視頻的開源格式,它主要被瀏覽器所支持。如果你有 VLC 播放器便可以播放,不然的話你就需要將它轉成 MP3 或 WAV 文件。

現在你的瀏覽器變成錄音機了

MediaRecorder API 是瀏覽器新增的強大功能。在本文我們已經看到了它的錄音能力,但它不僅於此。我們的應用沒有保存功能,刷新頁面後錄音會丟失。我們可以使用 IndexedDb 或發送到服務器保存。如果 WebM 不是你想要的格式,可以考慮在前端進行重新編碼,儘管這可能是 WebAssembly 的工作…

這裡有一個 live demoGithub 源碼在這裡

作者:Phil Nash

譯者:Mark Wong

原文:www.twilio.com/blog/medias…

相關文章

Vue實現剪貼板複製功能

Vue+Element二次封裝axios為插件使用

[譯]JavaScript中的頭等函數

Intl.NumberFormat