チュートリアル
APIで動画にテキストを追加する:字幕とオーバーレイのワークフロー
動画上のテキストがプロンプトではなくAPI設計の問題である理由
生成された動画にテキストを追加するのは、プロンプトを一行書き換えるだけのように見えます。字幕を記述し、リクエストを送信し、テキスト入りのクリップを受け取る。しかし実際には、字幕が読みやすく、タイミングが合い、ローカライズ可能で、複数のシーンで再利用できる必要が出てきた時点で、プロンプトは面白い部分ではなくなります。アーキテクチャこそが重要なのです。
実現可能な道は2つあり、それぞれ異なるコードベースへと通じています:
- 生成時のネイティブテキスト。 動画モデルにテキストをシーンの一部としてレンダリングさせます。1回のリクエスト、1つのアセットで、後処理は不要です。
- クリーンな素材+オーバーレイ。 まずテキストなしの素材を生成し(またはテキストなしの構図を要求し)、2番目のレンダリングステップで字幕とオーバーレイを合成します。
なぜこれが単なる見た目の問題ではないのでしょうか? なぜなら下流のすべてがこの選択に依存するからです。テキストが生成されたピクセルの中に存在する場合、スタイルを簡単に変更したり、翻訳したり、音声に合わせてタイミングを調整したり、クリップを再生成せずに誤字を修正したりすることはできません。テキストが別のオーバーレイ層に存在する場合、レイアウト、フォント、タイミングを自分で掌握できますが、自分でレンダラーを持つ必要があり、パイプラインにリクエストが1つ増えます。
このガイドの残りの部分では、動画上のテキストを、本番環境で通常そうなるものとして扱います:データの問題(どのテキストが、どこに、いつ)とレンダリングの問題(誰がそれを描画するか)です。この2つを分離すれば、API呼び出しは単純明快になり、字幕ロジックを書き直すことなく生成バックエンドを切り替えられます。
有用なメンタルモデルとして、常に3つの事柄を区別してください:コンテンツ(テキスト自体)、タイミング(いつ表示されるか)、プレゼンテーション(フォント、位置、スタイル)。ネイティブ生成はこれら3つすべてを不透明な1つのステップに圧縮します。オーバーレイはこれら3つすべてを明示的かつ編集可能なまま保ちます。どちらも普遍的に優れているわけではなく、統合を書く前にどちらにコミットするかを知ることが目的です。
パス1:プロンプトによる生成時のネイティブな画面上テキスト
ネイティブテキストとは、生成モデルが文字を動画フレームに描画することを意味します。テキストが焼き込まれた単一の出力アセットが得られ、パイプラインは短く保たれます:プロンプトを構築し、送信し、ポーリングし、納品します。
プロンプトに入れるべきもの
モデルがレンダリングするタイポグラフィは合成テキストよりも予測不可能なので、プロンプトはデザインシステム全体を記述する場所ではなく、狭い指示として扱ってください。実用的なアドバイス:
- テキストを短く保つ。 ショットごとに数語。長い文はスペルの揺れやレイアウトの窮屈さを引き起こしやすくなります。
- リテラル文字列を引用符で囲む。 テキストが正確に表示される必要がある場合は、引用符で囲み、その正確なテキストを要求してください。曖昧な記述は曖昧な結果を生みます。
- 位置とスタイルを明示する。 「下三分の一に中央揃えの大きな白いテキスト」は実行可能です。「いい感じのタイトル」はそうではありません。
- ショットごとに1つのテキスト要素。 同じクリップにタイトル、サブタイトル、透かしを要求すると、失敗モードが倍増します。
- 言語を明示する。 コピーが英語でない場合は明示してください。グリフのカバレッジは異なります。
何が返ってくることを期待すべきか
出力は仕様ではなくドラフトとして扱ってください。良い結果でも、グリフの変形、不均一な間隔、動きによる部分的な遮蔽が発生する可能性があります。納品前に必ずレンダリングされたフレームを検査してください。安価なプログラム的チェックと、テキストを含む最初と最後のフレームへの目視確認で、ほとんどの問題を捉えられます。
このパスが優る場合
テキストが副次的で雰囲気的なものである場合、ネイティブテキストは正しいデフォルトの選択です:背景の通りの看板、製品上のスタイライズされたロゴ、失敗したら再生成する覚悟のある短いタイトルカードなど。2番目のレンダリングステップを本当に負担できない場合にも優ります。たとえば、クリップごとに1リクエストが予算である緊迫したターンアラウンドのワークフローなどです。
代償はコントロールです。文言、スタイル、タイミングの変更はすべて新しい生成リクエストを意味し、結果はリトライ間で決定的ではありません。プロンプトとストレージを設計し、再生成されたクリップが古いものをきれいに置き換えられるようにしてください。
パス2:クリーンな素材を生成してテキストを自分で合成する
オーバーレイのパスは作業を2つに分けます。まず、意図的にテキストを含まない素材を生成します。次に、その上に字幕とオーバーレイを合成します。レンダリングサービスまたは独自のメディアパイプラインを使用します。
まずクリーンな素材を生成する
テキストのない構図を要求します:シーン、被写体、カメラの動き、光を記述し、画面上のテキストを要求することを明示的に避けます。モデルが看板やUIテキストを捏造する傾向がある場合は、読み取り可能なテキストを含まない映像であることを言及してください。ここでの出力はベース素材です——多くのテキストバリエーションで再利用できる安定した入力です。
後合成
オーバーレイのステップは2つの入力を受け取ります:ベース素材と構造化された字幕/オーバーレイのペイロードです。レンダラーを自分で制御するため、プロンプトでは保証できない属性を得られます:
- 確定したフォントとサイズ。 同じペイロードは毎回まったく同じようにレンダリングされ、ブランドの一貫性にとって重要です。
- 正確なタイミング。 字幕は音声、音楽のビート、シーン切り替えにフレーム単位で合わせられます。
- セーフエリアとレイアウトルール。 マージンを強制し、顔や重要な被写体を避け、プラットフォーム固有のセーフエリア内にテキストを保つことができます。
- 安価な反復。 誤字の修正や字幕の翻訳は、動画の再生成ではなく、オーバーレイの再レンダリングです。
- コンポーザビリティ。 ウォーターマーク、下三分の一バー、字幕を独立してレイヤー化し、出力に応じて切り替えられます。
トレードオフ
オーバーレイのパスはモデル依存をパイプラインの複雑さと交換します。2番目のリクエストが増え、中間素材を保存する場所が必要になり、レンダリング設定を自分で所有します。その代わり、テキストはバージョン管理、テスト、置き換え可能なデータになります。本格的な字幕のニーズがあるもの——アクセシビリティ字幕、多言語バリエーション、テンプレート化されたソーシャルフォーマット——には、この取引はほとんど常に価値があります。
実用的なパターンは、オーバーレイを非破壊的にレンダリングすることです:ベース素材と字幕ペイロードを唯一の真実の情報源とし、合成された動画はいつでも再生成できる派生物として扱います。
両方のパスで生き残る字幕ペイロードの設計
字幕データをうまく設計すれば、ネイティブ生成とオーバーレイの選択は書き直しではなくレンダリングの詳細になります。目標は単一のペイロードで、ネイティブテキスト用にプロンプトへシリアライズでき、オーバーレイ用にレンダラーへ渡せることです。
コアフィールド
各テキスト要素をオブジェクトとしてモデル化し、コンテンツ、タイミング、プレゼンテーションを分離します:
{
"track": "captions",
"items": [
{
"text": "Everything you need to know",
"start": 0.0,
"end": 2.4,
"style": { "role": "title", "align": "center", "position": "lower_third" },
"lang": "en"
}
]
}
重要な設計上の決定:
- 時間は秒単位の浮動小数点。 プロジェクト全体で単一の時間基準を使用し、レンダリング時のみフレームに変換します。
- 絶対値ではなくロールでスタイルを設定。
title、caption、lower_thirdのようなロールに名前を付け、レンダラーでフォントとサイズに解決します。これによりペイロードはフォーマット間で移植可能になります。 - トラック名。
captions、titles、watermarkトラックを分離し、出力に応じてトラックを有効/無効にできるようにします。 - 項目ごとの言語タグ。 フォント選択と後続の翻訳チャネルの両方に必要です。
- テキストフィールドにプレゼンテーション情報を焼き込まない。 スタイルのヒントをテキストに入れないでください。それがスタイルオブジェクトの目的です。
1つのスキーマから2つのパスへ供給する
ネイティブ生成の場合、小さなアダプターを書き、最も重要な項目を選んでプロンプト指示に変換します:リテラルテキスト、その位置、スタイル記述子。このアダプターは意図的に非可逆にしてください——ネイティブレンダリングは完全な字幕トラックに従うことはできません。
オーバーレイの場合は、ペイロードをレンダラーに渡し、レンダラーがロールと位置を解決し、各項目の時間ウィンドウ内に描画します。
見返りは:アプリケーションコードが字幕オブジェクトを構築し、ネイティブからオーバーレイへ(または特定のクリップで戻す)の切り替えはデータ移行ではなく設定変更になります。
動作するオーバーレイリクエストを段階的に説明
以下はオーバーレイパスのシーケンスをAPI形式のステップで表現したものです。正確なエンドポイント名とパラメータはプロバイダーによって異なりますが、形は安定しており、薄い抽象化レイヤーがバックエンド間でそれを安定させます。
ステップ1:クリーンな素材生成を送信
POST /video/generations
{
"prompt": "A slow dolly shot through a modern office, no on-screen text, natural light",
"duration_seconds": 6,
"aspect_ratio": "16:9"
}
プロンプトをテキストなしに保ち、返されたタスク識別子を保存します。
ステップ2:素材の準備ができるまでポーリング
GET /video/generations/{job_id}
タイトなループではなくバックオフでポーリングします。queued、running、succeeded、failed などの状態をコードの一級状態として扱い、結果の素材URLまたはIDを永続化して、クラッシュしても生成結果が失われないようにします。
ステップ3:オーバーレイレンダリングを送信
POST /video/overlays
{
"source_asset": "asset_abc123",
"captions": {
"track": "captions",
"items": [
{ "text": "Shipping today", "start": 0.4, "end": 2.0, "style": { "role": "title", "position": "lower_third", "align": "center" }, "lang": "en" },
{ "text": "No rebuild required", "start": 2.2, "end": 4.0, "style": { "role": "title", "position": "lower_third", "align": "center" }, "lang": "en" }
]
}
}
オーバーレイリクエストはソース素材とテキストデータのみを運ぶことに注意してください。素材を再生成しないので、反復が安価になります。
ステップ4:合成結果を取得
生成タスクと同じ方法でオーバーレイタスクをポーリングし、最終素材を取得します。ベース素材、字幕ペイロード、出力を一緒に保存し、合成を再現可能にします。
コードでは、ステップ1〜4を1つの関数にラップし、プロンプトと字幕ペイロードを受け取って最終素材を返すようにします。その関数が本当のインターフェースであり、個々のエンドポイントは交換可能な実装の詳細です。
公開前の信頼性チェック
動画テキストのパイプラインは静かに失敗します:切り取られた字幕、誤って翻訳された行、決してクリーンアップされない再生成。ユーザーが見る前にチェックを追加してください。
レンダリングされたテキストを検証する
- ネイティブパス: 各テキストウィンドウの開始点と終了点でフレームをサンプリングして検査します。基本的な読みやすさチェックは可能な限り自動化しますが、顧客向けのコピーには人手によるレビューステップを残してください。モデルのタイポグラフィは予測不能に劣化する可能性があります。
- オーバーレイパス: レンダリング前にペイロードを検証します——各項目のタイミングが重複せず、クリップの長さ内にあり、サポートされている言語とロールを使用していること。レンダリング後、項目の境界でフレームをスポットチェックし、何も切り取られていないことを確認します。
リトライを安全にする
- 送信リクエストの冪等キー。ネットワーク呼び出しのリトライが重複した生成タスクを作成しないようにします。
- タスクごとの状態マシン:queued → running → succeeded/failed。永続化して、再起動が最初からやり直すのではなく復元するようにします。
- バックオフとタイムアウトを備えた有界ポーリング。永久ループではなく明確な失敗を提示します。
- 中間素材を保存する。 オーバーレイのステップが失敗した場合、すでに持っている素材を再生成するためにお金を使うべきではありません。
チェーン全体のコストを制御する
オーバーレイのパスには2つの課金ステップ——生成とレンダリング——があるので、両方を監視します。素材を再生成する頻度と、オーバーレイだけを再レンダリングする頻度を追跡します。素材の再生成が支配的なら、そのワークロードに対してネイティブ/オーバーレイの分割が適切でない可能性があります。(ベース素材, 字幕ペイロード)で最終素材をキャッシュし、同じ出力への重複リクエストが無料になるようにします。
可観測性
プロンプト、字幕ペイロードのハッシュ、タスクID、最終素材IDを一緒に記録します。ユーザーが字幕の誤りを報告したとき、問題が生成、データ、レンダリングのどこにあるかを数秒で特定できるようにしたいものです。字幕ペイロードをバージョン管理された唯一の真実の情報源とし、レンダラーが何を描画するよう要求されたかを常に説明できるようにします。
デフォルトのワークフローを選ぶ
これを開始ルールとして扱い、製品の成長に合わせて再検討してください。
ネイティブテキストを選ぶのは、テキストが装飾的または副次的で、文言が短く、誤りを修正する方法として再生成を受け入れられ、そのクリップに2番目のレンダリングステップを追加するのがエンジニアリング時間に見合わない場合です。
オーバーレイパスを選ぶのは、テキストが正確で、タイミングが合い、翻訳され、スタイルが変更され、複数の出力で再利用される必要がある場合です。字幕、サブタイトル、下三分の一バー、テンプレート化されたマーケティングフォーマットはほとんど常にここに該当します。追加のリクエストは決定性の代償です。
ハイブリッドは合理的です。 多くのチームはデフォルトでクリーンな素材を生成し、重要なものにはオーバーレイに頼り、ネイティブテキストは一回限りの雰囲気カットに取っておきます。両方のパスが同じ字幕ペイロードを消費するため、データに特別な処理をせずにクリップごとにこの決定を行えます。
どちらを選んでも、統合は薄い抽象化の背後に保ってください:プロンプトと字幕ペイロードを受け取って最終素材を返す1つの関数です。その境界こそが、生成バックエンドを切り替えたり、レンダリングオプションを追加したり、苦労して正しく仕上げた字幕ロジックに触れることなく個々のクリップをワークフロー間で移動させたりできるようにするものです。
関連記事
すべての記事を見る →-
チュートリアル
HiAPI API で hailuo-2.3-fast/image-to-video を呼び出す方法:curl と Python の実践
高速・低コストな画像から動画へのティアにおける最初の実行可能なリクエスト — モデル ID から MP4 のダウンロードまで
-
チュートリアル
HiAPI APIでhailuo-2.3/text-to-videoを呼び出す方法:curl、Python、実行可能なリクエスト例
-
チュートリアル
HiAPI で Kandinsky 6.0 Pro のテキストto動画を使用する:curl と Python チュートリアル
リクエスト優先の実践デモ:プロンプトから動画クリップへの呼び出しを構築し、リクエストを送信し、完了状態をポーリングし、結果をダウンロードする