コンテンツへスキップ

video/audioタグの映像を記録するRecording a media elementの紹介

by : 2018/08/07

現在のHTML5ではvideoやaudioタグを使って動画、音楽などを再生できるようになっています。しかし、これらのデータはストリーミングで流したり、getUserMediaを使って取得することしかできませんでした。

そこで登場したのが Recording a media elementです。これは video/audioタグの内容をレコーディングし、ファイルとしてダウンロードもできるAPIになります。

使い方

まずHTMLを記述します。videoタグを使います。 #startButton を押すとWebカメラの映像をストリーミングで流します。


<div class="left">
<button id="startButton">
開始
</button>
<h2>プレビュー</h2>
<video id="preview" width="160" height="120" autoplay muted></video>
</div>

view raw

index.html

hosted with ❤ by GitHub

さらに記録した内容を表示するDOMを用意します。


<div class="right">
<button id="stopButton">
停止
</button>
<h2>録画した内容</h2>
<video id="recording" width="160" height="120" controls></video>
<button id="downloadButton">
Download
</button>
</div>

view raw

index.html

hosted with ❤ by GitHub

JavaScriptの処理

まず必要なDOMを変数化します。最後の recordingTimeMS は録画を行うタイミングで、今回は5秒ごとにしています。細かければ動画が滑らかになりますが、CPU負荷も大きくなります。


let preview = document.getElementById("preview");
let recording = document.getElementById("recording");
let startButton = document.getElementById("startButton");
let stopButton = document.getElementById("stopButton");
let downloadButton = document.getElementById("downloadButton");
let logElement = document.getElementById("log");
let recordingTimeMS = 5000;

view raw

index.js

hosted with ❤ by GitHub

開始した際の処理

まず開始時の処理について解説します。最初はgetUserMediaを使ってWebカメラにアクセスします。そして、映像を #preview に表示します。そして、 preview.captureStream を使って記録を開始します。


// 開始ボタンを押した時の処理
startButton.addEventListener("click", function() {
// Webカメラにアクセス
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(stream => {
// アクセスが許可された場合
preview.srcObject = stream; // プレビューにWebカメラの映像を表示
downloadButton.href = stream; // ダウンロードボタンにも配置
// 表示内容をキャプチャする
preview.captureStream = preview.captureStream || preview.mozCaptureStream;
// プレビューが表示開始するタイミングをPromiseで取得
return new Promise(resolve => preview.onplaying = resolve);
})
// 表示が開始したらレコーディングを開始
.then(() => startRecording(preview.captureStream(), recordingTimeMS))
// レコーディングが終了時の処理
.then (recordedChunks => {
let recordedBlob = new Blob(recordedChunks, { type: "video/webm" });
recording.src = URL.createObjectURL(recordedBlob);
downloadButton.href = recording.src;
downloadButton.download = "RecordedVideo.webm";
})
.catch((err) => console.log(err));
}, false);

view raw

index.js

hosted with ❤ by GitHub

レコーディング中は非同期処理になるので startRecording という関数の中で処理を行っています。 MediaRecorder のインスタンスにWebカメラの映像を指定し、 start メソッドを実行するとレコーディングが開始されます。レコーディング内容は ondataavailable メソッドで呼び出されるので、これを変数に残し続けます。

レコーディングが終わると onstop が呼ばれます。今回は lengthInMS で自動的に停止するようにしています。


function startRecording(stream, lengthInMS) {
let recorder = new MediaRecorder(stream);
let data = [];
recorder.ondataavailable = event => data.push(event.data);
recorder.start();
let stopped = new Promise((resolve, reject) => {
recorder.onstop = resolve;
recorder.onerror = event => reject(event.name);
});
let recorded = new Promise((resolve, reject) => {
setTimeout(() => {
recorder.state == "recording" && recorder.stop()
resolve();
}, lengthInMS);
});
return Promise.all([
stopped,
recorded
])
.then(() => data);
}

view raw

index.js

hosted with ❤ by GitHub

また、プレビューを停止する場合には次のように実装することもできます。


stopButton.addEventListener("click", function() {
preview.srcObject.getTracks().forEach(track => track.stop());
}, false);

view raw

index.

hosted with ❤ by GitHub

デモ

ここまでの実装をJSFiddleにてデモできます。なお、執筆時点ではChromeとMozillaでしか動作しません。


動画リソースはWebカメラに限らず使えるでしょう。そうした時に特定の場所だけキャプチャするといった用途でも使えそうです。動画を編集するという目的にしてはCPU負荷が大きそうですが、動画コンテンツをより扱いやすくしてくれそうです。

Recording a media element – Web APIs | MDN

From → HTML5

コメントは受け付けていません。

%d人のブロガーが「いいね」をつけました。