0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

プレビューを書き出しに一致させるため、2つ目のレンダリングエンジンを出荷した。かえって事態は悪化した。

0
Posted at

この記事はもともと Katto のブログで公開したものです(原文・カノニカル): https://katto.tech/ja/blog/one-render-engine-preview-equals-export-ja

KattoはAIを使った動画クリッパーです。長い動画を放り込むと、いい瞬間を縦型のショート動画に切り出してくれます。そしてエディターで、書き出す前にフレーミングやキャプション、レイアウトを直せます。私はこれを一人で、build in public(公開しながらの開発)で作っています。この記事は、そのエディターで私がやらかした失敗と、それを直す過程で「見たままが手に入る(WYSIWYG)」について学んだことの話です。

解決しようとしていた問題

クリップエディターの成否は、たった一つの約束にかかっています。プレビューで見えているものが、そのままダウンロードされる。書き出したときにキャプションが1ピクセル上にずれていたり、クロップが動いていたり、色が違っていたりすれば、ユーザーはツールを信用しなくなります。そして、信頼こそがこのプロダクトそのものなのです。

私のプレビューは、ブラウザ内でレンダリングされるReactのコンポジションです。一方、書き出しはサーバー側でFFmpegを使ってレンダリングしていました。同じクリップを、2つの異なるレンダラーが描画していたわけです。案の定、両者はずれていきました。キャプションのフォント、絵文字の描画、スプリットスクリーンの正確なクロップ位置。まさに定番の「プレビューと書き出しが一致しない」問題です。

正しく感じた(が、間違っていた)解決策

そこで私は、いかにも当然に見える手を打ちました。ブラウザのプレビューを描いているのと同じReactコンポジションを、ヘッドレスChromium(Remotion)経由でサーバー側の書き出しにも使うようにしたのです。コンポーネントは一つ、真実の源(source of truth)も一つ。これでプレビュー=書き出しが保証される、はずでした。

これはRemotionを貶しているわけではありません。Remotionは本来の用途において素晴らしいツールです。間違えたのは私です。既存のFFmpegパイプラインの隣に、2つ目の書き出しエンジンとしてこれをくっつけてしまったのです。

最初のクリップ、つまりエディターを開く前にAIが生成するクリップは、依然としてFFmpegでレンダリングされていました。速いし、実績があるし、パイプライン全体を回してくれる。これを引っこ抜くつもりはありませんでした。

こうして私は、ファイルを生成するエンジンを2つ抱えることになりました。生成クリップはFFmpeg、編集後の再書き出しはChromiumとRemotion。消し去ろうとしていたはずの食い違いが、かえって悪化したのです。結果一覧で見ているクリップ(FFmpeg)と、ちょっと編集して再書き出しした同じクリップ(Remotion)が、微妙に違う仕上がりになりうる。私はレンダラーを1つから2つに増やしておいて、それを「一致(parity)」と呼んでいたわけです。

おまけに、Chromiumのレンダリングは遅かった。1クリップあたり3〜4分、FFmpegの約30秒に対してです。しかも時々失敗しました。失敗すると、こっそりFFmpegにフォールバックし、ユーザーには編集内容が黙って落とされたファイルを渡していました。最悪の失敗です。間違っていて、しかも静かに。

気づいたこと

「プレビュー=書き出し」は、プレビューそのものをレンダラーにすることで達成されるのではありません。レンダリングの真実の源を一つに保ち、プレビューをその忠実な近似にすることで達成されるのです。

ブラウザのPlayerは、優れたプレビューです。それを2つ目の書き出しエンジンにしてしまったのが間違いでした。そうなった瞬間から、同じジオメトリの実装が2つ存在し、変更のたびにずれていくことになったのです。

やったこと

  • **ファイルを生成するエンジンはFFmpeg一つに統一。**生成も再書き出しも、同じパイプラインを通ります。典型的な60秒未満のクリップの書き出しは、Chromiumパスでの3〜4分から、約30秒(実測で32s)にまで落ちました。

  • **ブラウザのPlayerは、得意なこと、つまりインタラクティブなプレビューに戻しました。**出荷されるものは一切レンダリングしません。

  • **ブラウザにしかできなかった装飾をFFmpegに移植しました。**単語ごとに色が循環するキャプションと、スタックレイアウトの調整可能な分割比率です。これで高速パスがよくあるケースをカバーできます。

  • **静かなフォールバックは廃止しました。**忠実にレンダリングできない場合、ユーザーには目に見えるエラーが表示されます。黙って間違ったファイルを渡すことは、二度とありません。

  • **座標系を一つに、これが最後に仕上げているピースです。**プレビューでクロップをドラッグしたとき、その正確な矩形こそがFFmpegの使うべきものであって、サーバーが独自に再計算した別のジオメトリであってはなりません。これは微妙なやつです。エンジンを統一したあとでさえ、プレビューはあるやり方でクロップ矩形を計算し、書き出しは別のやり方で計算していました。いま私はこれを片付けているところで、FFmpegがエディターの状態にある正確な矩形をそのまま消費するようにしています。というのも、教訓は一段下のレベルでも同じだからです。同じものを2度計算すれば、それが必ずずれの元になる、と。

教訓

  1. **「プレビューをレンダラーにする」は魅力的だが、たいてい間違い。**他に何かレンダリング経路を持った瞬間、レンダラーが2つになってしまいます。出力の真実の源は一つ。プレビューはそれを近似するもの。

  2. **「一致のための」2つ目のエンジンは、隠れた3つ目のずれの源になる。**2つのコードパスが同じジオメトリやフォーマットを計算すれば、必ずずれます。問題は「いつ」かだけです。

  3. **静かなフォールバックは最大の罪。**警告もなく微妙に間違ったファイルは、正直なエラーよりも多くの信頼を失わせます。失敗するなら大きな声で。

  4. **ログではなく、成果物を検証せよ。**私のログは「スタックレイアウトをレンダリング済み」と言っていました。本当のバグを見つけられたのは、ストレージから実際に書き出されたMP4を引っ張り出して、1フレームを目で見たときだけでした。ピクセルこそが真実です。

私は一人で、速く、公開しながら出荷しているソロファウンダーです。今回の件は、善意から出た回り道という代償を払わせてくれました。もしあなたがプレビューと書き出しを持つ何らかのエディターを作っているなら、信頼への最短ルートは退屈なものです。レンダラーは一つ、正直なエラー、そしてフレームを確認すること。

Kattoはkatto.techにあります。動画ツールを作っている方がいれば、プレビューと書き出しの一致について、ぜひ知見を交換したいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?