スポンサーリンク

JavaScriptでcanvasへ動画を描画しMediaRecorderで録画

もう3年以上前になるのですが、「JavaScriptでcanvasを録画して動画ファイルに保存する方法」という記事を投稿しました。

Google Analyticsによると少なくとも15000人以上には読まれているようですが、本日はじめてコメントが入りました。やった~!(棒

…さて、そんな貴重なコメントで、「動画保存バーションを行うにはどうすれば良いのでしょうか」という質問があったため、出来る限り有益な回答をしたいのですが、ぼくの読解力が足りないため、いまひとつ意図するところがわかりません。

該当記事では、canvas上に静止画をスライドショーのように連続して描画して、それを動画ファイルに変換しております。その画像を動画にしたバージョンをお求めとのことですが、動画なら普通はvideoタグで書くでしょうし、それならファイル名を指定しているハズで、なら録画自体が必要なくね…?と混乱した次第。

ただ、ぼくの想像力が足りないだけで、canvas上に動画を描画したいケースがあるのかも知れない…っ!

そんなわけで、(技術的な興味もありましたし)サクサクっと30分くらいでコードを書いてみました。

スポンサーリンク

canvasへ動画を描画しMediaRecorderで録画するサンプル

実行例

■録画したい動画
■録画用のcanvas

解説

半分ジョークで作った29秒の動画をサンプルにしているため、動画の内容自体は気にしないでくださいw

autoplay属性を付けているため、たぶん自動再生されていると思いますが、そうでなければ再生ボタンをポチっとお願いします。

その後、[録画開始]ボタンを押下すると、「録画用のcanvas」という画面が表示され、これが録画中の画面内容になります。

最後に[録画停止]ボタンを押下すると「録画用のcanvas」は消去され、代わりに「ダウンロード」というリンクが表示されますので、これをポチっと押すと動画(webm形式)がダウンロードできます。

録画処理はすべて貴方のブラウザの中で実行されるため、サーバー上に録画データが保存されたりとか、そういう面倒なことは一切ありません。

HTML部分

<div>
	■録画したい動画<br>
	<video id="video" controls src="[動画ファイル名]" width="500" autoplay loop muted></video>
</div>

<div id="canvas_wrapper">
	■録画用のcanvas<br>
	<canvas id="canvas"></canvas>
</div>

<div>
	<button id="rec_start">録画開始</button>
	<button id="rec_stop" disabled>録画停止</button>
</div>
<div>
	<a href="#" id="downloadlink">ダウンロード</a>
</div>

<style>
#canvas_wrapper {
	display:none;
}
#canvas {
	width:500px;
	border:1px solid red;
}
#rec_stop {
	enabled:false;
}
#downloadlink {
	display:none;
}
</style>

解説

HTML部分は特に難しいことはしていません。普通にvideoタグで再生する動画ファイルを指定して、録画開始時に表示するcanvasタグ、そして録画停止時に表示するダウンロードリンク用のタグを準備しているだけです。

尚、videoタグにはautoplay loop muted(自動再生/ループ/音声はミュート)を指定してありますが、これはChromeブラウザでは音声をミュートにしないと自動再生が有効にならないからです。

爆音の動画がいきなり自動再生されたら困りますもんね。mutedを付けないと自動再生できない仕様なのは当然かなと思います。

chrome以外ではテストしてないため、正常に動かなかったらごめんなさいね。

JavaScript部分

<script>
window.addEventListener('load', function () {
	let video = document.getElementById('video');
	let canvas = document.getElementById('canvas');
	let ctx = canvas.getContext('2d');
	let intervalID = null;

	//canvasからストリームを取得し、MediaRecorderを生成
	let stream = canvas.captureStream();
	let recorder = new MediaRecorder(stream, {mimeType:'video/webm;codecs=vp9'});

	//録画停止時にダウンロードリンクを生成する
	recorder.ondataavailable = function(e) {
		let videoBlob = new Blob([e.data], { type: e.data.type });
		let blobUrl = window.URL.createObjectURL(videoBlob);
		let anchor = document.getElementById('downloadlink');
		anchor.download = 'rec.webm';
		anchor.href = blobUrl;
		anchor.style.display = 'block';
	}

	//録画開始ボタン
	document.getElementById('rec_start').onclick = function () {
		//録画再生ボタンを無効にし、録画停止ボタンを有効にする
		this.disabled = true;
		document.getElementById('rec_stop').disabled = false;
		//canvasを表示し、動画の描画も開始
		canvas.width = video.videoWidth;
		canvas.height = video.videoHeight;
		document.getElementById('canvas_wrapper').style.display = 'block';
		intervalID = setInterval(function(){
			ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
		}, 1000/30);
		//録画開始
		recorder.start();
	};
	//録画停止ボタン
	document.getElementById('rec_stop').onclick = function () {
		//録画停止ボタンを無効にし、録画停止ボタンを有効にする
		this.disabled = true;
		document.getElementById('rec_start').disabled = false;
		document.getElementById('canvas_wrapper').style.display = 'none';
		//動画の描画を停止
		clearInterval(intervalID);
		//録画開始
		recorder.stop();
	};
});
</script>

JavaScript部分

大部分は「JavaScriptでcanvasを録画して動画ファイルに保存する方法」で解説したため、MediaRecorderに関する解説はここではしません。

しかし、残るcanvasへの動画描画についてもこの3行だけなんですよね…。

intervalID = setInterval(function(){
	ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
}, 1000/30);

canvasへ動画を描画するといってもフレーム単位の話で、drawImageを実行した瞬間に画面上に表示されている1フレームを描画するに過ぎません。

そのため、setIntervalを利用して1秒間に30回(30fps)の速度で1フレームずつ描画してるんです。すんごい力業でしょ。

まとめ

こんなふうにcanvasタグに無理やり動画を描画しなければならないケースってあるんかなぁ?

仮にcanvas描画するところまでは、例えばブラウザゲームを開発したり、動画をブラウザ内で加工しながら表示したい、という要件で必要になることもあるのかも知れません。しかし、はてさてそれを録画したい、ということがあるのだろうか。

ゲームのシェア機能的なアレを実装したい、とか?

ともあれ、必要性はわかりませんが、

  • canvasに動画を描画する方法
  • その内容を動画に保存する方法

について、個人的にも技術的な興味は出たので、サクサクっと書いてみた次第です。

コード自体は30分くらいでちゃちゃっと書いたものなので、バグとかあるかも知れません。いえきっとあります。あくまで参考程度にお願いしますね。

コメント

タイトルとURLをコピーしました