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.
Disponível em Nodaro Cloud
Uma produção do Studio é um workflow do Nodaro cujas configurações guardam as tomadas de um filme. Cada tomada tem uma imagem fixa enquadrada, um clipe animado opcional e o plano, os visuais, os vínculos de elenco e a voz que os geraram. client.studio lê e grava produções, então um script, um assistente de IA e o app Studio trabalham em uma mesma produção. client.shots armazena os registros compartilhados de tomadas por trás dos links de compartilhamento. Os métodos chamam a API REST de produções do Studio. Veja Produções do Studio pelo MCP para o guia de criação.
As produções do Studio são executadas no Nodaro Cloud. Onde as rotas não são servidas, todos os métodos lançam NotFoundError. Para verificar uma vez, chame client.studio.productions.list(): uma implantação com produções responde com uma página vazia, e uma sem elas lança NotFoundError.
Dois conjuntos de métodos
client.studio tem duas camadas. As duas trabalham nas mesmas produções.
| Camada | Use para | Retorna |
|---|---|---|
client.studio.productions.* | O documento da produção: criar a partir de um plano, editar com operações, gerar imagens fixas e clipes, adicionar voz e música, compartilhar e copiar | O próprio payload |
client.studio.* | Quadros planejados: recursos disponíveis, geração e revisão de quadros-chave, pacotes, salvamentos do editor e compartilhamento por link com verificação de revisão | O envelope { data } da API |
Os envelopes são tipados; o documento da produção não é. Uma produção, uma tomada e uma operação são JSON aberto, Record<string, unknown>. Tudo o que você usa para decidir o fluxo é tipado: version, rebased, receipts, warnings, os credits de uma cotação e os jobIds de uma execução. O vocabulário de operações vem do servidor: leia-o em skill().
Métodos de client.studio.productions
| Método | O que faz |
|---|---|
skill() | Lê o guia de criação, o catálogo, o esquema do plano e o guia de operação |
validatePlan(plan) | Verifica um plano, de graça |
list(opts?) | Lista as suas produções |
get(productionId, opts?) | Lê uma produção |
exportPlan(productionId, opts?) | Planeja os passos de exportação e calcula o preço deles |
create(input?) | Cria uma produção, opcionalmente a partir de um plano |
ops(productionId, input) | Aplica, ou pré-visualiza, um lote de operações |
reconcile(productionId) | Incorpora as gerações concluídas |
importPlan(productionId, plan, opts?) | Adiciona as cenas de um plano a uma produção |
describe(productionId, input) | Transforma um briefing em cenas |
generate(), generateStill(), generateClip() | Enquadra ou anima uma tomada |
frame(productionId, input) | Extrai uma imagem fixa do clipe de uma tomada |
voice(productionId, input) | Gera a fala de uma tomada |
revoice(productionId, input) | Troca as vozes do clipe de uma tomada |
music(productionId, input) | Cria a trilha sonora do filme |
share(), unshare(), clone() | Abre ou fecha o link de compartilhamento, ou copia a produção |
client.studio.productions
productions.skill()
Retorna o guia de criação, o catálogo completo, o JSON Schema do plano e o guia de operação, gerados a partir da versão que roda no servidor. É gratuito.
skill(): Promise<{ skill: string; catalog: string; schema: Record<string, unknown>; operating: string; generatedFrom: object }>const { skill, schema, operating } = await client.studio.productions.skill()operating lista as operações que ops() aceita. Leia-o em tempo de execução em vez de fixar o vocabulário no código.
productions.validatePlan(plan)
Verifica um plano antes que ele vire uma produção. É gratuito, não armazena nada e resolve os nomes do elenco com base na sua biblioteca. Corrija os errors e valide de novo até valid ser true; depois, chame create({ plan }).
validatePlan(plan: Record<string, unknown>): Promise<{
valid: boolean
errors: Array<{ path: string; message: string; hint?: string }>
warnings: Array<{ path: string; message: string; hint?: string }>
summary?: { name?: string; scenes: number; shots: number; cast: number; bound: number }
}>Prop
Type
const check = await client.studio.productions.validatePlan(plan)
if (!check.valid) console.log(check.errors)summary.bound conta as entradas do elenco que corresponderam a um personagem da sua biblioteca.
productions.list(opts?)
Lista as suas produções, das mais recentes para as mais antigas.
list(opts?: { limit?: number; cursor?: string; includeArchived?: boolean }): Promise<{ data: StudioProduction[]; nextCursor?: string }>Prop
Type
const { data: productions } = await client.studio.productions.list({ limit: 20 })productions.get(productionId, opts?)
Lê uma produção. É uma leitura pura e nunca incorpora um job concluído, então chame reconcile() antes quando estiver esperando por um.
get(productionId: string, opts?: { detail?: "summary" | "full"; shotId?: string }): Promise<StudioProduction>Prop
Type
const production = await client.studio.productions.get(productionId, { detail: "full" })productions.exportPlan(productionId, opts?)
Retorna os passos ordenados que montam o filme, com os preços deles. Não executa nada e não gasta nada: execute os passos você mesmo com os métodos comuns de nós.
exportPlan(productionId: string, opts?: { upscale?: boolean }): Promise<{
canExport: boolean
steps: Array<{ id: string; label: string; node: string; creditModel: string; credits: number | null; params: Record<string, unknown> }>
resultStepId: string | null
estimate: number | null
unpriced: string[]
}>Prop
Type
const plan = await client.studio.productions.exportPlan(productionId)
console.log(plan.canExport, plan.estimate)
for (const step of plan.steps) console.log(step.id, step.label, step.node, step.credits)canExport é false quando a produção tem menos de dois clipes. estimate é null quando algum passo não tem preço, porque uma soma parcial subestimaria o custo, e unpriced indica os modelos desses passos. O node de cada passo é um tipo de nó, como merge-video-audio, combine-videos ou video-upscale.
productions.create(input?)
Cria uma produção e, opcionalmente, incorpora um plano na mesma chamada.
create(input?: { name?: string; plan?: Record<string, unknown> }): Promise<{
production: StudioProduction
warnings?: Array<{ path: string; message: string; hint?: string }>
summary?: { shotsAdded: number; castEnrolled: number; castBound: number }
}>Prop
Type
const { production, summary } = await client.studio.productions.create({ name: "Rome chase", plan })productions.ops(productionId, input)
Aplica um lote de operações a uma produção. Toda alteração é uma operação, endereçada por uma chave estável, como o ID de uma tomada, o slug de um papel ou o ID do job de um resultado, nunca pela posição.
ops(productionId: string, input: StudioOpsRequest): Promise<StudioOpsResponse>
ops(productionId: string, input: StudioOpsRequest & { dryRun: true }): Promise<StudioOpsDryRunResponse>Prop
Type
const result = await client.studio.productions.ops(productionId, {
ops: [/* operations from the operating guide */],
baseVersion: version,
clientRequestId: crypto.randomUUID(),
})
version = result.version // carry it forward as the next baseVersion
for (const r of result.receipts) console.log(r.summary)- Atômico. Uma operação inválida recusa o lote inteiro com um
StudioOpErrorcujoopIndexa identifica, e nada é gravado. - Rebase automático. Duas pessoas podem editar uma produção ao mesmo tempo. Um lote montado sobre uma versão mais antiga continua sendo aplicado à mais recente, e
rebasedétrue. - Recibos.
receiptstem uma linha no pretérito por operação, como “Deleted take 2 of Shot 1 (in the bin)”. Quando o efeito de uma operação vai além do que ela nomeia, oimpactdela lista oskeyframeIdse osshotIdsa atualizar. - Adote a resposta. Substitua a sua cópia por
productione leveversionadiante. Não mescle a resposta com a sua cópia antiga.
Pré-visualize um lote. Com dryRun: true, a resposta diz o que o lote faria, para que uma pessoa possa aprovar antes as edições de um assistente. Ela tem dryRun, version, receipts e warnings, e nenhuma production. Cada recibo adiciona class: S seguro, D exclui, P muda quem pode acessar o trabalho, $ gasta créditos. Ele também adiciona restorable, que só está presente quando a operação colocou algo na lixeira. Leia-o como restorable ?? false.
Escreva dryRun: true como um literal no próprio objeto da chamada. Passado por uma variável, ele se amplia para boolean, e a chamada é tipada como uma aplicação, embora continue sendo uma prévia.
Uma prévia envia duas requisições: primeiro um lote vazio que comprova que a implantação consegue pré-visualizar, depois o seu lote. Caso contrário, uma implantação que não consegue pré-visualizar aplicaria o seu lote sem avisar. Dois erros podem ocorrer:
import { StudioPreviewAppliedError, StudioPreviewUnavailable } from "@nodaro/sdk"
try {
const preview = await client.studio.productions.ops(productionId, { ops, baseVersion, dryRun: true })
for (const r of preview.receipts) console.log(r.class, r.summary, r.restorable ?? false)
} catch (err) {
if (err instanceof StudioPreviewUnavailable) {
// Nothing was sent. Say that no preview is available; do not apply the batch instead.
} else if (err instanceof StudioPreviewAppliedError) {
// The batch was applied. Adopt err.applied.production and err.applied.version.
// Do not send it again. When err.applied is undefined, read the production first.
} else {
throw err
}
}productions.reconcile(productionId)
Incorpora todas as gerações que terminaram desde a última vez que você verificou e informa o que ainda está em execução. É a única chamada que transforma jobs concluídos em resultados sem o app aberto, e ela só grava quando algo foi incorporado.
reconcile(productionId: string): Promise<{
landed: string[]
pending: string[]
failed: string[]
warnings: string[]
production: StudioProduction
version: number
}>Prop
Type
const { landed, pending } = await client.studio.productions.reconcile(productionId)landed lista os jobs cuja mídia já está na produção, pending os jobs ainda em execução e failed os jobs que falharam ou foram cancelados.
productions.importPlan(productionId, plan, opts?)
Adiciona as cenas de um plano a uma produção existente.
importPlan(productionId: string, plan: Record<string, unknown>, opts?: { mode?: "append" }): Promise<{
production: StudioProduction
warnings?: Array<{ path: string; message: string; hint?: string }>
summary?: { shotsAdded: number; castEnrolled: number; castBound: number }
}>Prop
Type
await client.studio.productions.importPlan(productionId, extraScenesPlan)productions.describe(productionId, input)
Transforma um briefing em cenas com o Diretor. Inicia um job e retorna imediatamente; as cenas são incorporadas por reconcile(). A produção volta com a execução registrada como um rascunho pendente.
describe(productionId: string, input: {
brief: string
llmModel: string
mode?: "append" | "replace"
label?: string
clientRequestId?: string
}): Promise<{ production: StudioProduction; jobId: string }>Prop
Type
const { jobId } = await client.studio.productions.describe(productionId, {
brief: "A courier races across Rome in the rain to deliver a violin.",
llmModel,
})Gerar imagens fixas e clipes
generateStill() enquadra uma tomada, generateClip() a anima e generate() faz uma coisa ou outra conforme kind. Uma execução envia os jobs, registra um marcador pendente na produção e retorna: nada fica esperando por minutos. A requisição é montada no servidor a partir do próprio plano, dos visuais e das referências da tomada, então um script e um clique no app produzem a mesma mídia.
generate(productionId: string, input: StudioGenerateRequest): Promise<StudioGenerateResult>
generateStill(productionId: string, shotId: string, opts?: StudioGenerateOptions): Promise<StudioGenerateResult>
generateClip(productionId: string, shotId: string, opts?: StudioGenerateOptions): Promise<StudioGenerateResult>Prop
Type
import { isStudioGenerateEstimate } from "@nodaro/sdk"
const quote = await client.studio.productions.generateStill(productionId, "shot-2", { count: 2, dryRun: true })
if (isStudioGenerateEstimate(quote)) console.log(quote.credits) // null means unpriced, not free
const run = await client.studio.productions.generateStill(productionId, "shot-2", {
count: 2,
clientRequestId: crypto.randomUUID(),
})- Faça a cotação antes.
dryRun: truecalcula o preço da execução e não grava nada. Restrinja o tipo da resposta comisStudioGenerateEstimate(). - Repita com segurança. Com o mesmo
clientRequestId, uma nova tentativa responde com os jobs que a primeira chamada iniciou, marcados comdeduped: true, e não envia nem cobra nada. Nunca repita uma chamada paga sem ele. Todas as chamadas pagas desta página o aceitam, incluindoframe()evoice(). - A via é escolhida para você. Para um clipe, a rota de vídeo é escolhida a partir das entradas da tomada e retornada como
lane:generate-videooutext-to-video.
productions.frame(productionId, input)
Extrai uma imagem fixa do clipe ativo de uma tomada e a coloca onde target indica. Espera pelo job, que leva segundos, e retorna a produção alterada e a url da imagem.
frame(productionId: string, input: {
shotId: string
mode?: "first" | "last" | "timestamp"
timestamp?: number
target?: "new-shot" | "start-frame" | "end-frame" | "still"
clientRequestId?: string
}): Promise<StudioMediaResponse>Prop
Type
const { url } = await client.studio.productions.frame(productionId, { shotId: "shot-2", mode: "last" })productions.voice(productionId, input)
Gera a fala de uma tomada e a registra na tomada. Espera pelo job.
voice(productionId: string, input: {
shotId: string
text: string
voiceId?: string
voiceType?: "premade" | "custom" | "library"
ttsProvider?: string
delivery?: Record<string, number>
clientRequestId?: string
}): Promise<StudioMediaResponse>Prop
Type
await client.studio.productions.voice(productionId, { shotId: "shot-3", text: "We're out of time." })productions.revoice(productionId, input)
Troca as vozes do clipe ativo de uma tomada. Leva minutos, então retorna um jobId, e o novo clipe é incorporado pelo marcador dele.
revoice(productionId: string, input: { shotId: string; plan: Record<string, unknown>; clientRequestId?: string }): Promise<{ production: StudioProduction; jobId: string }>Prop
Type
const { jobId } = await client.studio.productions.revoice(productionId, {
shotId: "shot-3",
plan: recastPlan, // the speaker-ordered plan the voice recast route takes
})productions.music(productionId, input)
Cria a trilha sonora do filme. A faixa pronta é incorporada pelo marcador pendente dela.
music(productionId: string, input: {
prompt: string
duration?: number
instrumental?: boolean
vocalGender?: string
model?: string
clientRequestId?: string
}): Promise<{ production: StudioProduction; jobId: string }>Prop
Type
const { jobId } = await client.studio.productions.music(productionId, {
prompt: "Tense strings building to a chase",
instrumental: true,
})Compartilhar e copiar
share() abre a visualização por link e unshare() a fecha de novo. Compartilhar é uma chamada própria, nunca uma operação, então quem pode ver o trabalho nunca muda como efeito colateral de uma edição. clone() copia uma produção que é sua ou que você pode ver para o seu próprio projeto do Studio.
share(productionId: string): Promise<StudioProduction>
unshare(productionId: string): Promise<StudioProduction>
clone(productionId: string, input?: { name?: string }): Promise<StudioProduction>Prop
Type
await client.studio.productions.share(productionId)
const copy = await client.studio.productions.clone(productionId, { name: "Rome chase, take 2" })Uma cópia começa privada e não arquivada: o compartilhamento e o arquivamento nunca são copiados. Ela é copiada pela sua visão da origem, então a lixeira de outra pessoa não vem junto.
client.studio: quadros planejados
Estes métodos cobrem os quadros-chave planejados e a revisão deles. Verifique capabilities() antes de oferecer um controle, e chame reconcile() uma vez ao reabrir uma produção, porque a resposta de um envio pode ter se perdido. Nada aqui inicia uma geração ou aceita um candidato, a menos que você chame o método que faz isso.
| Método | O que faz |
|---|---|
capabilities() | Lê as versões do plano e as operações que esta implantação aceita |
skill(), list(), validatePlan(), create() | As mesmas leituras e a mesma criação da camada de produções, no envelope |
get(id, options?) | Lê uma produção com os recursos dela |
edit(id, input) | Aplica operações com condições de revisão |
saveEditorState(id, input) | Salva campos comuns do editor com base na revisão carregada |
generateKeyframe(id, input) | Gera um quadro planejado, sem aceitá-lo |
generateShot(id, input) | Faz a cotação ou envia uma imagem fixa ou um clipe |
acceptKeyframe(id, review, concurrency?) | Aceita um candidato revisado |
reconcile(id) | Registra jobs concluídos, sem aceitar nada |
setShared(id, input) | Compartilha ou deixa de compartilhar, vinculado à revisão que você conferiu |
clone(id, input?) | Copia uma produção salva |
importBundle(input) | Importa uma produção portátil |
appendBundle(id, input) | Anexa um pacote a uma produção |
studio.capabilities()
Retorna as versões do plano e quais operações de quadros planejados esta implantação aceita.
capabilities(): Promise<{ data: StudioProductionCapabilities }>const { data: caps } = await client.studio.capabilities()
if (caps.operations.generateKeyframes) showGenerateFrameButton()operations tem uma flag por operação, como readKeyframes, editKeyframes, generateKeyframes, acceptKeyframes, rejectKeyframes, editSequencePlans, generateLinkedClips, retakeLinkedClips, saveEditorState, revisionedSharing, editableSharedCopies, cloneLinkedProductions, importPlannedBundles, importLinkedBundles, appendPlannedBundles e appendLinkedBundles. automaticAcceptance e unattendedGeneration são sempre false.
studio.skill(), list(), validatePlan() e create()
As mesmas chamadas que productions.skill(), list(), validatePlan() e create(), retornadas no envelope { data }. Em list(), as linhas ficam em response.data.data.
skill(): Promise<{ data: Record<string, unknown> }>
list(options?: { limit?: number; cursor?: string; includeArchived?: boolean }): Promise<{ data: {
data: Array<{ id: string; name: string; version: number; updatedAt: string; thumbnailUrl: string | null; shared: boolean; archived: boolean; shotCount: number }>
nextCursor?: string
} }>
validatePlan(plan: Record<string, unknown>): Promise<{ data: { valid: boolean; errors: object[]; warnings: object[]; summary?: object } }>
create(input: { name?: string; plan?: Record<string, unknown> }): Promise<{ data: StudioProductionReply }>Prop
Type
const { data: page } = await client.studio.list({ limit: 20 })
for (const row of page.data) console.log(row.name, row.shotCount)studio.get(id, options?)
Lê uma produção com os recursos dela. Nunca incorpora jobs.
get(id: string, options?: { detail?: "summary" | "full"; shotId?: string }): Promise<{ data: StudioProductionReply }>Prop
Type
const { data: { production } } = await client.studio.get(productionId, { detail: "full" })
const frame = production.keyframes?.[0] // { id, label, revision, previewUrl, acceptedUrl, pending, ... }studio.edit(id, input)
Aplica operações com condições de revisão (POST .../:id/ops), no envelope. Use uma baseVersion estrita para remove_shot, restore_trashed e purge_trashed, e desvincule um segmento de sequência vinculado antes de remover a cena dele.
edit(id: string, input: { ops: Array<{ op: string; [field: string]: unknown }>; baseVersion?: number; strict?: boolean; clientRequestId?: string }): Promise<{ data: StudioProductionReply & { version: number; rebased: boolean; receipts: object[] } }>Prop
Type
await client.studio.edit(productionId, {
ops: [{ op: "reject_keyframe_result", keyframeId, expectedRevision, resultKey, expectedAcceptedResultKey, reason: "Face drifted" }],
baseVersion: version,
strict: true,
})Algumas operações de quadros planejados enviadas por edit():
reject_keyframe_resultregistra Needs revision sem gerar nada. Exigeoperations.rejectKeyframes.update_sequence_planedita os segmentos ordenados de uma sequência, cada um{ shotId, startKeyframeId, endKeyframeId }, e mantém os IDs das cenas. Exigeoperations.editSequencePlans.detach_sequence_segmenttorna um segmento independente, commodedefinido comoclearoukeep-accepted. Exigeoperations.editSequencePlans.purge_trashedesvazia as entradas da lixeira que você mostra, eclear_trashesvazia todas as lixeiras, incluindo as dos quadros planejados.
studio.saveEditorState(id, input)
Salva campos comuns do editor com base na revisão que você carregou. Verifique operations.saveEditorState antes. O salvamento é sempre estrito: um conflito falha com um 409, então mantenha o rascunho local e recarregue antes de resolver o conflito.
saveEditorState(id: string, input: { expectedVersion: number; graph: object; clientRequestId?: string })Prop
Type
await client.studio.saveEditorState(productionId, { expectedVersion: version, graph })O salvamento não pode alterar planos de quadros, aceitação, vínculos de extremidade, histórico de jobs, entradas protegidas da lixeira nem compartilhamento. Use as ações próprias de cada um.
studio.generateKeyframe(id, input)
Gera um quadro planejado sem aceitá-lo. Não há simulação (dry run) para quadros.
generateKeyframe(id: string, input: { keyframeId: string; expectedRevision: number; clientRequestId?: string; overrides?: Record<string, unknown> }): Promise<{ data: { jobIds: string[]; deduped?: true; lane?: string } }>Prop
Type
const { data: caps } = await client.studio.capabilities()
const { data: { production } } = await client.studio.get(productionId, { detail: "full" })
const frame = production.keyframes?.[0]
if (frame && caps.operations.generateKeyframes) {
const { data: generation } = await client.studio.generateKeyframe(productionId, {
keyframeId: frame.id,
expectedRevision: frame.revision,
clientRequestId: crypto.randomUUID(),
})
// follow generation.jobIds with client.jobs, then call reconcile()
}Gerar não aceita um candidato e não cria um retrato de personagem. Uma referência de elenco que tem só uma descrição não precisa de retrato.
studio.generateShot(id, input)
Faz a cotação ou envia uma imagem fixa ou um clipe para uma tomada.
generateShot(id: string, input: StudioShotGenerationInput): Promise<{ data: StudioGenerationReply }>Prop
Type
const { data: quote } = await client.studio.generateShot(productionId, { kind: "clip", shotId, dryRun: true })
if ("inputHash" in quote) {
await client.studio.generateShot(productionId, {
kind: "clip",
shotId,
expectedInputHash: quote.inputHash,
clientRequestId: crypto.randomUUID(),
})
}Clipes vinculados. A cotação de um clipe entre quadros planejados inclui inputHash, os endpointPins aceitos, as configurações normalizadas de duração, resolução, proporção e som, e o creditIdentifier usado no preço. Passe o inputHash conferido como expectedInputHash. Se as configurações ou os quadros aceitos mudaram desde a cotação, a chamada falha com 409 sequence_quote_changed antes de enviar qualquer coisa; peça uma nova cotação. Os créditos de uma cotação são uma estimativa: a geração reserva o preço atual.
Refações. Quando operations.retakeLinkedClips é true, passe retakeResultKey com kind: "clip" e shotId, e faça a cotação com dryRun: true. Envie com o expectedInputHash conferido e um novo clientRequestId, e deixe de fora mode, overrides e count. Uma refação reutiliza a requisição original e as imagens de quadro guardadas, mesmo depois que o plano ou a aceitação mudaram. Os takes anteriores continuam no histórico. Um take sem uma requisição original verificável ou sem imagens guardadas é recusado, e uma refação não reproduz os mesmos bytes de vídeo.
studio.acceptKeyframe(id, review, concurrency?)
Aceita um candidato revisado para um quadro planejado. É um passo separado e explícito: a geração nunca o chama.
acceptKeyframe(id: string, review: StudioKeyframeAcceptanceInput, concurrency?: { baseVersion?: number; strict?: boolean; clientRequestId?: string })Prop
Type
await client.studio.acceptKeyframe(productionId, {
keyframeId: frame.id,
expectedRevision: frame.revision,
resultKey,
expectedAcceptedResultKey: frame.acceptedResultKey,
requirementChecks, // one { requirementId, outcome } per requirement of the frame
})Um conflito lança o erro de sempre. O SDK nunca escolhe outro resultado nem tenta de novo com uma revisão mais recente por conta própria.
studio.reconcile(id)
Registra jobs concluídos, sem aceitar nenhum candidato e sem iniciar uma geração. Também verifica jobs de cenas na lixeira: um clipe concluído fica no grafo armazenado dessa cena, e você o recupera com restore_trashed.
reconcile(id: string): Promise<{ data: StudioProductionReply & { landed: string[]; pending: string[]; failed: string[]; version: number } }>Prop
Type
const { data } = await client.studio.reconcile(productionId)
console.log(data.landed, data.pending)studio.setShared(id, input)
Compartilha uma produção ou deixa de compartilhá-la, vinculado à revisão que você conferiu. Verifique operations.revisionedSharing e passe expectedVersion: uma edição simultânea então falha com 409 workflow_conflict, e o SDK não tenta de novo. Só quem pode alterar a visibilidade pode usar este método.
setShared(id: string, input: { shared: boolean; allowEditableCopy?: boolean; expectedVersion?: number }): Promise<{ data: StudioProductionReply }>Prop
Type
await client.studio.setShared(productionId, { shared: true, allowEditableCopy: true, expectedVersion: version })Com allowEditableCopy, um proprietário ou administrador do espaço de trabalho permite que quem vê o link copie o plano salvo, os prompts, as descrições do elenco, as entradas de referência guardadas e o histórico de takes. A lixeira e as notas de revisão privadas nunca vêm junto. As cópias começam privadas, sem nenhum quadro aceito. Desativar a cópia, ou deixar de compartilhar, bloqueia novas cópias; as cópias já feitas continuam independentes.
studio.clone(id, input?)
Copia uma produção salva. Verifique operations.cloneLinkedProductions antes de copiar uma produção com quadros vinculados, e passe a expectedVersion dela que você carregou: uma origem alterada falha com um 409.
clone(id: string, input?: { name?: string; projectId?: string; expectedVersion?: number }): Promise<{ data: StudioProductionReply }>Prop
Type
const { data: { production: copy } } = await client.studio.clone(productionId, {
name: "Rome chase copy",
expectedVersion: version,
})A cópia começa privada. Ela mantém as entradas dos quadros, que contam no seu armazenamento, recebe novos IDs de quadros, cenas e sequências e não traz jobs em execução nem quadros aceitos. Revise e aceite os quadros dela antes de gerar mídia que dependa deles. Copiar não envia nenhuma geração.
studio.importBundle(input)
Importa uma produção portátil como uma nova produção privada, com novos IDs de cenas, quadros e sequências (POST .../import-bundle). Verifique operations.importPlannedBundles para receitas e planos sem mídia, e importLinkedBundles para pacotes com mídia de quadros guardada.
importBundle(input: { bundle: Record<string, unknown>; projectId?: string }): Promise<{ data: StudioProductionReply }>Prop
Type
const { data: { production } } = await client.studio.importBundle({ bundle })Um pacote vinculado indica a produção de origem dele; o servidor verifica se ela é sua e confere cada imagem guardada antes de copiar qualquer coisa. Falta de acesso ou procedência forjada recusam a importação antes de a nova produção ser criada. Nenhum dos dois tipos de importação traz aceitação ou jobs em execução, e nenhum deles gera mídia.
studio.appendBundle(id, input)
Anexa um pacote completo a uma produção editável, com novos IDs e uma verificação exata de revisão (POST .../:id/import-bundle). Um token OAuth precisa de workflows:write, e você precisa de acesso de edição à produção. Verifique appendPlannedBundles ou appendLinkedBundles antes.
appendBundle(id: string, input: { bundle: Record<string, unknown>; expectedVersion: number; afterShotId?: string; applyFilm?: boolean }): Promise<{
data: { production: StudioProductionRecord; importedShotIds: string[]; importedKeyframeIds: string[] }
}>Prop
Type
const { data } = await client.studio.appendBundle(productionId, { bundle, expectedVersion: version })
console.log(data.importedShotIds)As cenas, os quadros, os jobs, o compartilhamento e as outras configurações existentes continuam como estão; os papéis de elenco importados são mesclados. Os quadros importados precisam ser aceitos de novo. Um afterShotId desconhecido ou uma expectedVersion desatualizada fazem a chamada falhar.
client.shots
Registros de tomadas por trás dos links de compartilhamento /s/:id, para o Share and Remix. Uma tomada guarda o estado de um construtor: as escolhas dos seletores, os prompts, os modelos de destino, as referências de menções @ e as URLs dos resultados. Esse estado fica sob um ID de 12 caracteres impossível de adivinhar, que também é a chave de compartilhamento. As tomadas são privadas por padrão; compartilhar é uma mudança de visibilidade que você faz.
create(input?: CreateShotInput): Promise<{ id: string }>
get(id: string): Promise<{ shot: Shot }>
update(id: string, input: UpdateShotInput): Promise<{ shot: Shot }>
delete(id: string): Promise<void>Prop
Type
const { id } = await client.shots.create({ mode: "single", freeText: "A lighthouse in a storm", models: ["nano-banana-2"] })
await client.shots.update(id, { visibility: "public" }) // anyone with the id can now read it
const { shot } = await client.shots.get(id)Uma tomada pública pode ser lida por qualquer pessoa que tenha o ID dela. Uma tomada privada só pode ser lida pelo proprietário, e as outras pessoas recebem NotFoundError. Só o proprietário pode atualizar ou excluir uma tomada.
Perguntas frequentes
Páginas relacionadas
Produções do Studio
Produções do Studio
Erros
Recast
Jobs e execuções
Última atualização
Biblioteca da comunidade
Explore a biblioteca da comunidade do Nodaro em TypeScript, clone na sua conta personagens, locais e objetos, favorite-os e denuncie uma publicação.
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.