Retour au blog
iagooglecloudffmpegbuildinpublic

J'ai remplacé mon moteur TTS. L'appel API était la partie facile.

Comment intégrer Google Chirp 3 HD dans un pipeline de doublage vidéo sans dégrader le timing ni la qualité vocale. Retour d'expérience sur 19 langues.

13 septembre 2026

J'ai remplacé mon moteur TTS. L'appel API était la partie facile.

Katto disposait déjà d'un système de doublage IA. Un créateur pouvait prendre un clip court, choisir une langue cible, et récupérer une version traduite. La première implémentation utilisait Kokoro et couvrait huit langues.

Récemment, j'ai migré le moteur de synthèse vocale principal vers Google Cloud Text-to-Speech avec Chirp 3 HD. L'objectif semblait direct : améliorer les voix et ajouter plus de langues. Katto expose désormais 19 langues de doublage et 12 voix sélectionnées dans l'éditeur.

Je m'attendais à ce que la migration soit essentiellement un remplacement d'API.

Ce ne fut pas le cas.

Générer une phrase naturelle est facile. Faire en sorte que cette phrase commence et se termine exactement dans l'espace laissé par un autre locuteur, c'est le vrai problème du doublage.

Si le locuteur original dit quelque chose en 2,4 secondes et que la traduction prend 3,2 secondes, un bon modèle TTS ne sauve pas le clip. La voix empiète sur la phrase suivante, les sous-titres dérivent, ou la parole doit être accélérée jusqu'à sonner précipitée.

La requête TTS s'est révélée être la plus petite partie du système.

Le pipeline que j'ai finalement construit

timings de mots en cache
        |
        v
segments de phrases avec créneaux temporels fixes
        |
        v
traduction consciente de la durée
        |
        v
Google Chirp 3 HD, une phrase à la fois
        |
        v
alignement audio borné avec FFmpeg
        |
        +----> sous-titres traduits depuis les mêmes segments
        |
        v
remux MP4 final

Chaque étape existe parce qu'une version plus simple a échoué d'une manière différente.

Conserver le timing original comme donnée

Katto dispose déjà des timestamps de mots issus de son pipeline de transcription. Je n'envoie pas la transcription complète à la traduction et au TTS comme un seul bloc. Je regroupe les mots en phrases.

Une phrase se termine à la ponctuation de fin de phrase, après une pause de plus de 0,6 seconde, ou lorsqu'elle dépasserait six secondes. Chaque segment conserve son début et sa fin d'origine. Ces nombres deviennent le contrat pour toutes les étapes ultérieures.

Synthétiser la transcription complète peut sembler plus fluide, mais cela supprime les ancres nécessaires pour replacer la parole sur la timeline vidéo. La synthèse au niveau de la phrase préserve suffisamment de contexte pour une voix naturelle tout en conservant des limites temporelles utiles.

Traduire pour la durée parlée, pas seulement le sens

Une traduction écrite correcte peut être une mauvaise traduction de doublage. Certaines langues nécessitent plus de syllabes pour exprimer la même idée. Une version littérale peut préserver chaque nuance et rester inutilisable parce qu'elle ne rentre pas dans son créneau.

Pour chaque groupe de phrases, je demande à Claude Haiku une traduction orale naturelle qui privilégie les formulations plus courtes et moins de syllabes. La réponse préserve chaque index de segment source.

Le prompt fait partie du système audio. Son travail n'est pas seulement la précision linguistique. Il réduit également l'étirement temporel nécessaire plus tard.

Cela reste une heuristique. Un LLM ne peut pas garantir la durée parce que la voix sélectionnée change aussi le rythme. La couche audio mesure toujours le WAV généré. Un cache en mémoire, indexé par langue cible et segments source, permet aux rendus suivants de réutiliser la traduction tant que le worker reste actif.

Synthétiser une phrase à la fois

Chaque phrase traduite est envoyée à l'API REST Google Cloud Text-to-Speech sous forme d'audio LINEAR16 à 24 kHz. Les noms de voix suivent le format locale-Chirp3-HD-speaker documenté par Google.

Google prend en charge plus de locales Chirp 3 HD que Katto n'en expose actuellement. J'ai délibérément limité le produit à 19 langues câblées à travers le chemin complet : UI, mapping de locale, polices, sous-titres et comportement de repli. Une API qui prétend supporter une langue ne signifie pas que le produit environnant la supporte correctement.

