Docs do Nodaro
DocumentaçãoReferência de nósModelosAgentes de IA (MCP)DesenvolvedoresSelf-hostingPesquisa
API REST

Pipelines

Inicie um pipeline História → vídeo via REST, acompanhe e aprove as etapas, converse com o diretor e derive um pipeline concluído a partir de uma etapa.

Disponível em Nodaro Cloud

A API de pipelines executa o História → vídeo (Story → Video) a partir do código. Você envia uma história de uma linha. O mecanismo de pipeline escreve um roteiro, cria o elenco, os adereços e os lugares e planeja as tomadas. Depois, ele renderiza quadros-chave, anima esses quadros com som e junta o filme. Cada etapa pode parar para a sua aprovação, ser executada sozinha ou abrir um chat com o diretor.

Os pipelines só rodam no Nodaro Cloud; as edições Community e Business retornam 403 edition_required. Em uma instalação self-hosted, monte os mesmos passos como um workflow, com nós como Gerar roteiro (Generate Script), Gerar imagem (Generate Image) e Gerar vídeo (Generate Video). As rotas recebem um bearer token; os tokens de app OAuth precisam dos escopos listados abaixo. Veja Autenticação.

Endpoints

MétodoCaminhoEscopoO que faz
POST/v1/pipelinespipelines:executeCria e inicia um pipeline.
GET/v1/pipelinespipelines:readLista os seus pipelines, do mais recente para o mais antigo.
GET/v1/pipelines/:idpipelines:readRetorna o status, a etapa atual e os créditos.
GET/v1/pipelines/:id/eventspipelines:readTransmite os eventos do pipeline (server-sent events).
GET/v1/pipelines/:id/stages/:stagepipelines:readRetorna o status, a saída e o feedback do revisor de uma etapa.
GET/v1/pipelines/:id/pending-approvalspipelines:readLista as etapas que aguardam aprovação.
GET/v1/pipelines/:id/timelinepipelines:readRetorna o filme montado: cenas, durações e áudio.
GET/v1/pipelines/:id/entities?type=pipelines:readLista os personagens, os objetos, os locais ou as cenas do pipeline.
POST/v1/pipelines/:id/stages/:stage/approvepipelines:approveAprova uma etapa, opcionalmente com edições.
POST/v1/pipelines/:id/stages/:stage/rejectpipelines:approveRejeita o roteiro com um feedback, para que ele seja escrito de novo.
POST/v1/pipelines/:id/sub-gates/:gate/approvepipelines:approveAprova um ponto de verificação dentro da etapa de animação.
POST/v1/pipelines/:id/sub-gates/:gate/rejectpipelines:approveRejeita esse ponto de verificação e interrompe o pipeline.
POST/v1/pipelines/:id/entities/:sceneId/helpers/accept_match_cut_breakpipelines:approveAceita uma quebra de match cut na etapa de imagens das cenas.
POST/v1/pipelines/:id/stages/:stage/chatpipelines:approveEnvia uma mensagem ao diretor (modo guiado).
GET/v1/pipelines/:id/stages/:stage/chatpipelines:readLê o chat de uma etapa.
POST/v1/pipelines/:id/stages/:stage/chat/turns/:turnId/applypipelines:approveAplica uma alteração que o diretor propôs.
POST/v1/pipelines/:id/branchpipelines:executeExecuta de novo um pipeline concluído a partir de uma etapa, como um novo pipeline.
POST/v1/pipelines/:id/forkpipelines:executeInterrompe o pipeline e mantém o canvas dele como nós comuns.
POST/v1/pipelines/:id/cancelpipelines:executeCancela um pipeline em execução e reembolsa os créditos não gastos.

Etapas e modos

Um pipeline passa por oito etapas, em ordem. :stage em um caminho é um destes nomes.

EtapaO que produz
scriptO plano da história: o título, as cenas, o elenco, os locais e os adereços.
charactersUm personagem para cada papel do elenco.
objectsOs adereços de que a história precisa.
locationsOs lugares por onde a história passa.
shot_listAs tomadas de cada cena, com as escolhas de câmera e de continuidade.
scene_imagesUm quadro-chave para cada tomada.
animate_audio_editAs tomadas animadas, com diálogos, narração, música e a edição.
post_mergeO filme final, já juntado.

