IT系おじさんのチラシの裏
2018年10月~
当サイトの記事にはアフィリエイト広告のリンクが含まれる場合があります

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分くらいでちゃちゃっと書いたものなので、バグとかあるかも知れません。いえきっとあります。あくまで参考程度にお願いしますね。

関連記事

JavaScriptのcanvasで縦書きを行う際の備忘録

canvas上に縦書きの文章を出力して画像化しようと考えてちょっとハマったので忘れないうちにメモしておきます。 結論から先に書くと、基本的にcanvasにはwriting-modeの設定が効くの

JavaScriptのWebAudioAPIで楽曲の口パクをしてみる

以前、ソフトウェアの解説動画を作った際、おっさんの声だけ流れてるのもアレだし、最近流行りのアバターにしゃべらせるやつやってみよう、と思ったことがあります。 vtuberとかおじさんよくわからない

コメント

新しいコメントを投稿する

[新規投稿]
 
TOP