在互動性高的應用程式中,讓使用者可以自由紀錄畫面,是必備的元素之一。這不僅提供了用戶便捷的錄影功能,也讓開發者可以輕鬆製作展示影片。無論是創建教學影片還是捕捉用戶操作、上傳到Youtube,錄影功能都能大大提升應用的靈活性和實用性。這篇文章將展示如何在 React 應用中實現一個簡單而功能強大的錄影按鈕。
我們將實現一個 RecordBtn 元件,這個元件提供了開始和停止錄影的功能。該按鈕會在點擊時切換錄影狀態,並能捕捉畫面和音訊流。最後生成 MP4 格式的影片並下載。
核心功能實現:
在使用這個元件時,把想要錄影的 canvas 和 audio 對象,作為參數傳入:
const canvas = useRef(null);
const audio = useRef(null);
return (
<section className="section" id={uniqueID}>
<canvas ref={canvas}
width={min * ratio}
height={ratio * min * ratio}>
</canvas>
{/* ...... */}
<RecordBtn canvas={canvas} audio={audio}></RecordBtn>
</section>
)
import downloadMedia from '../js/downloadMedia';
const media = {};
這個方法其實也適用於 audio 或 video 元素,可以根據需求擴展,讓它不只串流canvas的內容。
const chunks = [];
media.stream = canvas.current.captureStream(60); // 設定為 60 fps
我們嘗試裁剪原本的串流,只保留視訊,這會導致原本的音訊丟失,不過,canvas本來就沒有音頻,所以可以放心的創建一個新的 MediaStream,用來合併音訊、視訊。
if(audio?.current){
media.audio = audio.current;
media.audio.play();
media.audioStream = media.audio.captureStream();
media.stream = new MediaStream([
...media.stream.getVideoTracks(),
...media.audioStream.getAudioTracks()
]);
}
media.recorder = new MediaRecorder(media.stream, { mimeType: "video/mp4; codecs=vp9" });
media.recorder.ondataavailable = (evt) => { chunks.push(evt.data); };
media.recorder.onstop = () => { downloadMedia(chunks); };
media.recorder.start(1000);
還記得我們最初提到的 downloadMedia 函式嗎?讓我們把它完成:
function downloadMedia(data){
const blob = new Blob(data, {type: "video/mp4" });
const recording_url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = recording_url;
a.download = "video.mp4";
a.click();
}
不過,考慮到相容性,可能還需要加上特殊作法,詳細可以參考我查到的stackoverflow討論串
//......
a.style = "display: none;";
document.body.appendChild(a);
a.click();
setTimeout(() => {
URL.revokeObjectURL(recording_url);
document.body.removeChild(a);
}, 0);
這樣的設計讓用戶可以方便地錄製畫面和音訊,並將錄製的內容保存到本地,進一步增強了應用程式的互動性和展示效果。
如果感興趣,可以參考 Github 上的原始碼:
RecordBtn.jsx
這次也留給大家一個問題:你會如何擴展這個錄影功能,例如加入更多的錄影選項或提高錄影品質?