O mode que você escolhe na criação decide quem faz o pipeline avançar:

ModoO que acontece
manual (padrão)Toda etapa para em awaiting_approval. Você aprova, edita ou rejeita a etapa, e o pipeline segue.
autoO mecanismo executa cada etapa sozinho. Revisores automáticos verificam o roteiro, a cobertura do elenco, dos locais e dos adereços, e os quadros-chave. Depois de 3 vereditos bloqueantes seguidos, o pipeline falha e os créditos não gastos são reembolsados. Ele só para em uma quebra de match cut, até que todas as quebras sejam aceitas. Enquanto isso, o status continua running, e pending-approvals lista a etapa scene_images.
guidedComo manual, mais um chat com o diretor nas etapas script e post_merge.

Iniciar um pipeline

POST /v1/pipelines cria o pipeline, reserva os créditos dele e o inicia. A rota responde 201 com { id }.

curl -X POST https://app.nodaro.ai/v1/pipelines \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "root_node_id": "0e6b2f7c-4a1d-4c8e-9b3f-5d7a2c1e8f4b",
    "story_prompt": "A lighthouse keeper must restart the light before the storm hits.",
    "format": "short_film",
    "target_duration_seconds": 60,
    "mode": "auto",
    "output_resolution": "720p"
  }'
import { createClient, StaticTokenAuth } from '@nodaro/sdk'

const client = createClient({
  baseUrl: 'https://app.nodaro.ai',
  auth: new StaticTokenAuth(process.env.NODARO_API_KEY!),
})

const { id } = await client.pipelines.create({
  root_node_id: crypto.randomUUID(),
  story_prompt: 'A lighthouse keeper must restart the light before the storm hits.',
  format: 'short_film',
  target_duration_seconds: 60,
  mode: 'auto',
})
{ "id": "c2f8a4e6-1b9d-4f3a-8c7e-6d2b9f1a5e3c" }

Prop

Type

Cada formato permite uma faixa de durações:

FormatoMínimoMáximo
reel7 s90 s
commercial10 s90 s
trailer30 s180 s
short_film12 s600 s
music_video30 s600 s

Acompanhar um pipeline

GET /v1/pipelines/:id retorna o estado do pipeline. Consulte a rota periodicamente, a cada poucos segundos, ou abra GET /v1/pipelines/:id/events para receber as mudanças como server-sent events.

{
  "id": "c2f8a4e6-1b9d-4f3a-8c7e-6d2b9f1a5e3c",
  "status": "running",
  "current_stage": "scene_images",
  "mode": "auto",
  "spent_credits": 412,
  "reserved_credits": 1180,
  "upfront_credit_estimate": 1650,
  "failure_reason": null,
  "current_progress_message": "Rendering keyframe 5 of 9",
  "branched_from_pipeline_id": null,
  "branched_from_stage": null
}

status é queued, running, awaiting_approval, completed, failed, cancelled ou forked. failure_reason explica um pipeline failed.

Quando o pipeline está completed, GET /v1/pipelines/:id/timeline retorna o filme como dados que você pode renderizar ou entregar a um editor de vídeo:

{
  "fps": 24,
  "width": 1280,
  "height": 720,
  "scenes": [
    { "compositeUrl": "https://cdn.nodaro.ai/pipelines/scene-1.mp4", "durationSeconds": 8.5 },
    { "compositeUrl": "https://cdn.nodaro.ai/pipelines/scene-2.mp4", "durationSeconds": 11 }
  ],
  "musicUrl": "https://cdn.nodaro.ai/pipelines/score.mp3",
  "narrationUrl": "https://cdn.nodaro.ai/pipelines/narration.mp3"
}

Enquanto a etapa de animação está em execução, a linha do tempo também traz animateProgress: { totalShots, shotsDone, percent }. Para finalizar a montagem em um editor externo, veja Exportar uma linha do tempo.

curl https://app.nodaro.ai/v1/pipelines/c2f8a4e6-1b9d-4f3a-8c7e-6d2b9f1a5e3c \
  -H "Authorization: Bearer $NODARO_API_KEY"

