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étodo | Caminho | Escopo | O que faz |
|---|---|---|---|
POST | /v1/pipelines | pipelines:execute | Cria e inicia um pipeline. |
GET | /v1/pipelines | pipelines:read | Lista os seus pipelines, do mais recente para o mais antigo. |
GET | /v1/pipelines/:id | pipelines:read | Retorna o status, a etapa atual e os créditos. |
GET | /v1/pipelines/:id/events | pipelines:read | Transmite os eventos do pipeline (server-sent events). |
GET | /v1/pipelines/:id/stages/:stage | pipelines:read | Retorna o status, a saída e o feedback do revisor de uma etapa. |
GET | /v1/pipelines/:id/pending-approvals | pipelines:read | Lista as etapas que aguardam aprovação. |
GET | /v1/pipelines/:id/timeline | pipelines:read | Retorna o filme montado: cenas, durações e áudio. |
GET | /v1/pipelines/:id/entities?type= | pipelines:read | Lista os personagens, os objetos, os locais ou as cenas do pipeline. |
POST | /v1/pipelines/:id/stages/:stage/approve | pipelines:approve | Aprova uma etapa, opcionalmente com edições. |
POST | /v1/pipelines/:id/stages/:stage/reject | pipelines:approve | Rejeita o roteiro com um feedback, para que ele seja escrito de novo. |
POST | /v1/pipelines/:id/sub-gates/:gate/approve | pipelines:approve | Aprova um ponto de verificação dentro da etapa de animação. |
POST | /v1/pipelines/:id/sub-gates/:gate/reject | pipelines:approve | Rejeita esse ponto de verificação e interrompe o pipeline. |
POST | /v1/pipelines/:id/entities/:sceneId/helpers/accept_match_cut_break | pipelines:approve | Aceita uma quebra de match cut na etapa de imagens das cenas. |
POST | /v1/pipelines/:id/stages/:stage/chat | pipelines:approve | Envia uma mensagem ao diretor (modo guiado). |
GET | /v1/pipelines/:id/stages/:stage/chat | pipelines:read | Lê o chat de uma etapa. |
POST | /v1/pipelines/:id/stages/:stage/chat/turns/:turnId/apply | pipelines:approve | Aplica uma alteração que o diretor propôs. |
POST | /v1/pipelines/:id/branch | pipelines:execute | Executa de novo um pipeline concluído a partir de uma etapa, como um novo pipeline. |
POST | /v1/pipelines/:id/fork | pipelines:execute | Interrompe o pipeline e mantém o canvas dele como nós comuns. |
POST | /v1/pipelines/:id/cancel | pipelines:execute | Cancela 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.
| Etapa | O que produz |
|---|---|
script | O plano da história: o título, as cenas, o elenco, os locais e os adereços. |
characters | Um personagem para cada papel do elenco. |
objects | Os adereços de que a história precisa. |
locations | Os lugares por onde a história passa. |
shot_list | As tomadas de cada cena, com as escolhas de câmera e de continuidade. |
scene_images | Um quadro-chave para cada tomada. |
animate_audio_edit | As tomadas animadas, com diálogos, narração, música e a edição. |
post_merge | O filme final, já juntado. |
O mode que você escolhe na criação decide quem faz o pipeline avançar:
| Modo | O que acontece |
|---|---|
manual (padrão) | Toda etapa para em awaiting_approval. Você aprova, edita ou rejeita a etapa, e o pipeline segue. |
auto | O 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. |
guided | Como 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:
| Formato | Mínimo | Máximo |
|---|---|---|
reel | 7 s | 90 s |
commercial | 10 s | 90 s |
trailer | 30 s | 180 s |
short_film | 12 s | 600 s |
music_video | 30 s | 600 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/approveretorna{ 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/rejectcom{ feedback }retorna{ ok: true }, e o mecanismo escreve o roteiro de novo levando em conta a sua observação. Qualquer outra etapa retorna400 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.
| Etapa | O que o diretor pode propor | Turnos |
|---|---|---|
script | Uma 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_merge | Um 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/cancelinterrompe 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 retorna409 already_terminal, e nada muda. - Ramificar.
POST /v1/pipelines/:id/forktira 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 serforked. 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:
| Ferramenta | Escopo | O que faz |
|---|---|---|
start_pipeline | pipelines:execute | Inicia um pipeline. O modo padrão da ferramenta é auto. |
get_pipeline_status | pipelines:read | Lê o status, a etapa e os créditos. |
pipeline_pending_approvals | pipelines:read | Lista as etapas que aguardam aprovação. |
chat_pipeline_stage, apply_chat_proposal | pipelines:approve | Conversa com o diretor e aplica uma proposta. |
get_pipeline_stage_chat | pipelines:read | Lê o chat de uma etapa. |
branch_pipeline | pipelines:execute | Deriva um pipeline concluído. |
Veja Film Director para o jeito guiado de dirigir um filme a partir de um assistente.
Erros
| Status | Código | Significado |
|---|---|---|
400 | validation_error | O 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. |
400 | duration_out_of_bounds | A duração está fora da faixa do formato, ou acima de 600 segundos. |
400 | pipeline_not_completed | Foi pedida uma derivação de um pipeline que não está completed. |
400 | invalid_stage | O envio ou a leitura de um chat indica uma etapa diferente de script, shot_list ou post_merge. |
400 | invalid_stage_name | Uma aprovação indica uma etapa que não é uma das oito. A leitura dessa etapa retorna 404 com este código. |
400 | stage_not_implemented | Uma chamada de rejeição indica uma etapa diferente de script. |
400 | invalid_change_type_for_stage | Foi proposto um patch para a etapa post_merge, que só aceita uma derivação. |
400 | invalid_sub_gate | O 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. |
400 | shot_not_found | A tomada a aceitar não está nessa cena. |
400 | not_a_match_cut | A tomada a aceitar não tem um match cut planejado. |
400 | invalid_entity_type | A lista de entidades foi pedida com um type diferente de character, object, location ou scene. |
401 | unauthorized | O token está ausente, é inválido ou foi revogado. |
402 | insufficient_credits | A conta não tem créditos para cobrir a reserva. |
403 | edition_required | A instância não é o Nodaro Cloud. |
403 | insufficient_scope | Um token de app OAuth não tem o escopo da rota. |
404 | not_found | Nenhum 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. |
404 | pipeline_not_found | Uma chamada de derivação indica um pipeline que não existe ou não é seu. |
404 | stage_not_started | A etapa que você leu ainda não começou. |
404 | stage_not_found | Uma 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. |
404 | scene_not_found | O pipeline não tem cena com esse ID. |
409 | patch_invalid | Uma proposta do chat não é uma alteração válida e não pôde ser aplicada. |
409 | stage_not_awaiting | A etapa não aguarda mais aprovação, quando você aplica uma proposta do chat ou aprova com edições. |
409 | stage_already_advanced | A etapa não aguarda mais aprovação, quando você aprova sem edições ou rejeita. |
409 | stage_not_awaiting_approval | Uma chamada de sub-gate chegou a uma etapa de animação que não aguarda aprovação. |
409 | already_terminal | Uma chamada de cancelamento chegou a um pipeline que já foi concluído, falhou ou foi cancelado. |
409 | critic_retry_cap_reached | O roteiro já foi revisado duas vezes, por você ou pelo revisor automático de roteiro. |
409 | scene_not_planned | A cena ainda não tem um plano de tomadas, então nenhuma quebra pode ser aceita nela. |
501 | chat_not_wired_for_stage | A etapa não tem um chat funcionando. Hoje, isso vale só para shot_list. |
Perguntas frequentes
Páginas relacionadas
História → vídeo
Film Director
Produções do Studio
Workflows
Créditos
Última atualização
Biblioteca da comunidade
Explore, pesquise, favorite e clone personagens, locais e objetos da Biblioteca da comunidade pela API REST, e denuncie uma publicação para moderação.
Assistente de prompt
Transforme uma ideia bruta em um prompt otimizado via REST: peça perguntas guiadas, monte um prompt com as respostas ou melhore um prompt em uma chamada.