Skip to main content
Faire un appel à /audio/speech est facile. C’est en narrant un vrai article que les problèmes intéressants apparaissent : le point de terminaison accepte au plus 4096 caractères par requête, chaque voix appartient à un modèle spécifique, les formats audio diffèrent d’un modèle à l’autre, et un texte écrit pour être lu ne ressemble en rien à un texte écrit pour être entendu. Dans ce tutoriel, nous traitons les quatre. Le résultat est un script qui transforme une URL en un seul fichier audio :
Nous allons :
  1. Choisir un modèle et une voix adaptés à la narration longue
  2. Faire une seule requête de synthèse et enregistrer l’audio
  3. Découper un long article en morceaux respectant la limite de caractères
  4. Assembler les morceaux synthétisés en un seul fichier sans coutures audibles
  5. Réécrire l’article en quelque chose qui vaut la peine d’être écouté
  6. Combiner les pièces, puis examiner le streaming pour un usage interactif

Configuration

Vous avez besoin de Python 3.9 ou plus récent, du paquet requests et d’une clé API Venice.

1. Choisir un modèle et une voix

Les voix appartiennent aux modèles. Envoyer une voix d’une famille à un modèle d’une autre famille est la première erreur la plus courante, alors commencez par lister ce que chaque modèle accepte réellement :
model_spec.voices est la liste de voix qui fait autorité pour un modèle, et supported_formats vous indique les valeurs de response_format qu’il accepte. Retirez le | length de la requête pour afficher les noms de voix eux-mêmes. Nous utiliserons tts-xai-v1 avec la voix eve. Elle prend en charge pcm, ce qui rend l’assemblage des morceaux simple à la section 4.
La vitesse de synthèse varie bien plus entre modèles TTS que la qualité de sortie, et l’écart est suffisamment important pour modifier votre architecture. Chronométrez une requête réaliste sur deux ou trois candidats avant de vous engager. Un morceau qu’un modèle renvoie en quelques secondes peut prendre à un autre plusieurs minutes.

2. Faire une seule requête

Le corps de la réponse est de l’audio brut plutôt que du JSON, donc écrivez les octets directement dans un fichier.
Les combinaisons incompatibles sont rejetées avant qu’aucun audio ne soit généré, et l’erreur vous indique ce qui aurait fonctionné à la place :

3. Découper le texte à la limite des 4096 caractères

Le champ input accepte au plus 4096 caractères. Un texte plus long est rejeté d’emblée plutôt que tronqué silencieusement :
Nous découpons donc l’article d’abord. Découper aux frontières de phrases est important, car un morceau qui se termine au milieu d’une phrase produit une hésitation audible à la jointure. Créez narrate.py :
Sur un script de 5362 caractères, cela produit quatre morceaux, chacun se terminant sur une phrase :
La valeur par défaut de max_chars est 1500 plutôt que quelque chose proche du plafond de 4096, et c’est délibéré. Le temps de synthèse croît avec la longueur d’entrée, donc les morceaux plus petits reviennent plus tôt et, comme ils s’exécutent en parallèle, terminent le travail global plus vite. Ils rendent aussi les nouvelles tentatives peu coûteuses lorsqu’une requête échoue.

4. Assembler les morceaux en un seul fichier

Concaténer de l’audio encodé comme le MP3 n’est pas fiable, car chaque morceau porte ses propres en-têtes de trame. Demander pcm évite complètement le problème. PCM est constitué d’échantillons bruts sans conteneur, donc l’assemblage se résume à ajouter des octets bout à bout, et le module wave de la bibliothèque standard Python écrit l’en-tête pour nous.
Un seul morceau revient rapidement par rapport à la quantité d’audio qu’il contient :
Cette requête a pris environ 13 secondes pour produire 89 secondes de parole. Exécuter les quatre morceaux en parallèle est ce qui maintient le total raisonnable : la narration complète ci-dessous a pris 15 secondes de temps d’horloge. ThreadPoolExecutor.map renvoie les résultats dans l’ordre où les entrées ont été soumises, de sorte que les morceaux arrivent dans l’ordre de lecture même s’ils ont été synthétisés en même temps.
Le PCM brut ne transporte aucune fréquence d’échantillonnage, donc vous devez fournir la bonne lors de l’écriture de l’en-tête WAV, et elle est spécifique à chaque modèle. tts-xai-v1 renvoie 24 kHz tandis que tts-gradium-v1 renvoie 48 kHz. Trompez-vous et la narration est jouée à la mauvaise vitesse et à la mauvaise hauteur.
Pour trouver la fréquence pour n’importe quel modèle, demandez un court clip en wav et lisez l’en-tête qu’il renvoie :

