Edição
Edite podcasts e vídeos longos em TypeScript. Detecte silêncio, sincronize gravações, planeje cortes a partir de uma transcrição e renderize uma EDL.
client.edit reúne as ferramentas de edição para podcasts e vídeos longos. Ele encontra silêncios, mede o deslocamento de tempo entre várias gravações, planeja um corte a partir de uma transcrição e renderiza uma lista de decisões de edição (EDL) em um vídeo ou arquivo de áudio final. Quatro métodos iniciam um job e retornam { jobId }, que você consulta periodicamente com client.jobs.getStatus(). Um quinto, remapTranscript(), roda localmente, sem requisição.
Métodos
| Método | Endpoint | O que faz |
|---|---|---|
edit.silenceDetect(input) | POST /v1/silence-detect | Encontra os trechos silenciosos de uma fonte de áudio ou vídeo |
edit.audioSync(input) | POST /v1/audio-sync | Mede o deslocamento de tempo entre gravações, de 2 a 6 |
edit.editPlan(input) | POST /v1/edit-plan | Planeja um corte mais enxuto, clipes curtos ou capítulos a partir de uma transcrição |
edit.applyEdl(input) | POST /v1/apply-edl | Renderiza uma EDL em um vídeo ou um arquivo de áudio |
edit.remapTranscript(edl, transcript) | Nenhum, local | Move os tempos de uma transcrição para a linha do tempo editada |
Editar um podcast pelo código
Transcrever a gravação
Execute client.audio.transcribe() com um mecanismo que retorne os tempos por palavra. O output_data.json dele é a transcrição de que o plano precisa.
Encontrar o silêncio
Execute silenceDetect() na gravação principal. O output_data.json dele contém os trechos silenciosos.
Planejar o corte
Execute editPlan() no modo tighten com a transcrição, as fontes e o silêncio. Leia o plano com unwrapEditPlanOutput().
Renderizar
Passe o plano para applyEdl(). O job concluído contém o vídeo ou o áudio editado.
import { unwrapEditPlanOutput } from "@nodaro/sdk"
async function outputOf(jobId: string): Promise<any> {
for (;;) {
const { data } = await client.jobs.getStatus(jobId)
if (data.status === "completed") return data.output_data
if (data.status === "failed" || data.status === "cancelled") throw new Error(data.error_message ?? data.status)
await new Promise((resolve) => setTimeout(resolve, 3_000))
}
}
// 1. Transcribe with word timings
const tr = await client.audio.transcribe({ audioUrl: masterUrl, provider: "elevenlabs-stt" })
const transcript = (await outputOf(tr.jobId)).json
// 2. Find the silence
const sd = await client.edit.silenceDetect({ audioUrl: masterUrl, thresholdDb: -35 })
const silence = (await outputOf(sd.jobId)).json
// 3. Plan a tighter cut
const plan = await client.edit.editPlan({
mode: "tighten",
planTier: "standard",
transcript,
sources: [{ id: "ep", url: masterUrl, kind: "video", role: "master-audio" }],
silence,
})
const edl = unwrapEditPlanOutput(await outputOf(plan.jobId))
// 4. Render the plan
const render = await client.edit.applyEdl({ edl, output: "video", quality: "final" })
const { videoUrl } = await outputOf(render.jobId)As mesmas etapas existem como nós: Transcrever (Transcribe), Detectar silêncio (Silence Detect), Plano de edição (Edit Plan) e Aplicar EDL (Apply EDL).
client.edit
edit.silenceDetect(input)
Encontra os trechos silenciosos de uma fonte de áudio ou vídeo. Roda no servidor, sem modelo de IA.
silenceDetect(input: SilenceDetectInput): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.edit.silenceDetect({ audioUrl: masterUrl, minSilenceMs: 900 })O output_data.json do job concluído é um objeto SilenceRanges: { version, ranges: [{ startMs, endMs }], durationMs }. Passe o objeto inteiro como silence para editPlan().
edit.audioSync(input)
Mede, pelo som, o deslocamento entre os relógios de 2 a 6 gravações de uma mesma conversa, como faz o nó Sincronizar áudio (Audio Sync). Roda no servidor, sem modelo de IA. Custa 11 créditos por fonte depois da primeira: 11 para 2 fontes, 33 para 4 e 55 para 6.
audioSync(input: AudioSyncInput): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.edit.audioSync({
sources: [
{ id: "mic", url: micUrl },
{ id: "camA", url: camAUrl },
],
reference: "mic",
})O output_data.json do job concluído é um AudioSyncResult:
{
version: number
reference: string // the source every offset is measured against
offsets: Array<{
sourceId: string
offsetMs: number // referenceMs = sourceMs + offsetMs
confidence: number // 0 to 1; below 0.5 a note asks you to check by ear
driftMsPerHour: number | null // measured, never corrected; null when the overlap was too short
}>
notes: string[] // low confidence, drift above 33 ms over the overlap, no shared sound
}Com a gravação principal como reference, cada offsetMs é exatamente o offsetMs dessa fonte na sua EDL. Uma requisição malformada é recusada com um NodaroError cujo code é validation_error, antes que qualquer crédito seja reservado. Isso inclui menos de 2 ou mais de 6 fontes, um id repetido ou um reference que não seja um dos ids.
edit.editPlan(input)
Planeja uma edição a partir de uma transcrição com tempos, como faz o nó Plano de edição. Escreve um de três tipos de plano: um corte mais enxuto da gravação inteira, um conjunto de clipes curtos ou capítulos.
editPlan(input: EditPlanInput): Promise<{ jobId: string }>Prop
Type
import { unwrapEditPlanOutput } from "@nodaro/sdk"
const { jobId } = await client.edit.editPlan({
mode: "clips",
planTier: "standard",
transcript,
sources: [{ id: "ep", url: masterUrl, kind: "video", role: "master-audio" }],
silence,
count: 5,
targetAspect: "9:16",
})
const { data } = await client.jobs.getStatus(jobId) // poll until completed
const clips = unwrapEditPlanOutput(data.output_data) // one EDL per clipLeia a saída do job concluído com unwrapEditPlanOutput(). Essa função retorna um Edl no modo tighten, um array de Edl no modo clips e um ChapterSet no modo chapters.
Em uma instalação self-hosted, este método precisa de uma conexão com o Nodaro Cloud. Sem ela, falha com 503 nodaro_connection_required.
edit.applyEdl(input)
Renderiza uma lista de decisões de edição em um vídeo ou um arquivo de áudio, como faz o nó Aplicar EDL.
applyEdl(input: ApplyEdlInput): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.edit.applyEdl({ edl, output: "video", quality: "proxy", crossfadeMs: 80 })A EDL é verificada antes que qualquer crédito seja reservado. Uma fonte desconhecida, um segmento sem imagem em uma edição de vídeo ou mais de 180 minutos de saída em uma única renderização falham com um NodaroError cujo code é invalid_edl. A duração é medida depois dos crossfades. O message indica o problema, por exemplo, que a edição renderiza 200 minutos e precisa ser dividida em partes de no máximo 180 minutos.
edit.remapTranscript(edl, transcript)
Move uma transcrição para a linha do tempo de uma edição, localmente, sem requisição. Descarta as palavras dentro dos trechos cortados, recorta as palavras que atravessam um corte e desloca todos os tempos para a saída editada. applyEdl() faz o mesmo no servidor quando você passa um transcript para ele.
remapTranscript(edl: Edl, transcript: Transcript): TranscriptProp
Type
const editedTranscript = client.edit.remapTranscript(edl, transcript)
// caption the edited video without another transcriptionUse-o para legendar uma edição sem renderizar e sem uma segunda transcrição. Ele também é a opção mais rápida para uma transcrição grande quando você só precisa dos novos tempos.
Perguntas frequentes
Páginas relacionadas
Vozes e áudio
Mídia e uploads
Plano de edição
Aplicar EDL
Detectar silêncio
Última atualização
Vozes e áudio
Navegue pelas vozes, troque e substitua vozes, crie novas vozes, duble vídeos e separe, mixe e transcreva áudio em TypeScript com o SDK do Nodaro.
Cenas 3D
Em TypeScript, gere uma cena 3D editável com um prompt, edite-a, renderize-a em MP4 e execute a Renderização 3D Pro com client.scene3d e os nós de cena 3D.