Skip to main content
Fazer uma chamada ao /audio/speech é fácil. Narrar um artigo real é onde os problemas interessantes aparecem: o endpoint aceita no máximo 4096 caracteres por requisição, cada voz pertence a um modelo específico, os formatos de áudio diferem de modelo para modelo, e texto escrito para ser lido não se parece em nada com texto escrito para ser ouvido. Neste tutorial trabalhamos os quatro pontos. O resultado é um script que transforma uma URL em um único arquivo de áudio:
Iremos:
  1. Escolher um modelo e uma voz adequados para narração de textos longos
  2. Fazer uma única requisição de fala e salvar o áudio
  3. Dividir um artigo longo em pedaços que caibam no limite de caracteres
  4. Unir os pedaços sintetizados em um único arquivo sem emendas audíveis
  5. Reescrever o artigo em algo que valha a pena ouvir
  6. Combinar as peças, e então dar uma olhada em streaming para uso interativo

Configuração

Você precisa do Python 3.9 ou mais recente, do pacote requests e de uma chave de API Venice.

1. Escolha um modelo e uma voz

Vozes pertencem a modelos. Enviar uma voz de uma família para um modelo de outra é o erro inicial mais comum, então comece listando o que cada modelo realmente aceita:
model_spec.voices é a lista autoritativa de vozes de um modelo, e supported_formats diz quais valores de response_format ele aceita. Remova o | length da consulta para imprimir os nomes das vozes. Vamos usar tts-xai-v1 com a voz eve. Ele suporta pcm, o que torna a união dos pedaços simples na seção 4.
A velocidade de síntese varia muito mais entre modelos TTS do que a qualidade da saída, e a diferença é grande o suficiente para mudar sua arquitetura. Meça uma requisição realista contra dois ou três candidatos antes de se comprometer. Um pedaço que um modelo retorna em poucos segundos pode levar vários minutos em outro.

2. Faça uma única requisição

O corpo da resposta é áudio bruto, e não JSON, então escreva os bytes diretamente em um arquivo.
Combinações incompatíveis são rejeitadas antes que qualquer áudio seja gerado, e o erro indica o que teria funcionado:

3. Divida o texto no limite de 4096 caracteres

O campo input aceita no máximo 4096 caracteres. Textos mais longos são rejeitados imediatamente, em vez de silenciosamente truncados:
Portanto, dividimos o artigo primeiro. Dividir em fronteiras de frase importa, porque um pedaço que termina no meio de uma frase produz um tropeço audível na junção. Crie narrate.py:
Em um roteiro de 5362 caracteres, isso produz quatro pedaços, cada um terminando em uma frase:
O max_chars padrão é 1500, e não algo próximo do teto de 4096, e isso é intencional. O tempo de síntese cresce com o comprimento da entrada, então pedaços menores retornam mais cedo e, como executam em paralelo, terminam o trabalho todo mais rápido. Eles também tornam as tentativas de repetição baratas quando uma requisição falha.

4. Una os pedaços em um único arquivo

Concatenar áudio codificado como MP3 é pouco confiável, porque cada pedaço carrega seus próprios cabeçalhos de frame. Solicitar pcm evita o problema por completo. PCM é composto por amostras brutas sem contêiner, então unir é apenas concatenar bytes, e o módulo wave da biblioteca padrão do Python escreve o cabeçalho para nós.
Um único pedaço retorna rapidamente em relação à quantidade de áudio que contém:
Essa requisição levou cerca de 13 segundos para produzir 89 segundos de fala. Executar os quatro pedaços simultaneamente é o que mantém o total razoável: a narração completa abaixo levou 15 segundos de tempo real. ThreadPoolExecutor.map retorna os resultados na ordem em que as entradas foram submetidas, então os pedaços chegam em ordem de leitura mesmo tendo sido sintetizados ao mesmo tempo.
PCM bruto não carrega taxa de amostragem, então você precisa informar a correta ao escrever o cabeçalho WAV, e ela é específica do modelo. tts-xai-v1 retorna 24 kHz, enquanto tts-gradium-v1 retorna 48 kHz. Errar isso faz a narração tocar na velocidade e no tom errados.
Para descobrir a taxa de qualquer modelo, peça um clipe curto como wav e leia o cabeçalho que ele devolve:

5. Prepare o texto para soar bem

Markdown extraído lido em voz alta literalmente é quase impossível de escutar. URLs são o exemplo mais claro. Um modelo de fala soletra caractere por caractere, então https://docs.venice.ai/llms.txt sai como:
h t t p s dois-pontos barra barra docs ponto venice ponto a i l l m s ponto t x t
Cabeçalhos, marcadores de lista, tabelas e blocos de código causam versões menores do mesmo problema. Em vez de brigar com Markdown usando expressões regulares, podemos pedir a um modelo de chat que reescreva o artigo como algo destinado a ser falado. Crie article_to_audio.py:
A substituição URL_PATTERN fica como rede de segurança para o link ocasional que o modelo deixe passar.

6. Juntando tudo

O ponto de entrada faz o scrape, escreve o roteiro, o salva e narra:
Salvar script.txt ao lado do áudio vale as duas linhas. Quando uma narração soa errada, o roteiro quase sempre mostra por quê, e você pode corrigir sem pagar para sintetizar de novo.
Pouco menos de seis minutos de narração, produzidos em cerca de quinze segundos. O roteiro agora começa com prosa em vez de elementos de navegação:
Venice is built on a simple but powerful principle. User privacy comes first. The platform’s entire architecture flows from this philosophical commitment.
Para verificar uma narração sem precisar ouvi-la inteira, envie o áudio de volta por /audio/transcriptions e compare a transcrição com script.txt. Transcrever os últimos vinte segundos é uma maneira rápida de confirmar que os pedaços foram unidos na ordem correta, e pega pedaços perdidos e URLs soletradas em segundos.

Streaming para uso interativo

A narração em lote otimiza o tempo total. Uma interface de voz tem a prioridade oposta, que é entregar o primeiro áudio o mais rápido possível. Definir streaming: true retorna o corpo frase a frase à medida que é gerado, então a reprodução pode começar em cerca de um segundo em vez de esperar pelo clipe completo.
Prefira pcm a mp3 quando estiver alimentando a Web Audio API de um navegador ou um dispositivo de áudio diretamente, pois não precisa de etapa de decodificação.

Opções de requisição que vale a pena conhecer

Erros

Como os pedaços são independentes, uma falha custa no máximo um deles, e refazer synthesize para esse pedaço é sempre seguro.

Próximos passos

Algumas extensões naturais a partir daqui:

Texto para Fala

Referência para o endpoint de fala e seus parâmetros.

Clonagem de Voz

Narre com uma voz personalizada em vez de uma predefinida.

Respostas com Citações usando Web Search

Gere o texto que esta ferramenta narra.

Fala para Texto

Transcreva áudio para verificar uma narração de ponta a ponta.