---
title: "台本 → MP4 を1コールで生成"
method: POST
path: "/api/v1/agent/generate"
tags: ["agent"]
---

# 台本 → MP4 を1コールで生成

`POST /api/v1/agent/generate`

## Request

- Base URL: `https://app.yukkurigen.com`
- URL: `https://app.yukkurigen.com/api/v1/agent/generate`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer

## Headers

- `Prefer` 'respond-async'

## Request body

- object
  - `output` 'mp4' | 'draft': 何を返すか。mp4=本番レンダー（動画1分につき1クレジット・端数切り上げ・有料プランかクレジットパックで買ったクレジット・サーバで音声を合成してから焼く。受け付けで台本の文字数（各行の text と reading の長いほう）から多めに見積もって押さえ、実際の長さで精算する。差額を引けなければ焼かずにジョブが insufficient_credits で失敗し、押さえた分は全額返る）／draft=プロジェクトと台本を作るところで止める（消費なし・数秒で返る）。mp4 は合成とレンダー開始を待つため、10行の台本で45秒を超えることがある——idempotencyKey を付けるか、draft で作ってから generate_audio → render_mp4 と刻む。mp4 は renderId を返すので進捗をポーリングする（callbackUrl を渡せば通知も届く）。
  - `title` string: 動画のタイトル（テーマ）。横長の動画では画面の左上に出し続ける（titleTelop:false で消せる）。
  - `titleTelop` boolean: タイトルを出すか。横長は左上（章の見出しがあると最初の章より前の行だけ）、縦型は画面の上にずっと。false で両方とも消す。省略時は title を渡したときだけ出す。
  - `templateId` string: テンプレートid（任意）。list_templates が返す id をそのまま渡す——system（5種）でも mine（自作）でもよい。存在しない/他人のものなら 400 template_not_found（課金なし）。省略すると台本の話者から選ぶ。
  - `script` ScriptLine[], required
    - `speaker` string, required: キャラクターid（reimu, marisa, zundamon 等。/api/v1/characters 参照）
    - `text` string, required: セリフ本文（字幕に出る）。読み違えそうな漢字にはルビを書ける: ｜漢字《よみ》（｜は全角・半角どちらでも）——字幕は「漢字」、声は「よみ」。短く 漢字《よみ》 とも書ける（直前の漢字の並び全体に掛かる）。親文字・よみは50文字まで、改行と《》｜は入れない。完成していない記法はそのまま字幕に出る。読みは POST /api/v1/projects/{projectId}/readings/check で確かめる
    - `reading` string: 行全体の読み仮名（未指定なら text を、ルビと読みの辞書を当てて読む）。書くとその行は辞書もルビも効かず、これをそのまま読む。2000文字まで（text と同じ上限）。本番 MP4 の見積もりは各行の text と reading の長いほうで数える
    - `emotion` 'joy' | 'excited' | 'surprise' | 'shocked' | 'sad' | 'crying' | 'angry' | 'troubled' | 'thinking' | 'confused' | 'doubtful' | 'smug' | 'embarrassed' | 'relaxed' | 'explaining' | 'love': 表情（任意）。立ち絵の目・眉・口・顔色・汗や涙の差分を組み合わせた16種で、セリフに合わせて行ごとに変えると動画が生き生きする。joy=喜び / excited=大喜び / surprise=驚き / shocked=ガーン / sad=悲しみ / crying=泣き / angry=怒り / troubled=困り・焦り / thinking=考え中 / confused=混乱 / doubtful=ジト目 / smug=ドヤ顔 / embarrassed=照れ / relaxed=ほっこり / explaining=説明 / love=好き。**1行も書かなければ、セリフの手がかりから自動で付く**（1行でも書けば、書いた行だけ）。どのキャラも16種すべて描ける。
    - `pose` 'normal' | 'point' | 'wave' | 'cheer' | 'hip' | 'think' | 'mouth_cover' | 'whisper' | 'shh' | 'chest' | 'mic' | 'cross_arms' | 'peace' | 'hold': ポーズ＝腕の形（任意）。表情とは別に選べる。ずんだもん・四国めたん・春日部つむぎ・あんこもんだけに効き、ゆっくり（霊夢・魔理沙）には無い。そのキャラに無いポーズは無視される。省略すると表情ごとの既定の腕。**1行も書かなければ、セリフの手がかりから自動で付く**。
    - `effect` union: この行の頭で鳴らす効果音。組み込みの名前（GET /api/v1/audio-library の effects）か、自分が上げた音の url（POST /api/v1/assets/audio-uploads/confirm・/inline の data.url。素材管理で上げた効果音の url も可）。外部の URL・他人の素材は 400 validation_error（invalidAudio）。最大2秒鳴らし、行が短ければ行の長さまで。**1行も書かなければ、セリフから自動で要所に付く**（1行でも書けば、書いた行だけ鳴る。null=鳴らさない）。
      - 'pa' | 'カメラのシャッター1' | 'キーンコーンカーンコーン' | 'きらーん1' | 'クイズ不正解1' | 'クイズ正解1' | 'ショック1' | 'ショック4' | 'ずっこける' | 'チーン1' | 'ナイフで突き刺す3' | 'パンチ' | 'パトカー' | 'ひらめく1' | 'ホラー1' | '和太鼓でドドン' | '心臓の鼓動1' | '決定ボタンを押す1' | '間抜け1' | '騒がしい高校の教室'
      - string: 自分が上げた音の url
    - `bgm` string, nullable: この行から流す BGM（任意）。次に bgm を書いた行まで引き継ぐ。組み込みの曲の名前（GET /api/v1/audio-library の bgm[].name。path でも可）・自分が上げた音の url（audio-uploads の data.url）・"none"（この行から止める）。曲の切り替えは 0.7 秒のクロスフェード、曲はループする。外部の URL・他人の素材は 400 validation_error（invalidAudio）。どの行にも書かなければ従来どおり（動画全体の BGM）。 PATCH /lines では null でこの行の指定を外す（前の行の BGM のまま）。
    - `card` object: この行から画面中央に出す図解カード（見出し＋項目）。要点・手順・理由・比較・数字など図にすると分かりやすい所に付ける（目安: 7行に1枚、最大6枚）。style: list=箇条書き / steps=番号付きの手順 / point=要点・数字を1つ大きく。span 行ぶん（次のカードの手前まで）出る。焼く直前に画像にして素材の列に入れる。図解・写真・章・強調はサーバが台本から勝手に作らない——書いた行にだけ出る。
      - `title` string, required
      - `items` string[]
      - `style` 'list' | 'steps' | 'point'
      - `span` integer
    - `chapter` string: この行から始まる章の見出し（14文字以内が目安。30文字まで受け付け、16文字を超えた分は黙って切る）。横長の画面の左上に次の章まで出し続ける（縦型では出ない）。目安: 8行に1つ。
    - `emphasis` union: 強調テロップ（その行だけ）。文字列（黄色・従来の場所）か、色と出す場所を書いたオブジェクト。
      - string
      - object
        - `text` string, required: 強調する言葉（10文字以内が目安、12文字で切る）
        - `color` 'yellow' | 'red' | 'blue' | 'green': 文字の色（既定 yellow）
        - `position` 'top' | 'center' | 'bottom': 出す高さ。top=画面の上の方 / center=真ん中 / bottom=字幕のすぐ上。省くと従来の高さ（横長は上から26%、縦型は24%。顔と顔の間）
        - `x` number: テロップの中心の横の位置（画面の幅の %）。省くと左右の真ん中。端ほど折り返す幅が狭くなる（20〜80 が無難）
        - `y` number: テロップの中心の縦の位置（画面の高さの %）。position より勝つ
    - `photo` union: この行に添える写真の英語の検索語（具体的な物から順、最後は1語）。焼く直前に Openverse の CC0・パブリックドメインの写真を探して素材の列に入れる。見つからなければ何も出ない。
      - string
      - string[]
    - `cameraMode` 'dynamic' | 'summary' | 'null', nullable: その行のカメラ。**任意（使わなくてよい）。** dynamic=その行でカメラが背景ごと話者に寄る / summary=立ち絵を消す / null・省略=寄らない。使うなら盛り上がり・オチの2〜4行まで（全行 dynamic は寄りが効かなくなる）。自動で付くのは**作るときだけ**で、どの行にも cameraMode を書かなかったときに限り、セリフの手がかりから数か所に dynamic が付く。**寄りを一切入れたくないなら、どれか1行に `"cameraMode": null` と書く**（自動が止まる）。作った後は PATCH /projects/{projectId}/lines で null にすればその行は寄らない（後から自動で付け直すことはない）。立ち絵が画面に出ている行にだけ効く。
    - `camera` LineCamera: 行ごとのカメラ（その行だけ）。
      - `zoom` number: 寄りの大きさ（1 は寄らない）
      - `target` union
        - string: "speaker"（その行の話者）か、台本で話すキャラの id
        - object: 画面の %（0〜100）の点
          - `x` number, required
          - `y` number, required
      - `center` boolean: 寄る先を画面の真ん中へ持ってくるか（既定 true）
      - `move` 'cut' | 'ease' | 'slow': 前の行のカメラからの移り方（既定 ease）
      - `shake` union: 行の頭で画面を揺らす（true は light）
        - boolean
        - 'light' | 'strong'
      - `materials` 'zoom' | 'fixed': その行の素材をカメラと一緒に寄せるか（省くとテンプレートの従来どおり）
    - `stage` StageEntry[]: この行から舞台（画面）に立つキャラの並び（任意）。要素はキャラの id の文字列（テンプレートの枠の位置に立つ）か、立ち位置つきの {id, x?, y?, scale?, facing?}（StageEntry。文字列と混ぜてよい）。x はキャラの横の中心（画面の幅の %、0〜100。50 が真ん中）、y は枠の位置から下へずらす量（画面の高さの %、-50〜50）、scale は枠に対する大きさ（0.5〜2。tohoku-ahiru-talk と自作テンプレートは頭の高さを保つ、yukkuri-talk は下端を保つ）、facing は顔の向き（left / right。省くと x を書いたときは画面の中央の方を向く）。書かなかった項目は枠のまま。範囲の外・知らない項目は 400 validation_error。位置も stage と一緒に引き継ぎ、次に stage を書いた行で文字列で書いたキャラ・並びに無いのに台詞で登場したキャラは枠の位置に戻る。舞台に居るまま位置・大きさが変わると約0.3秒でなめらかに動く。位置を書いたキャラは4人の並び・素材の寄せに従わず書いた所に立ち続け、cameraMode dynamic はいま立っている所へ寄る。1人で真ん中に寄せるのは自動ではない（x:50 と書く）。台本で話すキャラだけ書ける（それ以外は 400 validation_error・invalidStage）。次に stage を書いた行まで引き継ぐ。並びから外したキャラはその行で退場し、加えたキャラは登場する（外側へ・外側から約0.3秒ですべる）。台詞のある行の話者は並びに無くても登場し、以後も残る（ただし offstage: true の行の話者は登場しない。voiceOnly のキャラは書けない＝400 voiceOnlyOnStage）。どの行にも書かなければ従来どおり（初めて話した行で登場し、最後まで残る）。描ける人数は動画全体の話者（声だけの話者は数えない）で数えて tohoku-ahiru-talk（とその複製）は4人まで、yukkuri-talk は2人（超えた話者は声と字幕だけ）。tohoku-ahiru-talk はその時点で舞台に居る人数で並ぶ（3人は2人と1人、4人そろうと左右に2人ずつ少し小さく。人数が変わると約0.3秒で並び直す）。story-talk では効かない。
      - union: 行の stage の1人ぶん。キャラの id の文字列（テンプレートの枠の位置）か、立ち位置つきのオブジェクト。
        - string: キャラの id（台本で話すキャラ）。テンプレートの枠の位置に立つ
        - object
          - `id` string, required: キャラの id（台本で話すキャラ）
          - `x` number: キャラの横の中心（画面の幅の %）。50 が真ん中
          - `y` number: 枠の位置から下へずらす量（画面の高さの %）。マイナスで上へ
          - `scale` number: 枠に対する大きさ（1 が枠のまま）
          - `facing` 'left' | 'right': 顔の向き。省くと x を書いたときは画面の中央の方を向く（x が 45 未満なら右、55 を超えたら左）
    - `backgroundMotion` 'none' | 'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight': 背景のゆっくりした動き（任意）。none=止める（既定）/ zoomIn=寄る / zoomOut=引く / panLeft・panRight=カメラが左・右へ流れる。書いた行から、次に backgroundMotion を書いた行まで引き継ぐ（動画全体なら1行目に書く）。その背景が出ている間いっぱいをかけて最大8%動く（8秒より短い場面では小さく）。背景か動きを替えた行から頭から動く。画像の背景だけに効く（動画の背景は動かない）。cameraMode の寄りとは別で、重ねて使える。
    - `transition` 'dissolve' | 'fadeBlack' | 'cut': この行での場面転換の見せ方（任意。その行だけ）。dissolve=0.6秒で溶かす（既定）/ fadeBlack=行の頭の前後0.4秒ずつの暗転（画面全体。背景を変えない行でも暗転する）/ cut=一瞬で切り替え。dissolve・cut は、その行で backgroundImageUrl か backgroundMotion が変わるときだけ効く。
    - `eyecatch` union: この行の前に挟む全画面の章タイトル（任意）。文字列なら見出しだけ、{title, subtitle} なら小見出しつき（見出し30文字・小見出し40文字まで）。背景を暗くぼかしてキャラを消し、見出しを1.8秒出す（横長・縦型とも）。その行の音声の前に1.8秒の無音の間を足してそこに出すので台詞とは重ならない——そのぶん動画が1.8秒ずつ長くなり、本番 MP4 のクレジット（動画1分につき1）と受け付けの見積もりにも入る。同じ行で背景・backgroundMotion・stage を変えると、アイキャッチの裏で入れ替わる。
      - string
      - object
        - `title` string, required
        - `subtitle` string
    - `action` union: この行の頭でキャラが1回する動き（任意。その行だけ・引き継がない）。立ち絵の全体を動かすので組み込み・自作（PNG・PSD）・ゆっくりのどれにも効き、口パク・表情・ポーズは続く。文字列はその行の話者、{type, target} は target のキャラ（台本で話して画面に出るキャラだけ。ほかは 400 validation_error・invalidAction）、配列で複数（4つまで。同じキャラは最初の1つ）。jump=跳ぶ（約0.8秒）/ hop=ぴょんぴょん2回（約0.6秒。同じ行の stage で立ち位置が変わるなら跳ねながら移る。1回約0.3秒で2〜4回）/ shake=震える（約0.6秒）/ bow=顔の向きへお辞儀（約1秒）/ spin=振り向く（約0.5秒。同じ行で facing が変わればその向きへ、変わらなければ一回り）/ fall=ずっこける（行の長さに合わせて1.3〜3秒で起き上がる）/ bounce=はしゃぐ（約0.75秒）。動き出すのは行の音声の頭（アイキャッチの後・その行で登場するキャラは入りきってから）。目安: 盛り上がり・驚き・オチ・あいさつに。毎行には付けない。story-talk では効かない。
      - union: 行の action の1つぶん。動きの名前の文字列（その行の話者が動く）か {type, target?}。
        - 'jump' | 'hop' | 'shake' | 'bow' | 'spin' | 'fall' | 'bounce'
        - object
          - `type` 'jump' | 'hop' | 'shake' | 'bow' | 'spin' | 'fall' | 'bounce', required: 動きの名前
          - `target` string: 動くキャラの id（台本で話すキャラ。省くとその行の話者）
      - ActionEntry[]
        - union: 行の action の1つぶん。動きの名前の文字列（その行の話者が動く）か {type, target?}。
          - 'jump' | 'hop' | 'shake' | 'bow' | 'spin' | 'fall' | 'bounce'
          - object
            - `type` 'jump' | 'hop' | 'shake' | 'bow' | 'spin' | 'fall' | 'bounce', required: 動きの名前
            - `target` string: 動くキャラの id（台本で話すキャラ。省くとその行の話者）
    - `voice` LineVoice: 行の voice（声の速さ・高さ。その行だけ）。自作キャラの既定の voice も同じ形。
      - `speed` number: 話す速さ（1 が標準）
      - `pitch` number: 声の高さ（0 が標準）
    - `offstage` boolean: true でこの行の話者は声だけ（任意。舞台の外から話す・電話の声など）。その台詞では舞台に出てこない（台詞による自動の登場をしない）。既に舞台に居るキャラは残る（口も動く）——姿を消すなら同じ行の stage から外す。offstage の行でしか話さず、どの行の stage にも無いキャラは一度も画面に出ず、枠も使わない。この行の cameraMode dynamic は寄らない。この行の話者を action で動かす（target を省いたものを含む）・camera の target にする（"speaker" を含む）のは 400 validation_error（invalidAction / invalidCameraTarget）。camera の target を省くと寄る先は画面の真ん中。字幕・音声は普段どおり。その行だけ（引き継がない）。story-talk ではその行の話者の絵を出さない。
  - `channelId` string: チャンネルid（省略可。テンプレートの既定を引く）
  - `voicePlaybackRate` number: 動画全体の読み上げの再生速度（0.5〜2.0。既定 1.1）。焼くときと共有リンクで音声の再生に掛かる（音声の作り直しは要らない）。プロジェクトの voice_playback_rate に残り、共有リンク・あとの render も同じ速さになる。行ごとの速さ・高さは script[].voice（掛け合わせ）。
  - `voiceOnly` string[]: 動画全体で姿を出さず、声だけで話すキャラの id の並び（任意。8人まで。ナレーター・電話の声など）。台本で話すキャラだけ（それ以外は 400 validation_error・invalidVoiceOnly）。そのキャラは一度も画面に出ない: 台詞の行でも舞台に立たず、テンプレートの枠も使わない（空いた枠はほかの話者が使う）、その行の cameraMode dynamic でも寄らない、4人の並び・描ける人数にも数えない。声と字幕は普段どおり。stage に書く・action で動かす・camera の target にするのは 400（voiceOnlyOnStage / invalidAction / invalidCameraTarget）。プロジェクトの voice_only に残り、あとから PATCH /projects/{id}/settings の voiceOnly で変えられる。話者の検査（cast_mismatch）は声だけのキャラにも掛かる。
  - `backgroundImageUrl` string: 動画全体の背景画像/動画のURL（https のみ、内部アドレス不可）。省略すると既定の背景（室内のイラスト）になる。
  - `callbackUrl` string, uri: 完了通知の宛先（mp4 のときだけ意味を持つ）。https のみ・内部アドレス不可。
  - `platform` 'youtube' | 'tiktok' | 'shorts': 出力プラットフォーム。shorts / tiktok は縦型になる。
  - `idempotencyKey` string: 冪等キー（任意）。`Idempotency-Key` ヘッダと同じ働きで、ヘッダが無いときに使われる。同じ鍵で投げ直せば最初の結果が返り、課金は起きない（24時間）。処理中なら 409 code:"in_flight"。

