Recast
REST で、分析済みの動画を自分のキャストで Recast します。実行の見積もりと購入、インタラクティブなゲートへの回答、オーディオのリミックス、作成したスクリプトのインポートができます。
Nodaro Cloud で利用できます
Recast API は、分析済みの動画を、あなた自身のキャストで再生成します。実行の見積もりを出してプランを購入し、シーンごとにレンダリングします。インタラクティブな実行では、その途中でキャスト、シーンの静止画、音楽を選べます。映画を JSON のスクリプトとして書いてインポートすることもできるので、元の動画がまったくなくても Recast できます。recast.nodaro.ai も、このエンジンで動いています。
Recast は Nodaro Cloud でのみ動作し、セルフホスティング環境では、これらのルートは 404 を返します。セルフホスティング環境では代わりに、ワークフローの中で 動画分析(Video Analysis)ノードを使って動画を分解し、動画生成(Generate Video)でシーンを再生成してください。これらのルートの認証には、Bearer トークンを使います。認証を参照してください。
エンドポイント
| メソッド | パス | 内容 | 料金 |
|---|---|---|---|
POST | /v1/recast/estimate | 実行の見積もりを出します。 | 無料 |
POST | /v1/recast | 実行を作成します。このときにプランを購入します。 | 見積もったプランの料金 |
GET | /v1/recast/:id | 実行をポーリングし、保留中のゲートを読み取ります。 | 無料 |
POST | /v1/recast/:id/start | planned の実行のレンダリングを開始します。 | プランの料金に含まれます |
POST | /v1/recast/:id/select | 保留中のゲートに回答します。 | 無料 |
POST | /v1/recast/:id/estimate-rescore | 新しいサウンドトラックか、新しいミックスの見積もりを出します。 | 無料 |
POST | /v1/recast/:id/rescore | 見積もったオーディオの変更を適用します。 | 見積もりの料金 |
GET | /v1/video-analysis/authoring-skill | スクリプトを書くためのガイドを取得します。 | 無料 |
POST | /v1/video-analysis/import/validate | スクリプトを検証します。 | 無料 |
POST | /v1/video-analysis/import | スクリプトを、完了済みの分析としてインポートします。 | 無料 |
実行の見積もりと作成
実行は、分析ジョブから始まります。分析ジョブは、動画分析ノードで分析した動画か、インポートしたスクリプトのどちらかです。まず、見積もりを出します。POST /v1/recast/estimate は、実行の作成に使う設定を受け取り、{ totalCredits, breakdown } を返します。
次に、POST /v1/recast で実行を作成し、そのプランを購入します。戻り値は { recastId } です。ボディには workflowId が必要です。これは、実行を関連付ける、あなたが所有するワークフローの ID です。workflowId がないと、このルートは 400 workflow_id_required を返します。存在しない ID や、ほかのユーザーのワークフローの ID を指定すると、404 workflow_not_found を返します。
curl -X POST https://app.nodaro.ai/v1/recast/estimate \
-H "Authorization: Bearer $NODARO_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "analysisJobId": "6c1e8a3f-9b2d-4f5a-8e7c-3d1b9a5f2e6c", "resolution": "720p", "interactive": true }'
curl -X POST https://app.nodaro.ai/v1/recast \
-H "Authorization: Bearer $NODARO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflowId": "8d3f5b7a-1c9e-4a2d-b6f8-4e2a7c9d1b3f",
"analysisJobId": "6c1e8a3f-9b2d-4f5a-8e7c-3d1b9a5f2e6c",
"resolution": "720p",
"interactive": true,
"clientCapabilities": ["sheet-gate"]
}'import { createClient, StaticTokenAuth } from '@nodaro/sdk'
const client = createClient({
baseUrl: 'https://app.nodaro.ai',
auth: new StaticTokenAuth(process.env.NODARO_API_KEY!),
})
const quote = await client.recast.estimate({ analysisJobId, resolution: '720p', interactive: true })
console.log(quote.totalCredits, quote.breakdown)
const { recastId } = await client.recast.create({
workflowId,
analysisJobId,
resolution: '720p',
interactive: true,
clientCapabilities: ['sheet-gate'],
})nodaro recast estimate --analysis-job <jobId> --resolution 720p --json
nodaro recast create --workflow <workflowId> --analysis-job <jobId> --resolution 720p --jsonProp
Type
レンダリングの設定をまとめて再利用するには、recast-render プリセットとして保存します。プリセットを参照してください。
実行の進行を確認する
GET /v1/recast/:id は、{ status, interactive?, capabilities?, audio? } を返します。ステータスは planning、planned、generating と進み、最後に completed か failed になります。planned の実行は、POST /v1/recast/:id/start を待ちます。このルートはレンダリングを開始し、{ gvpJobId? } を返します。開始のルートは冪等で、追加の料金はかかりません。レンダリングの料金は、プランの見積もりにすでに含まれているためです。
curl https://app.nodaro.ai/v1/recast/2e9b4d6f-8a1c-4e3b-9f5d-7c2a4e6b8d1f \
-H "Authorization: Bearer $NODARO_API_KEY"
curl -X POST https://app.nodaro.ai/v1/recast/2e9b4d6f-8a1c-4e3b-9f5d-7c2a4e6b8d1f/start \
-H "Authorization: Bearer $NODARO_API_KEY"const run = await client.recast.get(recastId)
if (run.status === 'planned') await client.recast.start(recastId)nodaro recast status <recastId> --json
nodaro recast start <recastId>インタラクティブなゲートに回答する
インタラクティブな実行は、サーバーが進めます。選択が不要なステップはすべて Nodaro が進めるので、あなたはポーリングしてゲートに回答するだけです。回答を待っているゲートがあるときは、ステータスの interactive.next にそのゲートが示されます。ゲートは、次の順番で開きます。
gate | 選ぶもの |
|---|---|
cast | キャストメンバー 1 人につき、ポートレート 1 枚です。 |
sheet | 人物の場合のみで、実行で提示されたときに選びます。選んだ顔を共有する 3 枚のアイデンティティシートのうちの 1 枚です。そのため、選ぶのは体型と服装です。 |
anchors | シーンのセグメントの静止画です。 |
music | 映画の 1 つの区間に使う音楽です。 |
ゲートが開くのは、作成時に clientCapabilities で宣言した種類(たとえば sheet-gate)だけです。それ以外のゲートは自動で決定されるので、クライアントが回答できない質問を受け取ることはありません。
回答には、POST /v1/recast/:id/select を使います。選択は無料です。
| フィールド | 内容 |
|---|---|
gate | cast、sheet、anchors、music のいずれかです。 |
picks | cast と sheet で使います。あなたの選択を、保留中のゲートが示す形式で指定します。 |
segment, anchorPicks | anchors で使います。セグメントと、選んだ静止画を表す { start?, end? } です。 |
section, musicPick | music で使います。区間と、選んだトラックです。 |
finishAuto | true にすると、このゲートと残りのすべてのゲートを、自動評価に任せます。 |
await client.recast.resolveGate(recastId, { gate: 'cast', picks })
await client.recast.resolveGate(recastId, { gate: 'music', section: 0, musicPick: 1, finishAuto: true })放置されたインタラクティブな実行も安全です。実行は待機を続け、期限が過ぎると自動で確定します。
サウンドトラックやミックスを変更する
テイクが完了した後は、動画をもう一度レンダリングせずに、音楽を差し替えたり、ミックスのバランスを調整し直したりできます。この機能を使えるのは、ステータスに capabilities.audioLayers: 1 が含まれ、テイクに audio マニフェストがある場合だけです。
interface RecastAudioManifestV1 {
version: 1
revision: string
mode: 'bed' | 'replace'
present: { music?: true; video?: true }
layers: { music?: { url: string }; video?: { url: string } }
bakedEffectiveGain: { music?: number; video?: number }
pendingRescore?: {
jobId: string
requestId: string
state: 'pending' | 'running'
expectedAudioRevision: string
requestedEffectiveGain: { music?: number; video?: number }
}
}presentは、テイクにあるオーディオのレーンを示します。musicと、bedモードでは元のvideoの音声です。layersは、ブラウザーで再生できるプレビューファイルがあるレーンだけを示します。layersにないレーンも、ダウンロードには含まれていることがあります。bakedEffectiveGainは、現在のファイルでの各レーンのレベルを、パーセントで示します。- ステータスの
resultUrlが、受け取る唯一の動画 URL です。
見積もってから適用する
見積もりと適用には、同じ操作を渡します。音楽の差し替えは 1 つまで送れます。audioUrl か、brief を付けた 1 つ以上の sections のどちらかです。それに加えて、希望する mix の全体を送ります。ミックスだけを送ることもできます。
{
"expectedAudioRevision": "server-revision",
"sections": [{ "index": 0, "brief": "Sparse analogue pulse" }],
"mix": {
"music": { "gain": 60, "muted": false },
"video": { "gain": 85, "muted": false }
}
}- 見積もる:
POST /v1/recast/:id/estimate-rescoreは無料で、{ credits, audioRevision, noOp }を返します。残高が足りない場合でも、料金を返します。 - 適用する:
POST /v1/recast/:id/rescoreは、同じボディにrequestId(UUID)を加えたものを受け取ります。expectedAudioRevisionも同じ値にします。戻り値は{ recastId, jobId }で、何も変わらない場合は{ recastId, noOp: true, audioRevision }です。no-op の場合、クレジットは確保されず、ジョブも作成されません。 - 確認する:ステータスをポーリングします。
audio.pendingRescoreは操作を示し、再読み込みしても消えません。新しいリビジョンが公開されるか、操作が失敗すると消えます。次の操作の前に、ステータスをもう一度読み取ってください。
ゲインは 0〜200 のパーセントで、ミュートしたレーンは 0 として扱われます。指定できるのは、present にあるレーンと、このリクエストで追加する音楽だけです。replace モードのテイクには、video のレーンがありません。また、結果のすべてのレーンを無音にすることはできません。requestId を再利用するのは、まったく同じリクエストを再試行するときだけにしてください。
音楽を差し替えるときは、mix の全体も送ってください。mix を省略できるのは、結果が決まった標準のレベルと一致する場合だけです。標準のレベルは、bed モードでは音楽 35 と動画 100、replace モードでは音楽 100 です。現在のレベルがそれ以外の場合は、409 legacy_mix_mismatch が返されます。
curl -X POST https://app.nodaro.ai/v1/recast/2e9b4d6f-8a1c-4e3b-9f5d-7c2a4e6b8d1f/rescore \
-H "Authorization: Bearer $NODARO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"requestId": "4f6a8c1e-3b5d-4e7f-9a2c-6d8b1f3e5a7c",
"expectedAudioRevision": "server-revision",
"mix": { "music": { "gain": 60, "muted": false }, "video": { "gain": 85, "muted": false } }
}'const status = await client.recast.get(recastId)
const revision = status.audio?.revision
if (status.capabilities?.audioLayers === 1 && revision) {
const operation = {
expectedAudioRevision: revision,
mix: { music: { gain: 60, muted: false }, video: { gain: 85, muted: false } },
}
const quote = await client.recast.estimateRescore(recastId, operation)
if (!quote.noOp) {
await client.recast.rescore(recastId, { ...operation, requestId: crypto.randomUUID() })
}
}スクリプトを映画としてインポートする
映画を JSON ドキュメントとして書けば、元の動画なしで Recast できます。多くの場合、このドキュメントは言語モデルの助けを借りて書きます。3 つのルートは、どれも無料です。
作成ガイドを読む
GET /v1/video-analysis/authoring-skill は、ガイドを Markdown で返します。ドキュメントのフィールド、使える値、制限、オーディオのルール、検証済みの作例が含まれます。このガイドを、スクリプトを書くモデルに渡してください。
スクリプトが有効になるまで検証する
{ "script": { … } } を付けて POST /v1/video-analysis/import/validate を呼び出すと、{ valid, errors, warnings } が返されます。各エラーには path と message があり、多くの場合は、修正のループ向けに書かれた hint もあります。valid が true になるまで、各パスを修正して検証を繰り返します。
インポートする
{ "script": { … }, "rightsAttested": true } を付けて POST /v1/video-analysis/import を呼び出すと、スクリプトが完了済みの分析として保存され、{ jobId, created, warnings, json } が返されます。json は、サーバーが導き出すフィールドを加えた、あなたのドキュメントです。これを正式なドキュメントとして保管してください。同じスクリプトをもう一度インポートすると、同じ jobId が created: false とともに返されます。
Recast する
その jobId を analysisJobId に指定し、fidelity: "faithful" と rightsAttested: true を付けて、実行を作成します。
rightsAttested: true は必須です。作成した Recast は、ブランド名も含めて書かれたとおりにレンダリングされるため、この値で、スクリプトがあなた自身の作品であることを確認します。この値がないと、インポートは 403 rights_attestation_required を返します。
ドキュメントは、次の部分でできています。
| 部分 | 内容 |
|---|---|
meta | durationSec、width、height、aspectRatio(16:9 または 9:16 で、幅と高さに合わせます)、そして必須の title です。title は、プロジェクトの名前になります。 |
look | 任意。映画全体のルックです。 |
slots | キャストと、舞台となる場所です。それぞれに role(person、object、background のいずれか)があります。 |
scenes | シーンです。0 から隙間なく番号を付け、それぞれ 8 秒以下にします。全体の長さは、4 秒からプラットフォームの実行上限までです。 |
実行上限を超えるドキュメントは拒否されます。途中で切り詰められることはありません。sceneNumber、slotRefs、visualResolved は書かないでください。これらはサーバーが導き出すもので、あなたが書いた値は無視されます。エディターで JSON をコピーを使ってコピーした分析が、そのままインポートできるのも、このためです。
curl https://app.nodaro.ai/v1/video-analysis/authoring-skill \
-H "Authorization: Bearer $NODARO_API_KEY" > recast-authoring.md
curl -X POST https://app.nodaro.ai/v1/video-analysis/import \
-H "Authorization: Bearer $NODARO_API_KEY" \
-H "Content-Type: application/json" \
-d "{ \"script\": $(cat script.json), \"rightsAttested\": true }"const guide = await client.recast.authoringSkill()
const check = await client.recast.validateScript(script)
if (check.valid) {
const { jobId } = await client.recast.importScript(script, { rightsAttested: true })
}nodaro recast skill > recast-authoring.md
nodaro recast validate --file script.json
nodaro recast import --file script.json --rights-attested --jsonMCP から使う
AI アシスタントは、get_recast_authoring_skill、validate_recast_script、import_recast_script、start_recast、get_recast_status、resolve_recast_gate を使って、同じ流れを実行します。start_recast は最初に料金を示し、確認のためにもう一度呼び出されたときにだけ、クレジットを使います。MCP での Recast を参照してください。
エラー
| ステータス | コード | 意味 |
|---|---|---|
400 | workflow_id_required | workflowId なしで POST /v1/recast が送信されました。 |
400 | validation_error, duplicate_section, unknown_section, all_audio_silent | リクエストまたはオーディオの操作が不正です。 |
402 | insufficient_credits | アカウントのクレジットが、プランまたはオーディオの変更の料金に足りません。 |
403 | rights_attestation_required | スクリプトのインポートに rightsAttested: true がありませんでした。 |
404 | workflow_not_found | ワークフローが存在しないか、あなたのものではありません。 |
404 | not_found | 実行が存在しないか、インスタンスがセルフホスティング環境です。 |
409 | audio_layers_unavailable, audio_layer_unavailable, audio_preview_unavailable | テイクにリビジョン管理されたオーディオがないか、指定したレーンが存在しないか、そのレーンに使えるプレビューがありません。 |
409 | rescore_sections_unavailable, legacy_mix_mismatch | このテイクでは音楽の区間を差し替えられないか、mix なしの差し替えが現在のレベルと一致しません。 |
409 | stale_audio_revision, rescore_in_progress, idempotency_conflict | オーディオが変更されたか、別の変更が実行中か、requestId が別のリクエストに再利用されました。ステータスを読み取ってから、再試行してください。 |
よくある質問
関連ページ
Recast
動画分析
プリセット
音声とメディア
ジョブ
最終更新