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.
client.voices trabalha com vozes da ElevenLabs: lista e pesquisa vozes, troca a voz de uma gravação, dá uma nova voz a cada falante, cria novas vozes e dubla áudio e vídeo para outros idiomas. client.audio oferece os blocos de áudio separadamente: separação, isolamento de voz, efeitos, mixagem, volume, junção e transcrição. Todo método de geração retorna um jobId; consulte-o periodicamente com client.jobs.getStatus(). Os métodos chamam a API REST de voz e mídia.
Métodos
| Método | O que faz |
|---|---|
voices.list() | Lista as vozes prontas |
voices.searchLibrary(params?) | Pesquisa a Biblioteca de vozes da comunidade |
voices.listClones() | Lista seus clones de voz existentes |
voices.deleteClone(id) | Exclui um dos seus clones de voz |
voices.createClone() e createCloneFromFile() | Descontinuados |
voices.change(input) | Substitui a voz em uma gravação ou em um vídeo |
voices.recast(input) | Dá uma voz diferente a cada falante |
voices.analyze(input) | Detecta os falantes antes de uma troca de vozes |
voices.exportMix(input) | Renderiza um vídeo a partir de stems de voz mixados |
voices.design(input) | Cria uma nova voz a partir de uma descrição |
voices.remix(input) | Fala um texto em uma voz que você descreve |
voices.dub(input) | Dubla áudio ou vídeo para outro idioma |
voices.textToDialogue(input) | Dá voz a um roteiro com vários falantes em um único arquivo de áudio |
audio.separate(input) | Divide uma faixa em stems |
audio.isolate(input) | Mantém a voz principal e remove o ruído |
audio.applyFx(input) | Adiciona reverberação, eco, telefone ou megafone |
audio.mix(input) | Sobrepõe várias faixas em uma só |
audio.adjustVolume(input) | Muda o nível, normaliza ou aplica fade |
audio.combine(input) | Junta segmentos de áudio em sequência |
audio.transcribe(input) | Transforma fala em texto, com os tempos das palavras |
client.voices: vozes
voices.list()
Lista as vozes prontas da ElevenLabs (GET /v1/voices). Quando o servidor não tem uma chave da ElevenLabs configurada, ele retorna, em vez disso, um conjunto selecionado.
list(): Promise<Voice[]>const voices = await client.voices.list()voices.searchLibrary(params?)
Pesquisa a Biblioteca de vozes da comunidade (GET /v1/voices/library). Todos os parâmetros são opcionais, e valores vazios são omitidos para que os padrões do servidor se apliquem. hasMore, na resposta, indica se existe outra página.
searchLibrary(params?: VoiceLibraryParams): Promise<{ voices: Voice[]; hasMore: boolean }>Prop
Type
const { voices, hasMore } = await client.voices.searchLibrary({ search: "deep", language: "en" })
const voice = voices[0]
await client.nodes.run("text-to-speech", {
text: "Hello!",
voice: voice.voice_id,
voiceType: "library",
...(voice.recommendedProvider ? { provider: voice.recommendedProvider } : {}),
})Cada voz pode trazer duas indicações sobre os modelos de fala em que foi verificada:
recommendedProvideré o melhor modelo para a voz. Apps sem um seletor de modelo devem enviá-lo comoproviderpara o Texto para fala (Text to Speech), para que a voz soe como a prévia dela na biblioteca.verifiedProviderslista todos os modelos em que a voz foi verificada. Apps com um seletor de modelo devem substituir a escolha do usuário só quando ela não estiver nessa lista.
voices.listClones()
Lista seus clones de voz (GET /v1/voice-clones). Os clones feitos antes de a clonagem ser descontinuada continuam funcionando como IDs de voz em qualquer lugar que aceite uma voz.
listClones(): Promise<VoiceClone[]>const clones = await client.voices.listClones()voices.deleteClone(id)
Exclui um dos seus clones de voz (DELETE /v1/voice-clones/:id).
deleteClone(id: string): Promise<void>Prop
Type
await client.voices.deleteClone(cloneId)voices.createClone() e createCloneFromFile()
A clonagem de voz não é mais oferecida no Nodaro. Ela foi descontinuada em setembro de 2026. Os dois métodos continuam no cliente e estão marcados como obsoletos. Eles falham com um NodaroError cujo code é voice_cloning_retired, com status 410. Para uma nova voz personalizada, use design().
client.voices: modificador de voz
voices.change(input)
Substitui a voz de uma gravação, ou de um vídeo inteiro com fala, por outra voz (POST /v1/voice-changer), como faz o nó Modificador de voz (Voice Changer). Com videoUrl, o servidor extrai o áudio do vídeo, troca a voz e coloca a nova voz de volta na imagem original.
change(input: {
voiceId: string
audioUrl?: string
videoUrl?: string
model?: string
stability?: number
similarityBoost?: number
style?: number
useSpeakerBoost?: boolean
seed?: number
removeBackgroundNoise?: boolean
}): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.voices.change({
videoUrl: "https://example.com/talking.mp4",
voiceId: "Aria",
})
// the finished job's output_data has videoUrl and audioUrlvoices.recast(input)
Dá uma voz diferente a cada falante detectado em uma gravação (POST /v1/voice-changer-pro), como faz o nó Modificador de voz Pro (Voice Changer Pro). O método roda no Nodaro Cloud, custa créditos e é executado como um job.
recast(input: VoiceChangerProInput): Promise<{ jobId: string }>Prop
Type
Cada entrada de orderedVoices é uma destas opções:
- Um ID de voz: o nome de uma voz pronta, como
"Rachel", ou um ID de voz da ElevenLabs. null: uma posição que mantém a voz original. Esse falante mantém a própria voz, enquanto os falantes seguintes continuam tendo a voz trocada. As posições que mantêm a voz original não custam nada, porque só os falantes com voz trocada são cobrados.- Um objeto com
voiceIde as configurações desse falante:stability,similarityBoostestyle, de 0 a 1,useSpeakerBooste umseedde 0 a 4.294.967.295.volumeModeé"match"(o padrão, o nível do falante original),"normalize"ou"manual", comvolumeem porcentagem de 0 a 200.engine: "v3"fala a linha de novo a partir da transcrição, com suporte a[audio tags], em vez de converter a fala gravada.
O falante 0 recebe orderedVoices[0], o falante 1 recebe orderedVoices[1], e assim por diante. Os falantes depois da última entrada mantêm a própria voz. A voz e a música são sempre separadas primeiro. preserveBackground só decide se a música volta.
voiceFx.preset é um ambiente de reverberação (room, bathroom, car, hall, concert-hall, church, cave, arena ou outdoor), telephone, megaphone, echo ou custom. As predefinições de reverberação usam wetDryMix de 0 a 100. echo e custom usam delayMs de 20 a 2.000 e decay de 0 a 1.
// Recast speakers 0 and 2, and keep speaker 1's own voice
const { jobId } = await client.voices.recast({
audioUrl: "https://example.com/panel.mp3",
orderedVoices: ["Rachel", null, "Aria"],
})
// Repeatable voices, a hall reverb, and finer separation
const { jobId: tuned } = await client.voices.recast({
audioUrl: "https://example.com/dialogue.mp3",
orderedVoices: [
{ voiceId: "Rachel", seed: 12345, stability: 0.6 },
{ voiceId: "Aria", seed: 67890, volumeMode: "manual", volume: 120 },
],
voiceFx: { preset: "hall", wetDryMix: 35 },
separationQuality: "best",
})No modo de vídeo, o output_data do job concluído tem videoUrl e audioUrl.
voices.analyze(input)
Detecta os falantes de um clipe sem trocar as vozes (POST /v1/voice-changer-pro/analyze). O método separa a voz da música uma vez e descobre quem fala quando. Ele roda no Nodaro Cloud, com preço fixo, como um job.
analyze(input: {
audioUrl?: string
videoUrl?: string
separationQuality?: "fast" | "best"
suggestTitle?: boolean
}): Promise<{ jobId: string }>Prop
Type
O output_data do job concluído é um VcpAnalysis: os vocalsUrl e backgroundUrl separados, os speakers detectados (cada um com id, os segments de tempo, firstStartSec, wordCount e um snippet de texto), languageCode com languageProbability e suggestedTitle, quando pedido. Passe-o como analysis para cada recast() seguinte, para que a troca de vozes reaproveite as faixas separadas e não pague de novo pela detecção.
voices.exportMix(input)
Renderiza o vídeo final a partir de um conjunto mixado de stems (POST /v1/voice-changer-pro/export). É a última etapa depois de recast({ output: "stems" }). O método roda no Nodaro Cloud, com preço fixo, como um job.
exportMix(input: {
videoUrl: string
tracks: Array<{ url: string; gain: number; muted: boolean; kind?: "voice" | "background" }>
voiceFx?: { preset: AudioFxPreset; wetDryMix?: number; delayMs?: number; decay?: number }
}): Promise<{ jobId: string }>Prop
Type
O fluxo interativo analisa uma vez, troca as vozes gerando stems e depois mixa e renderiza. Veja o fluxo com uma pequena função auxiliar de consulta periódica:
import type { VcpAnalysis } 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, 2_000))
}
}
const { jobId: analyzeJob } = await client.voices.analyze({ videoUrl })
const analysis = (await outputOf(analyzeJob)) as VcpAnalysis
const { jobId: recastJob } = await client.voices.recast({
videoUrl,
orderedVoices: ["Rachel", null, "Aria"],
output: "stems",
analysis,
})
const stems = await outputOf(recastJob)
const { jobId: exportJob } = await client.voices.exportMix({
videoUrl,
tracks: [
{ url: stems.tracks[0].url, gain: 100, muted: false },
{ url: stems.tracks[1].url, gain: 90, muted: false },
{ url: stems.backgroundUrl, gain: 70, muted: false, kind: "background" },
],
voiceFx: { preset: "hall", wetDryMix: 25 },
})
const { videoUrl: finalVideo } = await outputOf(exportJob)Os ganhos, os mudos e o efeito são aplicados quando o vídeo é renderizado, e a imagem é copiada como está. Por isso, a exportação corresponde à sua prévia, e você pode mudar a mixagem quantas vezes quiser antes de exportar. Uma mixagem com todas as faixas no mudo é recusada com um 400.
client.voices: criar e traduzir
voices.design(input)
Cria uma nova voz sintética a partir de uma descrição em texto (POST /v1/voice-design), como faz o nó Design de voz (Voice Design). O job concluído traz uma prévia em áudio e o ID da nova voz, que você pode usar em qualquer lugar que aceite uma voz.
design(input: {
text: string
voiceDescription: string
model?: string
loudness?: number
guidanceScale?: number
seed?: number
quality?: number
shouldEnhance?: boolean
userPrompt?: string
}): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.voices.design({
text: "Welcome back. Tonight we follow the river north, into the mountains where the story began.",
voiceDescription: "A calm, deep voice of an older male narrator with a slight British accent",
})voices.remix(input)
Fala um texto em uma voz descrita em palavras simples, sem criar uma voz (POST /v1/voice-remix), como faz o nó Remix de voz (Voice Remix).
remix(input: { text: string; voiceDescription: string; userPrompt?: string }): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.voices.remix({
text: "Your order is on its way.",
voiceDescription: "A cheerful young woman, fast and upbeat",
})voices.dub(input)
Dubla um áudio, ou um vídeo inteiro, para outro idioma, mantendo a voz de cada falante (POST /v1/dubbing), como faz o nó Dublagem (Dubbing). A dublagem de um vídeo retorna output_data.videoUrl, o clipe dublado, e output_data.audioUrl, só a faixa dublada.
dub(input: DubbingInput): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.voices.dub({
videoUrl: "https://example.com/interview.mp4",
targetLanguage: "es",
numSpeakers: 2,
})O preço depende dos minutos do trecho dublado, com um mínimo de 1 minuto. Um trecho tem no máximo 30 minutos; por isso, use startTime e endTime em fontes mais longas.
voices.textToDialogue(input)
Dá voz a um roteiro com vários falantes em um único arquivo de áudio (POST /v1/text-to-dialogue), como faz o nó Texto para diálogo (Text to Dialogue) com o ElevenLabs Dialogue v3.
textToDialogue(input: {
dialogue: Array<{ text: string; voice: string }>
stability?: 0 | 0.5 | 1
languageCode?: string
seed?: number
applyTextNormalization?: "auto" | "on" | "off"
}): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.voices.textToDialogue({
dialogue: [
{ text: "Did you hear that?", voice: "Rachel" },
{ text: "[whispers] Stay behind me.", voice: "Callum" },
],
})Um roteiro pode ter no máximo 5.000 caracteres, e menos de 2.000 dão a melhor qualidade. Ele pode usar no máximo 10 vozes diferentes. Vozes da biblioteca, vozes criadas com design de voz e clones existentes funcionam, combinados como você quiser. O output_data.audioUrl do job concluído é o arquivo.
client.audio
Os blocos de áudio que o Modificador de voz Pro usa internamente, disponíveis um a um. Todo método retorna um jobId.
audio.separate(input)
Divide uma faixa em stems (POST /v1/audio-separation), como faz o nó Separação de áudio (Audio Separation).
separate(input: { audioUrl: string; mode?: "vocal_instrumental" | "stems"; quality?: "auto" | "fast" | "best" }): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.audio.separate({ audioUrl: songUrl })
// output: vocalUrl and instrumentalUrl, or one URL per stem in stems modeaudio.isolate(input)
Mantém a voz principal e remove o ruído de fundo (POST /v1/audio-isolation), como faz o nó Extrator de voz (Voice Extractor).
isolate(input: { audioUrl: string }): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.audio.isolate({ audioUrl: interviewUrl })audio.applyFx(input)
Adiciona um efeito de reverberação, eco, telefone ou megafone (POST /v1/audio-fx), como faz o nó Efeitos de áudio (Audio FX). As predefinições são as mesmas do voiceFx da troca de vozes.
applyFx(input: {
audioUrl: string
preset?: AudioFxPreset
mix?: number
delayMs?: number
decay?: number
eqLow?: number
eqHigh?: number
}): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.audio.applyFx({ audioUrl: lineUrl, preset: "telephone" })audio.mix(input)
Sobrepõe várias faixas em uma só (POST /v1/mix-audio), como faz o nó Mixar áudio (Mix Audio).
mix(input: { audioUrls: string[]; trackVolumes?: number[] }): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.audio.mix({ audioUrls: [voiceUrl, musicUrl], trackVolumes: [100, 35] })audio.adjustVolume(input)
Muda o nível de um arquivo de áudio, ou do áudio de um vídeo (POST /v1/adjust-volume), como faz o nó Ajustar volume (Adjust Volume).
adjustVolume(input: {
audioUrl?: string
videoUrl?: string
volume?: number
normalize?: boolean
fadeIn?: number
fadeOut?: number
}): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.audio.adjustVolume({ audioUrl: musicUrl, volume: 60, fadeOut: 3 })audio.combine(input)
Junta segmentos de áudio em sequência (POST /v1/combine-audio), como faz o nó Combinar áudio (Combine Audio).
combine(input: { segments: Array<{ url: string; startTime?: number; endTime?: number }> }): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.audio.combine({
segments: [{ url: introUrl }, { url: episodeUrl, startTime: 4 }, { url: outroUrl }],
})audio.transcribe(input)
Transforma em texto a fala de um arquivo de áudio ou de vídeo (POST /v1/transcribe), como faz o nó Transcrever (Transcribe).
transcribe(input: {
audioUrl: string
provider?: "elevenlabs-stt" | "incredibly-fast-whisper" | "whisper"
language?: string
diarize?: boolean
tagAudioEvents?: boolean
wordTimestamps?: boolean
}): Promise<{ jobId: string }>Prop
Type
provider | Tempos das palavras | Observações |
|---|---|---|
elevenlabs-stt | Sempre | O único mecanismo que respeita diarize e tagAudioEvents. |
incredibly-fast-whisper | Só com wordTimestamps: true | Sem a opção, o job é concluído e cobrado, com segmentos de frase e uma lista words vazia. |
whisper | Nunca | Só segmentos de frase. wordTimestamps: true é recusado com 400 validation_error antes de qualquer gasto de créditos. |
Omitir provider usa whisper; por isso, wordTimestamps: true sem um provider também recebe o 400. Para obter os tempos das palavras, indique elevenlabs-stt, ou incredibly-fast-whisper com wordTimestamps: true. As legendas cinéticas precisam deles.
const { jobId } = await client.audio.transcribe({ audioUrl: talkUrl, provider: "elevenlabs-stt" })O output_data do job concluído é um TranscribeJobOutput:
| Campo | Unidade | Conteúdo |
|---|---|---|
text | A transcrição inteira em uma única string. | |
language | O código do idioma detectado ou pedido. | |
words | milissegundos | Uma entrada por palavra: { text, startMs, endMs, speaker? }. Fica vazia quando os tempos das palavras não foram pedidos ao mecanismo. |
json | milissegundos | A transcrição normalizada, { version, language, words, segments? }, que client.edit aceita. |
segments | segundos | Os intervalos brutos das frases, só dos mecanismos mais antigos. elevenlabs-stt não retorna nenhum; por isso, leia words. |
words tem exatamente o formato das captions que client.media.addCaptions() aceita; assim, você pode corrigir uma transcrição e gravá-la como legendas no vídeo.
Perguntas frequentes
Páginas relacionadas
Mídia e uploads
Edição
Voz e mídia
Modificador de voz Pro
Transcrever
Última atualização
Mídia e uploads
Envie arquivos ao Nodaro, liste sua biblioteca, baixe vídeos de redes sociais, corte clipes, embuta legendas e componha imagens e vídeos em TypeScript.
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.