在網絡上,咱們能夠從用戶的相機、麥克風甚至桌面捕獲媒體流。咱們可使用這些媒體流經過 WebRTC 進行實時視頻聊天,經過 MediaRecorder API 咱們還能夠直接在瀏覽器中記錄和保存用戶的音頻或視頻。css
下面咱們使用 HTML、CSS 和 JavaScript 構建一個簡單的錄音機應用來了解一下 MediaRecorder API 。在撰寫本文時,支持的瀏覽器包括 Firefox,Chrome 和Opera。Edge 和 Safari 後續也會支持。 咱們先來建立一個文件夾,再建立一個 HTML 文件及 CSS 文件供咱們使用。 開始 要構建此應用,咱們只須要一個文本編輯器和一個支持 MediaRecorded API 的瀏覽器。咱們將 CSS 文件命名爲 web-recorder-style.css
。html
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 代碼:git
*{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;}
複製代碼
在瀏覽器打開頁面你會看到以下內容:github
如今讓咱們來看看 MediaRecorder API。web
在使用 MediaRecorder API 時須要有媒體流。咱們能夠從 <video>
或 <audio>
中獲取,也能夠經過調用 getUserMedia
來捕獲用戶的攝像頭和麥克風。一旦得到流信息,即可以初始化 MediaRecorder
。api
在錄音過程當中,MediaRecorder
會廣播 dataavailable
事件,並將記錄的數據做爲事件的一部分。咱們能夠監聽這些事件並將數據塊存放在數組中。錄音完成後,能夠將數組裏的數據合成 Blob
對象。經過調用 MediaRecorder
對象上的 start
和 stop
來控制錄製的開始和結束。數組
下面,就讓咱們來實踐一下。promise
首先,咱們與頁面結合起來,經過按鈕來獲取用戶的麥克風媒體流。在頁面 <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
信息。
如今咱們得到了麥克風的使用權限,下來咱們要定義一些變量供後面使用。首先,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);
}
複製代碼
在瀏覽器中打開頁面並點擊「Get Microphone」按鈕。在權限對話框點擊「容許」,而後點擊「Record」。本身錄一段信息並播放。
若是您下載了其中一個錄音,您可能會發現沒有可以播放 WebM 文件的媒體播放器。WebM 是音頻和視頻的開源格式,它主要被瀏覽器所支持。若是你有 VLC 播放器即可以播放,否則的話你就須要將它轉成 MP3 或 WAV 文件。
MediaRecorder
API 是瀏覽器新增的強大功能。在本文咱們已經看到了它的錄音能力,但它不只於此。咱們的應用沒有保存功能,刷新頁面後錄音會丟失。咱們可使用 IndexedDb 或發送到服務器保存。若是 WebM 不是你想要的格式,能夠考慮在前端進行從新編碼,儘管這多是 WebAssembly 的工做...
這裏有一個 live demo。Github 源碼在這裏。
做者:Phil Nash
譯者:Mark Wong