發布日期: 2026年6月30日
難度: 中高級
所需時間: 約 35-45 分鐘
前言
不論是要製作線上教學影片、錄製軟體報錯(Bug)畫面,還是存取網頁視訊會議,螢幕錄影已經是日常不可或缺的功能。過去,我們可能需要安裝 OBS 等專業錄影軟體,或是安裝瀏覽器擴充外掛。
這篇文章將手把手帶領大家使用 HTML5 原生的 Screen Capture API 與 MediaRecorder API,開發出一個完全免安裝外掛、無廣告、資料純本地端處理(無隱私外洩風險),且同時支援麥克風與系統音訊雙重混音錄製的個人專屬「線上螢幕錄影工具」!
核心技術:HTML5 媒體串流 API
要在瀏覽器中完成錄影,主要依賴以下三個核心 API:
1. navigator.mediaDevices.getDisplayMedia():
- 這是原生的螢幕分享 API。調用時,瀏覽器會安全地跳出視窗,詢問使用者要錄製「整個螢幕」、「特定應用程式視窗」或是「單一瀏覽器分頁」。
2. navigator.mediaDevices.getUserMedia():
- 用於取得使用者的麥克風音訊(人聲輸入)。
3. MediaRecorder:
- 負責將獲取到的視訊與音訊媒體串流(MediaStream)打包編碼,並即時切片成二進位數據塊(Chunks),最後整合成影片檔案供下載。
第一步:規劃使用者介面 (HTML5 + CSS)
我們打造出具備毛玻璃(Glassmorphism)與霓虹發光感(Pulsing Glow)的現代排版:
- 左側設定面板:包含音訊切換開關、錄影狀態顯示、電子計時器(Timer)、以及開始/暫停/停止按鈕。
- 右側視訊工作區:包含即時影像預覽器與未錄製時的動態 Placeholder。
<div class="app-container">
<!-- 左側錄影控制台 -->
<div class="card controls-panel">
<h2><i class="fa-solid fa-sliders"></i> 錄製設定</h2>
<!-- 麥克風與系統音訊開關 -->
<div class="dashboard-info">
<span class="status-dot" id="status-dot"></span>
<div class="dashboard-timer" id="timer">00:00:00</div>
</div>
<!-- 錄影控制按鈕群 -->
</div>
<!-- 右側預覽播放器 -->
<div class="card video-container-wrapper">
<video id="video-preview" autoplay playsinline muted></video>
</div>
</div>
第二步:混音技術 (Audio Mixing)
在進行螢幕錄影時,常見的需求是同時錄製電腦聲音(如遊戲音效、分頁音樂)與我們講話的聲音(麥克風)。
這需要使用 HTML5 的 AudioContext 來進行合流混音,否則錄影軌道會因為衝突而只能保留其中一種聲音:
// 1. 取得麥克風人聲串流
const micStream = await navigator.mediaDevices.getUserMedia({ audio: true });
// 2. 取得螢幕與系統音效串流
const screenStream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: true });
// 3. 建立 AudioContext 並進行混音
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
const destination = audioCtx.createMediaStreamDestination();
// 將麥克風聲音連接至混音器
const micSource = audioCtx.createMediaStreamSource(micStream);
micSource.connect(destination);
// 將系統/分頁聲音連接至混音器
const screenSource = audioCtx.createMediaStreamSource(screenStream);
screenSource.connect(destination);
// 4. 組合最終包含視訊軌道與混音後音訊軌道的 Stream
const videoTrack = screenStream.getVideoTracks()[0];
const mixedAudioTrack = destination.stream.getAudioTracks()[0];
const combinedStream = new MediaStream([videoTrack, mixedAudioTrack]);
這段混音架構能完美合併麥克風音訊與分頁音訊,讓錄製好的影片同時擁有環境人聲與系統伴奏。
第三步:使用 MediaRecorder 錄製影片
獲得 combinedStream 後,即可開始初始化 MediaRecorder。我們優先使用編碼效率高、解析度出色的 WebM (VP9/Opus) 編碼:
let recordedChunks = [];
let mediaRecorder = null;
// 優先選用高壓縮率的 VP9,不支援則退回預設 WebM
let options = { mimeType: 'video/webm;codecs=vp9,opus' };
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
options = { mimeType: 'video/webm' };
}
mediaRecorder = new MediaRecorder(combinedStream, options);
// 每秒鐘即時收集一次錄影的數據碎片
mediaRecorder.ondataavailable = function(e) {
if (e.data && e.data.size > 0) {
recordedChunks.push(e.data);
}
};
// 停止錄影時的處理邏輯
mediaRecorder.onstop = function() {
// 1. 關閉所有媒體軌道以釋放攝影機、螢幕分享與麥克風佔用
screenStream.getTracks().forEach(t => t.stop());
if (micStream) micStream.getTracks().forEach(t => t.stop());
// 2. 將收集到的二進位碎片合併為一個影片 Blob
const blob = new Blob(recordedChunks, { type: 'video/webm' });
const videoURL = URL.createObjectURL(blob);
// 3. 將預覽器改為播放模式,允許使用者即時拉動進度條與監聽聲音
videoPreview.srcObject = null;
videoPreview.src = videoURL;
videoPreview.controls = true;
videoPreview.muted = false; // 允許播放聲音
};
// 開始錄影!
mediaRecorder.start(1000);
第四步:監聽瀏覽器「停止分享」按鈕
這是一個非常重要的細節。當我們開始錄影時,瀏覽器底部會跳出一個「停止分享」的系統浮動吧。如果使用者點選了它,我們必須即時捕捉到這個動作並主動觸存影片,否則錄影會當掉:
// 監聽螢幕視訊軌道的 ended 事件
videoTrack.onended = function() {
stopRecording(); // 主動呼叫停止錄製邏輯,確保已錄內容不遺失
};
第五步:Nginx 部署與無快取策略
為了能讓工具在生產環境中秒速加載且即時更新,我們將應用程式託管在 Nginx 伺服器的 /recorder/ 資料夾下,並設定禁止快取標頭:
# 停用螢幕錄影等工具的快取,確保版本迭代即時更新
location ~* ^/(collage|qrcode|cropper|cropper-circle|recorder)/.*\.html$ {
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
expires -1;
}
這能保證使用者每次造訪工具,載入的都是瀏覽器最精準、修復過後的程式碼版本。
結語
利用原生 HTML5 API 的強大能力,我們不需要依賴任何第三方伺服器,只花費大約 200 行代碼就在客戶端完成了螢幕捕獲、麥克風合流、即時編碼與影片導出。
- ❌ 拒絕浮水印:完全開源無限制,導出影片乾淨無瑕。
- ❌ 拒絕隱私外洩:影片編碼完全在您本機瀏覽器沙盒中完成,沒有任何資料會上傳到雲端,隱私極致安全。
- ⚡ 多功能控制:支援音訊自選開關、即時解析度反饋與時間儀表板。
*歡迎前往我們的產生器頁面測試使用:(https://stillbuilding.life/recorder/)*



