FrontEnd

フロントエンドで動画デコレーション&レンダリング

投稿日:

はじめに

今回は、以下のように動画用の背景画像をHTML+CSSで作り、その中心に動画を合成してレンダリングしてみたいと思います。 今回主に紹介したいのは、「DOMのキャプチャ」と「ffmpeg.wasm」を使ったレンダリングです。

レンダリング方法の検討

次の2つの方法を考えました。

  1. 背景用のDOMをキャプチャし、ffmpegで動画と合成する
  2. DOM上で背景とvideoタグを配置した上で、を丸ごと全フレームを画像に変換し、ffmpegまたはWebCodecsで動画にエンコードする

今回は1の方法で実装を進めます。2もやってみたのですが、次のような理由で実装が難しく、断念しました。

  • キャプチャ対象のDOMにvideoタグが含まれると、iOSでキャプチャできない。そのため、別途Remotion Player外にvideoタグを用意し、キャプチャするときだけRemotion Player内のVideoコンポーネントの代わりにcanvasを置き、外のvideoタグの内容をcanvasに書き写す必要がある。
  • Playerを1フレーム進めてから、実際に動画のフレームが描画されるまでラグがあり、videoの onSeeked でキャプチャする必要があるが、それを1フレームずつ繰り返していると途中で止まってしまう。

ちなみに、1の方法だと、動画の最中で背景に変化をさせることができません。

背景部分のキャプチャ

まずは、背景部分をキャプチャします。

modern-screenshotの導入

DOMをキャプチャするパッケージはいくつかありますが、その中でも最も様々なDOMやデバイスに対応していると思われる「modern-screenshot」を使います。このハッケージはhtml-to-imageのフォークです。(ちなみに、html-to-imageもdom-to-imageのフォークですが、dom-to-imageはメンテナンスが止まっています。)
これらのパッケージの動作原理ですが、こちらが参考になります。基本的には、 <svg> タグ内にHTMLを埋め込むことができる <foreignObject> の中にHTMLを入れ、svgをPNGに変換することで画像化しています。

それでは、moden-screenshotをpnpmで導入します。

DOMのキャプチャ

modern-screenshotの domToPng() を使ってキャプチャします。この関数はPromiseを返すのですが、

これで、DOMをキャプチャすることができました。

ffmpeg.wasmで画像と動画を合成

ffmpegでエンコード

最後に、ffmpeg.wasmで、先ほどキャプチャした画像と動画を合成していきます。

-filter_complexでは、背景画像の上に、動画を中心にフィットするように配置しています。。動画をフィットして配置するコマンドは以下を参考にしました。
http://sogohiroaki.sblo.jp/article/183618558.html

また -preset ultrafast にすることで、エンコード速度を最速にしています。これは、ffmpeg.wasmはトランスコード(動画や音声などののデコード・エンコード)のパフォーマンスが悪く、presetを指定しないとエンコードにめちゃくちゃ時間が時間がかかってしまうためです。
presetのみを指定すると、速度を速くすればするほどファイルサイズが大きくなります(ビットレート一定モードと併用すると、時間をかけた分品質が向上します)。このオプションの詳細は以下が参考になります。
https://tech.ckme.co.jp/ffmpeg_h264.shtml

これで実際に動かしてみると、以下のような動画が出力されました!

Next.jsでの動的import

ここまでの実装で、一通り動くのですが、Next.jsを使っていると以下のエラーがNext.jsのログに出力されます。

Node.jsではffmpeg.wasmは使えないようなので、どうやらサーバサイドレンダリング時にffmpeg.wasmを使っているのが良くないようです。そこで、ffmpegを使っているコンポーネントそのものをdynamic importすることで、サーバサイドレンダリングを回避してみます。

dynamic() の第2引数に { ssr: false } を指定することで、サーバサイドレンダリングをしないようにできます。このようにすることで、先ほどのエラーを回避することができます。

さいごに

フロントエンドだけでなんとか動画の合成とエンコードに成功しました!

おすすめ書籍

Reactハンズオンラーニング 第2版 ―Webアプリケーション開発のベストプラクティス プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発

blog-page_footer_336




blog-page_footer_336




-FrontEnd
-

執筆者:

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

react-icon

【初級者向け】Reactの開発環境の構築

1 はじめに2 Reactとは2.1 Declarative2.2 Component-Based2.3 Learn Once, Write Anyway2.4 Reactのメリット、デメリット3 環 ...

react-icon

Reactで動画編集機能を作り込める「remotion」を試してみた

1 はじめに2 Remotionとは3 Remotionを使ってみる3.1 導入3.2 動画のレイアウト作成3.3 Playerでの動画プレビュー3.4 テキスト編集機能を付け加える4 おまけ : C ...

rails

Rails 7でフロントエンド開発が大きく変わる

1 はじめに1.1 脱Node.jsの経緯2 Rails 7.0でのアセット管理3 propshaft4 importmap-rails4.1 JavaScript CDN経由でのnpmパッケージの利 ...

[Next.js] netlifyからCloudflare Pagesに引っ越してみた

1 はじめに2 netlify vs Cloudflare Pages3 Cloudflare Pagesへのデプロイ4 netlifyでのリダイレクト設定とビルド停止5 さいごに6 おすすめ書籍 は ...

【Vue.js】コンポーネントのテストコードをvue-test-utilsとJestで実装

1 はじめに2 セットアップ3 コンポーネントのテスト3.1 Shallow 描画3.2 基本的な例3.3 プロパティを渡す3.4 ユーザーの操作をシミュレーションする3.5 イベントを検証する3.6 ...

フォロー

blog-page_side_responsive

2024年4月
 123456
78910111213
14151617181920
21222324252627
282930  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。