## Response `200`

生成成功（同期の経路、同じ鍵の完了済み結果の再送、または Prefer なしの呼び出しをサーバが待つ設定で、待つ間にジョブが終わったとき）。レンダーを起動したあとにジョブだけが失敗した場合（まれ）も、同じ Idempotency-Key の再送（Prefer を付けていても）とサーバの待ちには、起動済みのレンダー（renderId: agent-{jobId}）がこの 200 で返る。そのレンダーは課金されたまま動いていて返金されず、2本目は作られない。

- AgentGenerateResult: プロジェクトを作り、音声を合成し、レンダーを開始した結果。**完成した動画はここでは返らない**——renderId で進捗を引くこと。
  - `projectId` string, required: 作成したプロジェクトのID
  - `renderId` string, required: レンダーのID。進捗の取得に使う
  - `status` string, required
  - `estimatedTime` number: 完了までの目安（秒）
  - `callbackUrl` string: 登録した通知先（渡したときだけ）
  - `callbackSecret` string: 通知の署名検証に使う（利用者ごとに固定）
  - `callbackSignatureHeader` string

## Other responses

- `202`: 非同期ジョブを受け付けた（Prefer: respond-async を付け、output が mp4 で、サーバの設定でジョブが使えるとき。Prefer なしでサーバが待つ設定のとき、待つ間に終わらなければ Preference-Applied なしで返る）。クレジットはこの時点で押さえ済み。同じ Idempotency-Key で投げ直すと、ジョブが処理中・成功済みなら同じ jobId が返り課金は起きない（失敗したジョブのクレジットは返金され、鍵は空く）。例外は、レンダーを起動したあとにジョブだけが失敗した場合（まれ）で、レンダーは課金されたまま動いていて返金されず、鍵も空かない。同じ鍵で投げ直すと、Prefer: respond-async を付けていても起動済みのレンダー（renderId: agent-{jobId}）が 200 で返り、2本目は作られない。
- `400`: リクエスト不正（code: validation_error。未知の speaker / キャラid のときは validSpeakers 同梱）
- `401`: 認証失敗（code: unauthenticated）。ジョブで受け付ける mp4 は Authorization: Bearer（API キーまたは ID トークン）が必要で、Cookie だけの呼び出しは 401
- `402`: 権限またはクレジット不足（purchaseUrl 同梱）。code: insufficient_credits は残高が足りない（shortfall と、不足を満たす最小のパックを purchase に同梱）。code: plan_required は無料プランで、有料プラン・買い切りライセンス・購入したクレジット（パック）の残りのどれも無い（purchase=standard と、少額の代わりとして alternative=いちばん小さいクレジットパックを同梱。パックは無料プランでも買える）。この鍵は解放されるので、購入・アップグレード後は同じ鍵でそのまま再試行してよい。
- `403`: 権限不足（render:mp4。ただし output:"draft" は projects:write / code: insufficient_scope）。ジョブで受け付ける mp4 は audio:generate も必要（読み上げる行が無い台本でも）。ジョブの受け付けには Authorization: Bearer も要り、Cookie だけの呼び出しは 401
- `409`: 同じ Idempotency-Key の処理が進行中（code: in_flight）。少し待って同じ鍵で再試行する。その鍵のジョブが処理中の間は、Prefer なしの同期の呼び出しにもこれが返る（Prefer: respond-async なら同じ jobId の 202）。
- `429`: レート上限（code: rate_limited、retryAfter 同梱）
- `500`: 生成に失敗（code: generate_failed）。予約したクレジットは返金済み。
- `503`: 冪等キーの判定ができなかった場合は鍵が取られておらず課金も起きていないので、同じ鍵でそのまま再試行する。クレジット確保に失敗した場合は課金の成否が確定しておらず鍵は保持されるので、GET /api/v1/credits で残高を確認し、しばらく置いてから同じ鍵で再試行する（鍵は65分で解ける）。callbackUrl を渡したのに通知の署名鍵を用意できない環境では code: callback_unavailable（callbackUrl を外して再実行する）。ジョブで受け付ける場合（Prefer: respond-async とフォールバック）、code: unavailable に jobId（と projectId）が付いた 503 は、受け付けのコミットが入ったかを確かめられなかったときと、ジョブを積めなかったときの2通りで返り、課金の状態は本文だけでは分からない。GET /api/v1/jobs/{jobId} で確かめること: ジョブがあって queued / running / succeeded なら課金されて進んでいる（そのまま追う）、not_found なら何も課金されていない、failed なら押さえたクレジットは返金される。同じ Idempotency-Key でそのまま投げ直してもよい: ジョブが queued / running / succeeded なら同じ jobId が返り、二重には課金されない。failed なら鍵は空いていて、投げ直しは新しい jobId の新しいジョブとして改めて課金されるが、先に押さえた分は返金されている（二重にはならない）。not_found なら新しく受け付ける。例外は、レンダーを起動したあとにジョブだけが失敗した場合（まれ）で、返金されず鍵も空かない。同じ鍵で投げ直すと、起動済みのレンダー（renderId: agent-{jobId}）が 200 で返り、2本目は作られない。

## Changes

- **2026-10-20** `ba5f36b016da`: 40 warning, 24 info
  - added the new `already_subscribed` enum value to the `code` response property for the response status `400`
  - added the new `already_subscribed` enum value to the `code` response property for the response status `401`
  - added the new `already_subscribed` enum value to the `code` response property for the response status `402`
  - added the new `already_subscribed` enum value to the `code` response property for the response status `403`
  - …60 more

[Operation history](https://skmtc.dev/yukkurigen/apis/yukkurigen-ai-operated-api/changes/api/v1/agent/generate/post.md)

---

[API](https://skmtc.dev/yukkurigen/apis/yukkurigen-ai-operated-api.md) · [All operations](https://skmtc.dev/yukkurigen/apis/yukkurigen-ai-operated-api/llms.txt) · [OpenAPI document](https://skmtc.dev/yukkurigen/apis/yukkurigen-ai-operated-api/revisions/ba5f36b016da?raw)
