Nodaro ドキュメント
ドキュメントノードリファレンスモデルAI エージェント(MCP)開発者向けセルフホスティングリサーチ
REST API

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/startplanned の実行のレンダリングを開始します。プランの料金に含まれます
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 --json

Prop

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 を使います。選択は無料です。

フィールド内容
gatecast、sheet、anchors、music のいずれかです。
pickscast と sheet で使います。あなたの選択を、保留中のゲートが示す形式で指定します。
segment, anchorPicksanchors で使います。セグメントと、選んだ静止画を表す { start?, end? } です。
section, musicPickmusic で使います。区間と、選んだトラックです。
finishAutotrue にすると、このゲートと残りのすべてのゲートを、自動評価に任せます。
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 }
  }
}
  1. 見積もる:POST /v1/recast/:id/estimate-rescore は無料で、{ credits, audioRevision, noOp } を返します。残高が足りない場合でも、料金を返します。
  2. 適用する:POST /v1/recast/:id/rescore は、同じボディに requestId(UUID)を加えたものを受け取ります。expectedAudioRevision も同じ値にします。戻り値は { recastId, jobId } で、何も変わらない場合は { recastId, noOp: true, audioRevision } です。no-op の場合、クレジットは確保されず、ジョブも作成されません。
  3. 確認する:ステータスをポーリングします。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 を返します。

ドキュメントは、次の部分でできています。

部分内容
metadurationSec、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 --json

MCP から使う

AI アシスタントは、get_recast_authoring_skill、validate_recast_script、import_recast_script、start_recast、get_recast_status、resolve_recast_gate を使って、同じ流れを実行します。start_recast は最初に料金を示し、確認のためにもう一度呼び出されたときにだけ、クレジットを使います。MCP での Recast を参照してください。

エラー

ステータスコード意味
400workflow_id_requiredworkflowId なしで POST /v1/recast が送信されました。
400validation_error, duplicate_section, unknown_section, all_audio_silentリクエストまたはオーディオの操作が不正です。
402insufficient_creditsアカウントのクレジットが、プランまたはオーディオの変更の料金に足りません。
403rights_attestation_requiredスクリプトのインポートに rightsAttested: true がありませんでした。
404workflow_not_foundワークフローが存在しないか、あなたのものではありません。
404not_found実行が存在しないか、インスタンスがセルフホスティング環境です。
409audio_layers_unavailable, audio_layer_unavailable, audio_preview_unavailableテイクにリビジョン管理されたオーディオがないか、指定したレーンが存在しないか、そのレーンに使えるプレビューがありません。
409rescore_sections_unavailable, legacy_mix_mismatchこのテイクでは音楽の区間を差し替えられないか、mix なしの差し替えが現在のレベルと一致しません。
409stale_audio_revision, rescore_in_progress, idempotency_conflictオーディオが変更されたか、別の変更が実行中か、requestId が別のリクエストに再利用されました。ステータスを読み取ってから、再試行してください。

よくある質問

最終更新

目次