curl https://app.nodaro.ai/v1/pipelines/c2f8a4e6-1b9d-4f3a-8c7e-6d2b9f1a5e3c/timeline \
  -H "Authorization: Bearer $NODARO_API_KEY"
const pipeline = await client.pipelines.get(id)
console.log(pipeline.status, pipeline.current_stage)

const timeline = await client.pipelines.getTimeline(id)
for (const scene of timeline.scenes) {
  console.log(scene.compositeUrl, scene.durationSeconds)
}

Aprovar ou rejeitar uma etapa

Nos modos manual e guided, cada etapa para em awaiting_approval. GET /v1/pipelines/:id/pending-approvals lista as etapas que aguardam, cada uma como { stage_name, output }. Leia uma etapa completa com GET /v1/pipelines/:id/stages/:stage, que retorna { status, output, critic_feedback }.

  • Aprovar. POST /v1/pipelines/:id/stages/:stage/approve retorna { ok: true }, e o pipeline segue em frente. Para alterar antes a saída da etapa, envie { edits }: um JSON Patch aplicado à saída antes da aprovação.
  • Rejeitar. Só o roteiro pode ser rejeitado. POST /v1/pipelines/:id/stages/script/reject com { feedback } retorna { ok: true }, e o mecanismo escreve o roteiro de novo levando em conta a sua observação. Qualquer outra etapa retorna 400 stage_not_implemented. Você pode rejeitar o roteiro no máximo duas vezes, e menos vezes se o revisor automático de roteiro já o tiver revisado.
curl -X POST https://app.nodaro.ai/v1/pipelines/c2f8a4e6-1b9d-4f3a-8c7e-6d2b9f1a5e3c/stages/script/approve \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "edits": [{ "op": "replace", "path": "/title", "value": "The Last Light" }] }'

curl -X POST https://app.nodaro.ai/v1/pipelines/c2f8a4e6-1b9d-4f3a-8c7e-6d2b9f1a5e3c/stages/script/reject \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "feedback": "Make the story darker and more suspenseful." }'
const approvals = await client.pipelines.pendingApprovals(id)
const { output } = await client.pipelines.getStage(id, 'script')

await client.pipelines.approveStage(id, 'script', [
  { op: 'replace', path: '/title', value: 'The Last Light' },
])
// or
await client.pipelines.rejectStage(id, 'script', 'Make the story darker and more suspenseful.')

Pontos de verificação dentro da etapa de animação

Nos modos manual e guided, a etapa animate_audio_edit pode parar em dois pontos de verificação próprios:

  • dialogue_recheck. A etapa compara a duração real dos diálogos com o plano e ajusta o tempo das cenas. Quando uma cena não consegue ficar dentro de uma margem de 10% da duração-alvo, a etapa espera a sua aprovação.
  • silent_cut_preview. A etapa monta uma prévia da montagem sem música e espera a sua aprovação antes de gerar a música e de pagar por ela.

POST /v1/pipelines/:id/sub-gates/:gate/approve retoma a etapa e retorna { ok: true, gate, resumed_at }. POST /v1/pipelines/:id/sub-gates/:gate/reject faz a etapa e o pipeline falharem e reembolsa os créditos não gastos. No modo auto, a etapa continua sem parar.

Quebras de match cut na etapa de imagens das cenas

A etapa scene_images pode parar em um terceiro ponto de verificação, match_cut_break_pending. Ela para ali em todos os modos, inclusive auto, quando um match cut planejado entre duas tomadas não se sustenta. A saída da etapa lista as tomadas em match_cut_break_pending.

As rotas de sub-gate acima não o liberam. Elas retornam 400 invalid_sub_gate, e a mensagem de erro indica a rota que libera. Aceite cada quebra com POST /v1/pipelines/:id/entities/:sceneId/helpers/accept_match_cut_break e { "shotId": "<shot id>" }. sceneId é o id da cena que contém a tomada, não o metadata.scene_id dela. GET /v1/pipelines/:id/entities?type=scene lista as cenas, cada uma com as tomadas dela em metadata.scene_node_data.shots.

Aceitar uma quebra exige o escopo pipelines:approve e não custa créditos. A chamada retorna { ok: true, pendingRemaining }, o número de quebras que ainda aguardam. Quando a última é aceita, a etapa continua.

