Recast
Cote, compre e acompanhe execuções do Recast em TypeScript, responda aos pontos de decisão, importe um roteiro próprio e mude a mixagem de um recast pronto.
Disponível em Nodaro Cloud
client.recast executa o Recast: ele gera de novo um vídeo de origem já analisado com o seu próprio elenco e também pode renderizar um roteiro que você escreveu, um “movie as JSON”. Você faz a cotação de uma execução, compra, acompanha e responde aos pontos de decisão dela de elenco, folhas, quadros-âncora e música. Os métodos chamam a API REST do Recast. Veja Recast pelo MCP para o guia de criação.
O Recast é executado no Nodaro Cloud. Em uma instalação self-hosted, estes métodos lançam NotFoundError.
Métodos
| Método | O que faz |
|---|---|
authoringSkill() | Lê o guia de criação de roteiros |
validateScript(script) | Verifica um roteiro próprio |
importScript(script, opts) | Armazena um roteiro próprio como uma análise |
estimate(input) | Faz a cotação de uma execução, de graça |
create(input) | Compra o plano e cria a execução |
get(recastId) | Lê o status da execução e o ponto de decisão pendente |
start(recastId, opts?) | Começa a renderizar uma execução planejada |
resolveGate(recastId, input) | Responde a um ponto de decisão pendente |
estimateRescore(recastId, input) | Faz a cotação de uma nova mixagem ou de uma nova faixa de música |
rescore(recastId, input) | Aplica a alteração de áudio cotada |
Roteiros próprios
authoringSkill()
Retorna o guia de criação, em Markdown (GET /v1/video-analysis/authoring-skill). Ele cobre o documento do roteiro, os vocabulários e os limites dele, as regras de áudio e um exemplo verificado. É gratuito.
authoringSkill(): Promise<string>const guide = await client.recast.authoringSkill()Entregue o guia ao modelo de linguagem que escreve o seu roteiro.
validateScript(script)
Verifica um roteiro próprio e retorna { valid, errors, warnings } (POST /v1/video-analysis/import/validate). É gratuito e não armazena nada.
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)
}Cada erro indica o path que está errado e normalmente traz uma hint escrita para um modelo de linguagem. Corrija e valide de novo até valid ser true.
importScript(script, opts)
Armazena um roteiro válido como um job de análise concluído (POST /v1/video-analysis/import). Use o jobId dele como o analysisJobId de um recast. É gratuito.
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 })Um recast de roteiro próprio é renderizado exatamente como foi escrito, então importe só obras que são suas. json é o seu documento com os campos que o servidor adiciona; prefira-o à sua entrada. Importar o mesmo roteiro de novo retorna created: false.
A execução
estimate(input)
Faz a cotação de uma execução em créditos (POST /v1/recast/estimate). É gratuito. O corpo é o mesmo de create(), sem workflowId, rightsAttested e 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)O segmentSec no SDK 2.17.0. As rotas do Recast recebem o nome de um pacote em segmentSec: "scenes-max", "scenes" ou "max". O SDK 2.17.0 tipa o campo como número, então passe o nome com um cast, como segmentSec: "scenes" as unknown as number, ou deixe o campo de fora para usar o padrão do servidor. Um número como 10 é recusado com um 400. O mesmo vale para create() e start().
create(input)
Cria a execução e compra o plano (POST /v1/recast). Faça a cotação com estimate() antes.
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"],
})Sem workflowId, a chamada falha com 400 workflow_id_required; um workflow desconhecido ou de outra pessoa falha com um 404.
get(recastId)
Lê a execução (GET /v1/recast/:id). Consulte-a periodicamente para acompanhar o progresso. Em uma execução interativa, interactive.next indica o passo ou o ponto de decisão pendente.
get(recastId: string): Promise<RecastRunSnapshot>Prop
Type
const run = await client.recast.get(recastId)
console.log(run.status, run.interactive)O snapshot tem status, interactive, capabilities e, em uma execução concluída com camadas de áudio separadas, audio. Veja Alterar a mixagem da música.
start(recastId, opts?)
Começa a renderizar uma execução no estado planned (POST /v1/recast/:id/start). A cotação do plano já cobre essa renderização, e uma chamada repetida não muda nada.
start(recastId: string, opts?: { segmentSec?: number; provider?: string }): Promise<{ gvpJobId?: string }>Prop
Type
const { gvpJobId } = await client.recast.start(recastId)resolveGate(recastId, input)
Responde a um ponto de decisão pendente em uma execução interativa (POST /v1/recast/:id/select). A plataforma avança todos os outros passos sozinha, então um cliente só consulta get() periodicamente e responde aos pontos de decisão. A escolha em si é gratuita.
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 })Um ponto de decisão só é aberto para os tipos que o seu create() declarou em clientCapabilities. A plataforma decide os demais automaticamente.
Alterar a mixagem da música
Um recast concluído pode manter a música e o som do próprio vídeo como camadas separadas. Quando get() retorna capabilities.audioLayers definido como 1, o manifesto audio descreve essas camadas:
revisionidentifica o áudio atual. Toda alteração precisa dele.presentlista as camadas que o recast tem,musicevideo.layersguarda arquivos de prévia das camadas que existem.bakedEffectiveGaindescreve os níveis do download atual.pendingRescoredescreve uma alteração ainda em andamento. Ele continua lá depois que a página é recarregada.
Nunca invente uma revisão e nunca deduza a mixagem a partir de uma prévia ausente.
estimateRescore(recastId, input)
Faz a cotação de uma alteração de áudio: uma nova mixagem, uma nova faixa de música ou as duas (POST /v1/recast/:id/estimate-rescore). É gratuito e retorna { credits, audioRevision, noOp }.
estimateRescore(recastId: string, input: EstimateRecastRescoreInput): Promise<{ credits: number; audioRevision: string; noOp: boolean }>Prop
Type
rescore(recastId, input)
Aplica a alteração de áudio (POST /v1/recast/:id/rescore). Envie a mesma operação que você cotou, mais um novo requestId, um UUID. Reutilize esse requestId só para repetir a mesma requisição depois de uma falha de rede.
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() })
}
}A alteração é executada como um job. Consulte get(recastId) periodicamente até audio.pendingRescore desaparecer e audio.revision mudar. Uma alteração que não faria nada retorna noOp: true, sem job.
- Uma operação contém uma mixagem, uma substituição de música (
audioUrlousections), ou uma substituição com a mixagem dela. - Com uma substituição, envie a mixagem completa que você quer. Deixá-la de fora só funciona para os níveis padrão antigos exatos e, nos outros casos, falha com
409 legacy_mix_mismatch. - Um
expectedAudioRevisiondesatualizado falha com409 stale_audio_revision, e uma segunda alteração enquanto outra está em execução falha com409 rescore_in_progress. Leia o recast de novo e faça a cotação de novo. - Uma operação inválida falha com um 400, como
validation_error,unknown_section,duplicate_sectionouall_audio_silent. - Uma cotação nunca reserva créditos e retorna o preço mesmo quando o seu saldo é insuficiente.
Perguntas frequentes
Páginas relacionadas
Recast
Recast
Jobs e execuções
Produções do Studio
Última atualização
Produções do Studio
Em TypeScript, crie produções do Studio com um plano, edite-as com operações, gere imagens e clipes, revise quadros planejados, compartilhe-as ou copie-as.
Pipelines
Inicie um pipeline de história para vídeo em TypeScript, acompanhe cada etapa, aprove etapas, converse com o diretor e leia a linha do tempo final.