VideoタグとWebカメラの映像と音声を一つのVideoタグに合成してダウンロード
- プログラミング
- 技術
HTML5のVideoタグにWebカメラの映像と音声を合成させて、1枚のビデオファイルを生成する方法について試してみました。どうもです、デザイナーの秋葉です、久々の技術のことを書いてみます。
参考にさせていただいたのはこちら
https://html5experts.jp/mganeko/12475/
Webカメラからの映像や音声をgetUserMediaというメソッドを使ってストリームデータを取得して、ブラウザだけで動画ファイルを生成してユーザーはダウンロードできるものです。
ここで考えたのは、オリジナルのVideoタグの動画に、カメラの自分の映像やしゃべった声をスーパーインポーズして一つの動画ファイルにするって、HTML5でできるのかな?と思って試したら、ちょっと手間がかかるけどChromeブラウザでできた。
デモをこちらに上げておきました、Chrome 56以降で試してください。
https://tuqulore.com/demo/201703_video_camera_add/
ちょっと複雑ですが概念図を書いてみました。
が、正直、これが最適なのかはわかりませんので、詳しい方、ご教授ください。
ちょっと複雑なように見えますが、
- 【映像】VideoとgetUserMediaの映像をcanvas 2DのdrawImageで合成
- 【音声】Web AudioのAudioContextにVideoとgetUserMediaに音声を合成
- 【合成】1.と2.の映像と音声をMediaRecorder APIでストリームデータとして合成
- 【完成】3.でできたBlobデータを新たなVideoタグに差し込んで完成
音声の合成
Web Audio APIとよばれるHTML5の音声を扱うJavaScript APIがあり、そのためにAudioContextを生成します。これは音の入り口から出口までの中で、音を変化させるゲインやエフェクトなどを接続していくイメージで、ギターをやっている人であれば、ギター→コンプ→歪み系→空間系→アンプというような音を変えていくためにエフェクターを組み合わせる感じで考えたら分かりやすいと思います。これをJavaScriptで自由に組み合わせて音を変化させることができます。
今回はVideoの音声はcreateMediaElementSource(Videoタグ)で、カメラの音声はcreateMediaStreamSource(カメラからのストリームデータ)を音の入り口として、途中でゲインを最大にして最後に出口の前で2つの音をマージしてひとつの音にします。
映像の合成
映像の合成はCanvasタグを使います。毎フレームオリジナルのVideoとカメラからのsub_videoをdrawImageメソッドで合成します。
Canvas 2Dはある程度勉強していたので、ここは非常に楽でした。
映像と音声の合成
そもそもCanvasタグの「絵」とJavaScriptで内部生成したAudioContextの「音」を一つのVideoファイルにすることが目的なのですが、ここではMediaStreamというあまり聞いたことのないAPIを使います。
映像も音声も「ストリーム」というデータとして扱えるので、このMediaStreamにトラックを追加して映像と音声を入れていきます。(addTrackメソッドを使います)
その後すぐMediaRecorderというAPIを生成して、ストリームデータを「レコーディング」します。(MediaRecorder.start()です)
合成ビデオ完成
ユーザーが停止ボタンを押すと、MediaRecorder.stop()したあと、MediaRecorder.ondataavailableイベントが呼ばれるので、そこで得られるBlob形式のビデオデータを、あらかじめ用意していた空っぽのVideoタグのsrc属性に当てて合成されたVideoが表示されます。
ダウンロードにはa href=”(BlobのURL)”を差し込んでdownload属性を仕込めば、ユーザーにダウンロードさせることができます。
カラオケっぽいサービスがつくれるか?
ここで多くの人が「オケをVideoで出して、マイクの音声で歌を重ねられるの?」と思うかもしれないし、実は私もそれをやりたかったので、自分のバンドのVideoに合わせて歌って録画しようと思ったんですが、マイク・カメラのレイテンシー(遅延)が半端なく大きかったので、オケに合わせて歌うというのはかなり違和感があり、ここは改善を待つしかないかなと思いました。
ただ、それができたらボーカル教室の面白そうなオンラインコンテンツも作れるかもとか思ったりします。やってみたいです。
感想
Web技術だけで音を扱ったり動画を内部で生成したり、ブラウザだけのアプリになるのもおもしろいです。
Firefoxでも同じJavaScript APIは備わっているようなんですが、AudioContext内で双方の音声を追加したときに何故かうまく動作しなかったようです。(原因は不明)
レイテンシーはどうしても今は解消できなさそうですが、もし方法をご存知のかたはご教授いただきたいです。
というわけで本日のチャレンジでした、技術はほんとおもしろいです。
最後にソースコードを上げておきます(ほんと、汚いコードですが、、)