Conversar com o diretor

No modo guided, uma etapa que aguarda aprovação tem um chat. Envie uma mensagem de até 8.000 caracteres com POST /v1/pipelines/:id/stages/:stage/chat e { message }. O diretor responde em uma frase e pode propor uma alteração.

{
  "turnId": "f1a3c5e7-9b2d-4f6a-8c1e-3d5b7f9a2c4e",
  "role": "assistant",
  "content": "I moved the keeper's reason for staying into scene 2 and tightened the ending.",
  "proposed_change": {
    "change_type": "edit_artifact",
    "json_patch": [{ "op": "replace", "path": "/scenes/1/description", "value": "The keeper finds his late wife's log and decides to stay." }]
  }
}

proposed_change é null, um edit_artifact com um json_patch, ou um suggest_branch com from_stage e um reason.

EtapaO que o diretor pode proporTurnos
scriptUma edição do plano (um JSON Patch no título, nas cenas, no elenco, nos locais ou nos adereços), ou uma derivação quando a mudança é estrutural demais para um patch.20 por pipeline
post_mergeUm diagnóstico do filme final e uma derivação a partir de uma etapa anterior. O filme em si não pode receber patch.8 por pipeline

Para aceitar uma proposta, chame POST /v1/pipelines/:id/stages/:stage/chat/turns/:turnId/apply. A rota retorna { applied: true, attemptId, newOutput } e aprova a etapa. Quando a mudança quebra o plano, por exemplo ao remover um personagem que uma cena ainda usa, ela retorna { applied: false, error }, e o diretor adiciona um turno que explica o que corrigir. Uma proposta inválida, ou uma etapa que não aguarda mais, retorna 409. GET /v1/pipelines/:id/stages/:stage/chat retorna { turns }, a conversa inteira.

Um pipeline guiado reserva créditos extras para o chat quando começa. Os créditos não usados são reembolsados.

curl -X POST https://app.nodaro.ai/v1/pipelines/c2f8a4e6-1b9d-4f3a-8c7e-6d2b9f1a5e3c/stages/script/chat \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Make the keeper'\''s motivation clearer in scene 2." }'
const reply = await client.pipelines.chatStage(id, 'script', "Make the keeper's motivation clearer in scene 2.")
if (reply.proposed_change) {
  const result = await client.pipelines.applyChatProposal(id, 'script', reply.turnId)
  if (!result.applied) console.log(result.error.code)
}

Derivar um pipeline concluído

POST /v1/pipelines/:id/branch executa de novo um pipeline completed a partir de uma etapa, como um novo pipeline. As etapas anteriores a fromStage são copiadas como aprovadas, fromStage começa a ser executada, e as etapas seguintes são criadas do zero. O pipeline original continua completed.

A derivação copia os personagens, os objetos e os locais para o novo pipeline, mas reutiliza os arquivos de imagem deles, então nenhum arquivo é duplicado. Ela começa com o chat vazio.

curl -X POST https://app.nodaro.ai/v1/pipelines/c2f8a4e6-1b9d-4f3a-8c7e-6d2b9f1a5e3c/branch \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "fromStage": "scene_images" }'
const branch = await client.pipelines.branch(id, { fromStage: 'scene_images' })
console.log(branch.pipelineId, branch.clonedStages)

A rota responde 201 com { pipelineId, clonedStages, clonedEntities }: o ID do novo pipeline, as etapas copiadas como aprovadas e o número de personagens, objetos e locais copiados. fromStage é qualquer nome de etapa da tabela acima.

Cancelar ou ramificar um pipeline

  • Cancelar. POST /v1/pipelines/:id/cancel interrompe um pipeline em execução, reembolsa os créditos reservados para o trabalho que não foi executado e retorna { ok: true }. Um pipeline que já foi concluído, falhou ou foi cancelado retorna 409 already_terminal, e nada muda.
  • Ramificar. POST /v1/pipelines/:id/fork tira o canvas do controle do pipeline. Cada nó que ele criou vira um nó comum que você pode editar, os créditos não gastos são reembolsados, e o status passa a ser forked. Uma ramificação não pode ser desfeita. Para continuar com o mecanismo, inicie um novo pipeline.

