前端錄屏黑科技:幾行 JS 代碼就能實(shí)現(xiàn)!
在過去,想要在網(wǎng)頁上實(shí)現(xiàn)“錄屏”功能,往往需要借助復(fù)雜的瀏覽器插件、桌面應(yīng)用或者付費(fèi)的第三方服務(wù)。這不僅增加了用戶的操作成本,也給開發(fā)者帶來了不小的挑戰(zhàn)。但如今,隨著 Web API 的不斷發(fā)展,一個(gè)強(qiáng)大的原生工具已經(jīng)悄然來到了我們身邊——MediaRecorder API。

1. 什么是 MediaRecorder API?
MediaRecorder 是 WebRTC(Web Real-Time Communication)技術(shù)棧的一部分。簡(jiǎn)單來說,它是一個(gè)可以接收媒體流(MediaStream),并將其編碼成特定格式(如 WebM 或 MP4),然后以數(shù)據(jù)塊(Blobs)的形式輸出的接口。
這里的媒體流來源非常廣泛,可以是:
- 用戶的攝像頭和麥克風(fēng) (navigator.mediaDevices.getUserMedia)
- 用戶的屏幕、窗口或?yàn)g覽器標(biāo)簽頁 (navigator.mediaDevices.getDisplayMedia)
- 網(wǎng)頁中的 <video> 或 <audio> 元素
- 甚至是一個(gè)動(dòng)態(tài)生成的 Canvas 畫布
而我們要實(shí)現(xiàn)的“錄屏”功能,正是利用了第二種來源——getDisplayMedia API。
2. 實(shí)現(xiàn)一個(gè)基礎(chǔ)的錄屏功能:三步走
實(shí)現(xiàn)一個(gè)基礎(chǔ)的錄屏功能,核心邏輯可以分為三步:獲取流 -> 錄制流 -> 處理結(jié)果。
第一步:獲取屏幕共享的媒體流
首先,我們需要向用戶申請(qǐng)權(quán)限,以獲取他們屏幕內(nèi)容的媒體流。getDisplayMedia API 會(huì)彈出一個(gè)瀏覽器原生的對(duì)話框,讓用戶選擇要共享的屏幕、窗口或標(biāo)簽頁。
// 1. 獲取屏幕共享流的函數(shù)
async function getScreenStream() {
try {
// 提示用戶選擇要共享的屏幕或窗口
const stream = await navigator.mediaDevices.getDisplayMedia({
video: true, // 必須,表示我們要捕獲視頻
audio: true // 可選,表示我們想同時(shí)捕獲該屏幕播放的音頻
});
return stream;
} catch (error) {
console.error("獲取屏幕共享失敗:", error);
alert("您取消了屏幕共享或發(fā)生了錯(cuò)誤。");
return null;
}
}注意:getDisplayMedia 必須由用戶交互(如點(diǎn)擊按鈕)觸發(fā),否則瀏覽器會(huì)出于安全考慮而阻止它。
第二步:創(chuàng)建 MediaRecorder 實(shí)例并開始錄制
獲取到 MediaStream 對(duì)象后,我們就可以用它來創(chuàng)建一個(gè) MediaRecorder 實(shí)例。

第三步:停止錄制并處理結(jié)果
當(dāng)用戶點(diǎn)擊停止按鈕或關(guān)閉屏幕共享時(shí),我們調(diào)用 mediaRecorder.stop()。錄制的數(shù)據(jù)塊會(huì)匯集在 recordedChunks 數(shù)組中,我們只需將它們整合成一個(gè) Blob 對(duì)象,就可以生成最終的視頻文件。
// 3. 停止錄制的函數(shù)
function stopRecording() {
if (mediaRecorder && mediaRecorder.state !== 'inactive') {
mediaRecorder.stop();
}
}
// 4. 處理錄制結(jié)果
function handleRecordingStop() {
// 將所有數(shù)據(jù)塊合并成一個(gè) Blob
const recordedBlob = new Blob(recordedChunks, { type: 'video/webm' });
// 創(chuàng)建一個(gè) URL,用于預(yù)覽或下載
const videoUrl = URL.createObjectURL(recordedBlob);
// 例如,創(chuàng)建一個(gè)下載鏈接
const downloadLink = document.createElement('a');
downloadLink.href = videoUrl;
downloadLink.download = `recording-${new Date().toISOString()}.webm`;
downloadLink.textContent = '下載錄屏';
document.body.appendChild(downloadLink);
// 或者創(chuàng)建一個(gè) video 元素進(jìn)行預(yù)覽
const previewVideo = document.createElement('video');
previewVideo.src = videoUrl;
previewVideo.controls = true;
document.body.appendChild(previewVideo);
// 清空數(shù)據(jù)塊,為下一次錄制做準(zhǔn)備
recordedChunks = [];
}將這三步與 UI 按鈕(開始、停止)結(jié)合起來,一個(gè)完整的網(wǎng)頁錄屏應(yīng)用就誕生了!
MediaRecorder 的應(yīng)用場(chǎng)景遠(yuǎn)不止于此,比如可以用它來實(shí)現(xiàn):用戶反饋與 Bug 復(fù)現(xiàn)、在線教育與演示等。
3. 注意事項(xiàng)與優(yōu)秀實(shí)踐
- 瀏覽器兼容性:MediaRecorder API 在現(xiàn)代瀏覽器(Chrome, Firefox, Edge, Safari)中得到了廣泛支持,但仍需檢查兼容性,并為不支持的瀏覽器提供優(yōu)雅降級(jí)。
- MIME 類型:不同的瀏覽器支持不同的 mimeType。可以使用 MediaRecorder.isTypeSupported() 方法來檢查支持情況,并選擇最合適的格式。video/webm 是最廣泛支持的。
- 用戶授權(quán):始終在用戶明確操作后才調(diào)用 getDisplayMedia,并清晰地告知用戶為何需要此權(quán)限。
- 資源管理:錄制完成后,記得使用 URL.revokeObjectURL() 釋放由 createObjectURL 創(chuàng)建的 URL,避免內(nèi)存泄漏。同時(shí),確保停止媒體流(stream.getTracks().forEach(track => track.stop())),關(guān)閉攝像頭或屏幕共享的指示燈。
- 性能考量:長(zhǎng)時(shí)間或高分辨率的錄制會(huì)消耗大量?jī)?nèi)存和 CPU。對(duì)于需要上傳的場(chǎng)景,可以考慮分片上傳,而不是等待整個(gè)文件錄制完畢。


























