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

Recast

TypeScript から Recast の実行を見積もり、購入し、進行を確認します。ゲートに回答し、作成したスクリプトをインポートし、完成した実行の音楽ミックスを変更します。

Nodaro Cloud で利用できます

client.recast は Recast を実行します。分析済みの元の動画を、自分自身のキャストで再生成し、自分で書いたスクリプト、つまり「movie as JSON」をレンダリングすることもできます。実行を見積もって購入し、進行を確認しながら、キャスト、シート、静止画、音楽の各ゲートに回答します。これらのメソッドは、Recast の REST API を呼び出します。スクリプトの書き方については、MCP での Recast を参照してください。

Recast は Nodaro Cloud で動作します。セルフホスティング環境では、これらのメソッドは NotFoundError をスローします。

メソッド

メソッド内容
authoringSkill()スクリプトの作成ガイドを読み取ります
validateScript(script)作成したスクリプトを検証します
importScript(script, opts)作成したスクリプトを、分析として保存します
estimate(input)実行を無料で見積もります
create(input)プランを購入して、実行を作成します
get(recastId)実行のステータスと保留中のゲートを読み取ります
start(recastId, opts?)計画済みの実行のレンダリングを開始します
resolveGate(recastId, input)保留中のゲートに回答します
estimateRescore(recastId, input)新しい音楽ミックスまたは音楽トラックを見積もります
rescore(recastId, input)見積もったオーディオの変更を適用します

作成したスクリプト

authoringSkill()

作成ガイドを、Markdown として返します(GET /v1/video-analysis/authoring-skill)。スクリプトドキュメント、その語彙と制限、オーディオのルール、検証済みの作例を扱います。無料です。

authoringSkill(): Promise<string>
const guide = await client.recast.authoringSkill()

このガイドを、スクリプトを書く言語モデルに渡してください。

validateScript(script)

作成したスクリプトを検証し、{ valid, errors, warnings } を返します(POST /v1/video-analysis/import/validate)。無料で、何も保存しません。

validateScript(script: Record<string, unknown>): Promise<{
  valid: boolean
  errors: Array<{ path: string; message: string; hint?: string }>
  warnings: string[]
}>

Prop

Type

let check = await client.recast.validateScript(script)
while (!check.valid) {
  script = await fixWithModel(script, check.errors) // each error has a path, a message and usually a hint
  check = await client.recast.validateScript(script)
}

各エラーは、問題のある path を示し、多くの場合、言語モデル向けに書かれた hint も付きます。valid が true になるまで、修正と検証を繰り返します。

importScript(script, opts)

有効なスクリプトを、完了済みの分析ジョブとして保存します(POST /v1/video-analysis/import)。その jobId を、実行の analysisJobId として使います。無料です。

importScript(script: Record<string, unknown>, opts: { rightsAttested: true }): Promise<{
  jobId: string
  created: boolean
  warnings: string[]
  json: Record<string, unknown>
}>

Prop

Type

const { jobId: analysisJobId, json } = await client.recast.importScript(script, { rightsAttested: true })

作成したスクリプトによる実行は、書かれたとおりにレンダリングされるため、自分が権利を持つ作品だけをインポートしてください。json は、サーバーが追加したフィールドを含む自分のドキュメントです。自分が渡した入力より、こちらを優先してください。同じスクリプトをもう一度インポートすると、created: false が返ります。

実行

estimate(input)

実行の料金を、クレジットで見積もります(POST /v1/recast/estimate)。無料です。ボディは create() と同じですが、workflowId、rightsAttested、clientCapabilities は含みません。

estimate(input: EstimateRecastInput): Promise<{ totalCredits?: number; breakdown?: Record<string, number> }>

Prop

Type

const quote = await client.recast.estimate({ analysisJobId, fidelity: "faithful" })
console.log(quote.totalCredits, quote.breakdown)

create(input)

実行を作成し、プランを購入します(POST /v1/recast)。先に estimate() で見積もってください。

create(input: CreateRecastInput): Promise<{ recastId: string }>

Prop

Type

const { recastId } = await client.recast.create({
  workflowId,
  analysisJobId,
  fidelity: "faithful",
  rightsAttested: true,
  interactive: true,
  clientCapabilities: ["sheet-gate"],
})

workflowId がないと、呼び出しは 400 workflow_id_required で失敗します。存在しないワークフローや、ほかのユーザーのワークフローは 404 で失敗します。

get(recastId)

実行を読み取ります(GET /v1/recast/:id)。進行状況を確認するには、ポーリングします。インタラクティブな実行では、interactive.next が、保留中のステップまたはゲートを示します。