5. Préparer un texte qui sonne bien

Le Markdown extrait, lu à voix haute tel quel, est proche de l’inécoutable. Les URL en sont l’exemple le plus clair. Un modèle vocal les épelle caractère par caractère, si bien que https://docs.venice.ai/llms.txt sort ainsi :
h t t p s deux points barre oblique barre oblique docs point venice point a i l l m s point t x t
Les titres, les puces, les tableaux et les blocs de code causent des versions plus discrètes du même problème. Plutôt que de combattre le Markdown avec des expressions régulières, nous pouvons demander à un modèle de chat de réécrire l’article comme quelque chose destiné à être parlé. Créez article_to_audio.py :
La substitution URL_PATTERN reste en place comme filet de sécurité pour le lien occasionnel que le modèle laisserait derrière lui.

6. Assembler le tout

Le point d’entrée extrait la page, rédige le script, l’enregistre et le narre :
Enregistrer script.txt à côté de l’audio vaut bien deux lignes. Quand une narration sonne mal, le script en montre presque toujours la raison, et vous pouvez la corriger sans payer une nouvelle synthèse.
Juste moins de six minutes de narration, produites en environ quinze secondes. Le script s’ouvre désormais sur de la prose plutôt que du mobilier de navigation :
Venice est bâti sur un principe simple mais puissant. La confidentialité de l’utilisateur passe avant tout. Toute l’architecture de la plateforme découle de cet engagement philosophique.
Pour vérifier une narration sans l’écouter entièrement, renvoyez l’audio dans /audio/transcriptions et comparez la transcription à script.txt. Transcrire les vingt dernières secondes est un moyen rapide de confirmer que les morceaux ont été assemblés dans le bon ordre, et cela repère en quelques secondes les morceaux perdus et les URL épelées.

Streaming pour un usage interactif

La narration par lots optimise le temps total. Une interface vocale a la priorité inverse, qui est d’obtenir le premier audio aussi vite que possible. Régler streaming: true renvoie le corps phrase par phrase au fur et à mesure de la génération, si bien que la lecture peut démarrer en environ une seconde au lieu d’attendre le clip complet.
Préférez pcm à mp3 lorsque vous alimentez directement l’API Web Audio d’un navigateur ou un périphérique audio, puisqu’il n’a besoin d’aucune étape de décodage.

Options de requête à connaître

Erreurs

Comme les morceaux sont indépendants, un échec ne coûte jamais que l’un d’eux, et relancer synthesize pour ce morceau est toujours sûr.

Étapes suivantes

Quelques extensions naturelles à partir d’ici :
  • Mettez en cache l’audio par un hash du texte, de la voix et du modèle afin que les paragraphes inchangés ne soient jamais re-synthétisés.
  • Substituez une voix clonée avec le Clonage vocal pour que la narration utilise la vôtre.
  • Générez le texte source au lieu de l’extraire, en utilisant Réponses sourcées avec la recherche web.
  • Ajoutez un audio d’introduction ou de fond avec Musique et effets sonores.

Synthèse vocale

Référence du point de terminaison speech et de ses paramètres.

Clonage vocal

Narrer avec une voix personnalisée plutôt qu’un préréglage.

Réponses sourcées avec la recherche web

Générez le texte que cet outil narre.

Reconnaissance vocale

Transcrivez de l’audio pour vérifier une narration de bout en bout.