Créditos

O pipeline reserva o custo estimado quando começa; upfront_credit_estimate mostra esse valor. spent_credits e reserved_credits mostram em que ponto a execução está. Um pipeline cancelado ou que falhou reembolsa o que não gastou, e max_cost_credits limita o total. Veja Créditos.

Usar pelo MCP e pelo SDK

O SDK expõe todas as rotas como client.pipelines.*. A CLI não tem comandos de pipeline. Os assistentes de IA usam estas ferramentas MCP:

FerramentaEscopoO que faz
start_pipelinepipelines:executeInicia um pipeline. O modo padrão da ferramenta é auto.
get_pipeline_statuspipelines:readLê o status, a etapa e os créditos.
pipeline_pending_approvalspipelines:readLista as etapas que aguardam aprovação.
chat_pipeline_stage, apply_chat_proposalpipelines:approveConversa com o diretor e aplica uma proposta.
get_pipeline_stage_chatpipelines:readLê o chat de uma etapa.
branch_pipelinepipelines:executeDeriva um pipeline concluído.

Veja Film Director para o jeito guiado de dirigir um filme a partir de um assistente.

Erros

StatusCódigoSignificado
400validation_errorO corpo é inválido, por exemplo uma duração abaixo de 5 ou acima de 3.600 segundos, ou um fromStage de derivação que não é uma etapa.
400duration_out_of_boundsA duração está fora da faixa do formato, ou acima de 600 segundos.
400pipeline_not_completedFoi pedida uma derivação de um pipeline que não está completed.
400invalid_stageO envio ou a leitura de um chat indica uma etapa diferente de script, shot_list ou post_merge.
400invalid_stage_nameUma aprovação indica uma etapa que não é uma das oito. A leitura dessa etapa retorna 404 com este código.
400stage_not_implementedUma chamada de rejeição indica uma etapa diferente de script.
400invalid_change_type_for_stageFoi proposto um patch para a etapa post_merge, que só aceita uma derivação.
400invalid_sub_gateO ponto de verificação não é um dos que as rotas de sub-gate resolvem. Para match_cut_break_pending, a mensagem indica a rota que aceita cada quebra.
400shot_not_foundA tomada a aceitar não está nessa cena.
400not_a_match_cutA tomada a aceitar não tem um match cut planejado.
400invalid_entity_typeA lista de entidades foi pedida com um type diferente de character, object, location ou scene.
401unauthorizedO token está ausente, é inválido ou foi revogado.
402insufficient_creditsA conta não tem créditos para cobrir a reserva.
403edition_requiredA instância não é o Nodaro Cloud.
403insufficient_scopeUm token de app OAuth não tem o escopo da rota.
404not_foundNenhum pipeline com esse ID pertence a você. Em uma chamada de sub-gate, também significa que a etapa não está parada nesse ponto de verificação.
404pipeline_not_foundUma chamada de derivação indica um pipeline que não existe ou não é seu.
404stage_not_startedA etapa que você leu ainda não começou.
404stage_not_foundUma chamada de sub-gate chegou a um pipeline cuja etapa de animação ainda não começou. Uma aprovação ou rejeição de etapa retorna 409 com este código.
404scene_not_foundO pipeline não tem cena com esse ID.
409patch_invalidUma proposta do chat não é uma alteração válida e não pôde ser aplicada.
409stage_not_awaitingA etapa não aguarda mais aprovação, quando você aplica uma proposta do chat ou aprova com edições.
409stage_already_advancedA etapa não aguarda mais aprovação, quando você aprova sem edições ou rejeita.
409stage_not_awaiting_approvalUma chamada de sub-gate chegou a uma etapa de animação que não aguarda aprovação.
409already_terminalUma chamada de cancelamento chegou a um pipeline que já foi concluído, falhou ou foi cancelado.
409critic_retry_cap_reachedO roteiro já foi revisado duas vezes, por você ou pelo revisor automático de roteiro.
409scene_not_plannedA cena ainda não tem um plano de tomadas, então nenhuma quebra pode ser aceita nela.
501chat_not_wired_for_stageA etapa não tem um chat funcionando. Hoje, isso vale só para shot_list.

Perguntas frequentes

Última atualização

Nesta página