TL;DR
MediaStreamの取得
// mediaStreamの取得(video/canvas)
stream = document.querySelector('canvas').captureStream()
// mediaStreamの取得(画面キャプチャー)
stream = await navigator.mediaDevices.getDisplayMedia()
// mediaStreamの取得(Webカメラ)
stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true })
MediaRecorderの作成
function processMediaWhenStop(stream, onStop) {
const mime = MediaRecorder.isTypeSupported("video/webm; codecs=vp9") ? "video/webm; codecs=vp9" : "video/webm";
const mediaRecorder = new MediaRecorder(stream, { mimeType: mime })
// start record
const chunks = []
mediaRecorder.addEventListener('dataavailable', e => chunks.push(e.data))
// call on stop callback
mediaRecorder.addEventListener('stop', async () => {
const blob = new Blob(chunks, { type: chunks[0].type })
await onStop(blob)
})
return mediaRecorder
}
onStop Callbackの一例(ファイルとしてダウンロード)
function downloadWebm(blob) {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'video.webm';
a.click();
}
おまけ: FFmpegで.mp4
に変換
$ ffmpeg -i video.webm -c:v copy -c:a copy video.mp4
はじめに
昔JS直書きでGoogle DoodleのCanvasを録画してGifにという記事を書きましたが、最近はより汎用性の高い方法を見つかりました。
操作Demo
Three.jsのサンプルを拝借いたします。
関数投入
processMediaWhenStop()
とdownloadWebm()
を先に投入します。
録画開始
該当するcanvasまたはvideoを特定出来たら、下記のコードを一気にコンソールに投入します。
stream = document.querySelector('canvas').captureStream()
recorder = processMediaWhenStop(stream, downloadWebm)
recorder.start() // 録画開始
録画終了&ファイルDL
手動でrecorder.stop()
をCallすれば、勝手に録画が停止し、video.webm
というファイルがダウンロードされます。
必要であれば、MP4に変換
$ ffmpeg -i video.webm -c:v copy -c:a copy video.mp4
上記コマンドで一瞬で出来ます。
ffmpeg version 6.0 Copyright (c) 2000-2023 the FFmpeg developers
built with Apple clang version 13.0.0 (clang-1300.0.29.30)
configuration: --prefix=/usr/local/Cellar/ffmpeg/6.0 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox
libavutil 58. 2.100 / 58. 2.100
libavcodec 60. 3.100 / 60. 3.100
libavformat 60. 3.100 / 60. 3.100
libavdevice 60. 1.100 / 60. 1.100
libavfilter 9. 3.100 / 9. 3.100
libswscale 7. 1.100 / 7. 1.100
libswresample 4. 10.100 / 4. 10.100
libpostproc 57. 1.100 / 57. 1.100
Input #0, matroska,webm, from 'video.webm':
Metadata:
encoder : Chrome
Duration: N/A, start: 0.000000, bitrate: N/A
Stream #0:0(eng): Video: vp9 (Profile 0), yuv420p(tv), 1039x860, SAR 1:1 DAR 1039:860, 1k tbr, 1k tbn (default)
Metadata:
alpha_mode : 1
Output #0, mp4, to 'video.mp4':
Metadata:
encoder : Lavf60.3.100
Stream #0:0(eng): Video: vp9 (Profile 0) (vp09 / 0x39307076), yuv420p(tv), 1039x860 [SAR 1:1 DAR 1039:860], q=2-31, 1k tbr, 16k tbn (default)
Metadata:
alpha_mode : 1
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
frame= 580 fps=0.0 q=-1.0 Lsize= 1833kB time=00:00:21.70 bitrate= 691.7kbits/s speed=2.2e+03x
video:1825kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.397173%
余談1: FFmpeg.wasmについて
理論上FFmpeg.wasmを活用すれば、ブラウザのみでMP4ファイルの出力が可能ですが、実際やってみたら以下の問題が発覚しました。
1、 FFmpeg.wasmを利用するには、該当ページのHEADに下記の記述がないと動きません。
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
なので、そこら中のサイトですぐでも録画したいことは出来ないです。
2、FFmpeg.wasmの変換速度が恐ろしく遅いです。
先ほどのvideo.webm
をコンソール版のFFmpegで変換する際の速度は、2200倍速でした。実際の所要時間も一瞬でした。
しかしFFmpeg.wasmだと、約0.02倍速でした(つまり1分間の動画を変換するには、50倍の50分間が必要です)。
余談2: GIFを出力
FFmpegはGIF画像としての出力も可能ですが、webm
ファイルから直接変換はできないみたいです。
一回mp4
ファイルに変換してから、下記のコマンドで変換すればできます。
ffmpeg -i video.mp4 -r 5 -vf scale=640:-1 video.gif
詳しい設定はこちらの記事を読んでください: FFmpegで動画をGIFに変換