get(recastId: string): Promise<RecastRunSnapshot>

Prop

Type

const run = await client.recast.get(recastId)
console.log(run.status, run.interactive)

スナップショットには status、interactive、capabilities があり、オーディオのレーンが分かれている完成した実行には audio もあります。音楽ミックスを変更するを参照してください。

start(recastId, opts?)

planned 状態の実行のレンダリングを開始します(POST /v1/recast/:id/start)。プランの見積もりにすでに含まれており、繰り返し呼び出しても何も変わりません。

start(recastId: string, opts?: { segmentSec?: number; provider?: string }): Promise<{ gvpJobId?: string }>

Prop

Type

const { gvpJobId } = await client.recast.start(recastId)

resolveGate(recastId, input)

インタラクティブな実行の、保留中のゲートに回答します(POST /v1/recast/:id/select)。それ以外のステップはすべてプラットフォームが自分で進めるので、クライアントは get() をポーリングして、ゲートに回答するだけです。回答自体は無料です。

resolveGate(recastId: string, input: ResolveRecastGateInput): Promise<Record<string, unknown>>

Prop

Type

await client.recast.resolveGate(recastId, { gate: "music", musicPick: 1 })
await client.recast.resolveGate(recastId, { finishAuto: true })

ゲートが開くのは、create() で clientCapabilities に宣言した種類だけです。それ以外は、プラットフォームが自動で決定します。

音楽ミックスを変更する

完成した実行は、音楽と動画自体の音声を、別々のレーンとして保持できます。get() が capabilities.audioLayers に 1 を返す場合、audio マニフェストがそれらを表します。

  • revision は、現在のオーディオを識別します。どの変更にも必要です。
  • present は、実行が持つレーン(music と video)を一覧にします。
  • layers は、存在するレーンのプレビューファイルを保持します。
  • bakedEffectiveGain は、現在のダウンロードの各レーンのレベルを示します。
  • pendingRescore は、まだ進行中の変更を示します。ページを再読み込みしても消えません。

リビジョンを勝手に作らず、プレビューがないことからミックスを推測しないでください。

estimateRescore(recastId, input)

オーディオの変更を見積もります。新しいミックス、新しい音楽トラック、またはその両方です(POST /v1/recast/:id/estimate-rescore)。無料で、{ credits, audioRevision, noOp } を返します。

estimateRescore(recastId: string, input: EstimateRecastRescoreInput): Promise<{ credits: number; audioRevision: string; noOp: boolean }>

Prop

Type

rescore(recastId, input)

オーディオの変更を適用します(POST /v1/recast/:id/rescore)。見積もったときと同じ操作に、新しい requestId(UUID)を加えて送信します。requestId を再利用するのは、ネットワーク障害の後に同じリクエストを再試行するときだけにしてください。

rescore(recastId: string, input: EstimateRecastRescoreInput & { requestId: string }): Promise<
  | { recastId: string; jobId: string }
  | { recastId: string; noOp: true; audioRevision: string }
>

Prop

Type

const { total: available } = await client.credits.balance()
const run = await client.recast.get(recastId)

if (run.capabilities?.audioLayers === 1 && run.audio) {
  const operation = {
    expectedAudioRevision: run.audio.revision,
    mix: {
      music: { gain: 55, muted: false },
      video: { gain: 100, muted: false },
    },
  }
  const quote = await client.recast.estimateRescore(recastId, operation)
  if (!quote.noOp && available >= quote.credits) {
    await client.recast.rescore(recastId, { ...operation, requestId: crypto.randomUUID() })
  }
}

変更はジョブとして実行されます。audio.pendingRescore が消えて audio.revision が変わるまで、get(recastId) をポーリングしてください。何も変わらない変更は、ジョブを作らずに noOp: true を返します。

  • 1 回の操作には、ミックス、1 つの音楽の差し替え(audioUrl または sections)、またはミックス付きの差し替えのいずれかを指定します。
  • 差し替えを行う場合は、希望する完全なミックスを送ってください。省略できるのは、正確に以前のデフォルトのレベルと一致する場合だけで、それ以外は 409 legacy_mix_mismatch で失敗します。
  • 古くなった expectedAudioRevision は 409 stale_audio_revision で失敗し、実行中にさらに変更を送ると 409 rescore_in_progress で失敗します。実行をもう一度読み取ってから、もう一度見積もってください。
  • 無効な操作は、validation_error、unknown_section、duplicate_section、all_audio_silent などの 400 で失敗します。
  • 見積もりがクレジットを確保することはなく、残高が足りない場合でも料金を返します。

よくある質問

最終更新

目次