Ajuster la parole dans le créneau sans la détruire

Après la synthèse, je compare la durée générée avec le créneau original.

target_duration = segment["end"] - segment["start"]
ratio = generated_duration / target_duration

Si la parole est légèrement trop longue, le filtre atempo de FFmpeg l'accélère tout en préservant la hauteur. Je plafonne l'accélération à 1,3x.

Ce plafond compte. Une limite antérieure de 1,6x faisait rentrer plus de phrases, mais certaines voix sonnaient anormalement pressées. Un alignement parfait n'est pas utile si le résultat est désagréable à entendre.

Chaque phrase ajustée est placée à son décalage original dans une piste maître. Les phrases courtes laissent une pause naturelle. Les phrases plus longues reçoivent une correction bornée. Cela ne résout pas toutes les traductions pathologiques. Cela applique une règle plus utile : préserver l'intelligibilité avant de poursuivre un timing mathématiquement parfait.

Donner à la parole et aux sous-titres la même horloge

La réponse de synthèse me donne de l'audio, pas des timestamps de mots fiables pour le texte nouvellement parlé. Inventer un timing au niveau des mots ferait paraître les sous-titres précis tout en étant faux.

Les clips doublés utilisent donc des sous-titres au niveau de la phrase générés à partir des mêmes segments traduits utilisés pour la parole. Leurs temps de début et de fin correspondent déjà au placement audio.

Le moteur de rendu sélectionne également des polices qui couvrent le script cible. Les polices latines ne suffisent pas pour le japonais, le chinois, l'hindi ou l'arabe. Les titres d'intro et les accroches IA suivent le même chemin de localisation, donc l'écran ne parle pas une langue et n'en affiche pas une autre.

Les problèmes de production ordinaires comptaient aussi

Tous les locuteurs sélectionnés ne fonctionnaient pas dans toutes les locales que j'ai testées. Si une voix sélectionnée n'est pas disponible, Katto réessaie une fois avec une valeur par défaut connue pour le genre choisi. L'aperçu en direct de l'éditeur appelle le même moteur Google. Un échantillon d'un autre modèle permettrait à l'utilisateur de choisir une voix qu'il ne recevra jamais.

La clé API de production est restreinte à l'adresse IPv4 du VPS, mais le VPS préférait IPv6 lors de l'accès à Google. Les requêtes valides étaient rejetées jusqu'à ce que l'appel TTS soit forcé via IPv4. L'API, la clé et le code étaient corrects. Le chemin réseau ne l'était pas.

Le doublage produit une variante vidéo séparée. Si la traduction, la synthèse, le rendu des sous-titres ou le remuxage échoue, le clip original reste intact. Pour les huit langues d'origine, Kokoro reste disponible lorsque le chemin Google est désactivé ou non configuré.

Ce qui a changé, et ce qui n'a pas changé

Le résultat visible était une expansion de 8 à 19 langues de doublage, plus des voix sélectionnables et des aperçus en direct.

L'amélioration plus profonde était architecturale. La traduction, la parole, les sous-titres, les superpositions et le rendu vidéo partagent maintenant une unité temporelle : le segment de phrase.

Le système ne clone pas le locuteur original, n'effectue pas de synchronisation labiale et n'invente pas de timestamps de mots générés. Les traductions très longues peuvent encore dépasser leur créneau idéal. Ces limites valent mieux que de prétendre à une précision que le pipeline ne peut pas fournir.

Je pensais remplacer un moteur de synthèse vocale. J'ai fini par resserrer le contrat entre presque toutes les étapes du pipeline média.

L'appel API était la partie facile. Faire en sorte que le résultat appartienne à la timeline originale était le travail.

Katto transforme les vidéos longues en clips courts verticaux et peut maintenant doubler ces clips dans 19 langues. Si vous construisez de la vidéo multilingue, je serais intéressé de savoir comment vous gérez le timing sans faire sonner la voix précipitée.

Références

Google Cloud Text-to-Speech : voix Chirp 3 HD

Articles liés

Prêt à transformer vos vidéos en clips viraux ?

Katto découpe, sous-titre et recadre automatiquement vos vidéos longues en contenu court.

Essayer Katto gratuitement