Ho sostituito il motore TTS. La chiamata API era la parte facile.
Come integrare Google Chirp 3 HD in una pipeline di dubbing AI mantenendo il timing originale del video senza distorcere la voce sintetizzata.
13 settembre 2026
Katto aveva già il dubbing AI. Un creator poteva prendere una clip breve, scegliere una lingua e ricevere la versione tradotta. La prima versione usava Kokoro e copriva otto lingue.
Di recente ho migrato il motore vocale principale a Google Cloud Text-to-Speech con Chirp 3 HD. L'obiettivo sembrava lineare: migliorare le voci e aggiungere più lingue. Katto ora espone 19 lingue di dubbing e 12 voci curate nell'editor.
Mi aspettavo che la migrazione fosse principalmente uno swap di API.
Non lo è stata.
Generare una frase naturale è facile. Far iniziare e finire quella frase nello spazio esatto lasciato da un altro speaker è il vero problema del dubbing.
Se lo speaker originale dice qualcosa in 2,4 secondi e la traduzione ne richiede 3,2, un buon modello TTS non salva la clip. La voce invade la frase successiva, i sottotitoli si sfasano, oppure il parlato deve essere accelerato fino a sembrare affrettato.
La richiesta TTS si è rivelata la parte più piccola del sistema.
La pipeline che ho costruito
timing delle parole in cache
|
v
segmenti di frase con slot temporali fissi
|
v
traduzione consapevole della lunghezza
|
v
Google Chirp 3 HD, una frase alla volta
|
v
allineamento audio vincolato con FFmpeg
|
+----> sottotitoli tradotti dagli stessi segmenti
|
v
remux MP4 finaleOgni stadio esiste perché una versione più semplice falliva in modo diverso.
Mantenere il timing originale come dato
Katto ha già i timestamp delle parole dalla pipeline di trascrizione. Non invio l'intera trascrizione alla traduzione e al TTS come un blocco unico. Raggruppo le parole in frasi.
Una frase termina alla punteggiatura, dopo una pausa superiore a 0,6 secondi, o quando supererebbe i sei secondi. Ogni segmento conserva il proprio start ed end originali. Quei numeri diventano il contratto per ogni stadio successivo.
Sintetizzare la trascrizione completa può suonare più fluido, ma rimuove gli ancoraggi necessari per riposizionare il parlato sulla timeline del video. La sintesi a livello di frase preserva abbastanza contesto per una voce naturale mantenendo confini temporali utili.
Tradurre per la durata parlata, non solo per il significato
Una traduzione scritta corretta può essere una cattiva traduzione per il dubbing. Alcune lingue richiedono più sillabe per esprimere la stessa idea. Una versione letterale può preservare ogni sfumatura ed essere comunque inutilizzabile perché non entra nel suo slot.
Per ogni gruppo di frasi, chiedo a Claude Haiku una traduzione parlata naturale che preferisca formulazioni più brevi e meno sillabe. La risposta preserva ogni indice del segmento sorgente.
Il prompt fa parte del sistema audio. Il suo compito non è solo l'accuratezza linguistica. Riduce anche lo stretching temporale necessario in seguito.
Resta un'euristica. Un LLM non può garantire la durata perché la voce selezionata cambia anche il ritmo. Il layer audio misura comunque il WAV generato. Una cache in memoria, indicizzata per lingua target e segmenti sorgente, consente ai rendering successivi di riutilizzare la traduzione finché il worker resta attivo.
Sintetizzare una frase alla volta
Ogni frase tradotta va alla REST API di Google Cloud Text-to-Speech come audio LINEAR16 a 24 kHz. I nomi delle voci seguono il formato locale-Chirp3-HD-speaker documentato da Google.
Google supporta più locale Chirp 3 HD di quante Katto ne esponga attualmente. Ho deliberatamente limitato il prodotto a 19 lingue cablate attraverso il percorso completo: UI, mappatura locale, font, sottotitoli e comportamento di fallback. Un'API che dichiara una lingua non significa che il prodotto circostante la supporti correttamente.
Far entrare il parlato nello slot senza distruggerlo
Dopo la sintesi, confronto la durata generata con lo slot originale.
target_duration = segment["end"] - segment["start"]
ratio = generated_duration / target_duration
Se il parlato è leggermente troppo lungo, il filtro atempo di FFmpeg lo accelera preservando il pitch. Limito l'accelerazione a 1,3x.
Quel limite conta. Un limite precedente di 1,6x faceva entrare più frasi, ma alcune voci suonavano innaturalmente affrettate. Un allineamento perfetto non è utile se il risultato è sgradevole da ascoltare.
Ogni frase aggiustata viene posizionata al suo offset originale in una traccia master. Le frasi brevi lasciano una pausa naturale. Le frasi più lunghe ricevono una correzione vincolata. Questo non risolve ogni traduzione patologica. Impone una regola più utile: preservare l'intelligibilità prima di inseguire un timing matematicamente perfetto.
Dare a parlato e sottotitoli lo stesso orologio
La risposta di sintesi mi dà audio, non timestamp affidabili delle parole per il testo appena parlato. Inventare timing a livello di parola farebbe sembrare i sottotitoli precisi pur essendo sbagliati.
Le clip doppiate usano quindi sottotitoli a livello di frase generati dagli stessi segmenti tradotti usati per il parlato. I loro tempi di start ed end corrispondono già al posizionamento audio.
Il renderer seleziona anche font che coprono lo script target. I font latini non bastano per giapponese, cinese, hindi o arabo. I titoli intro e gli hook AI seguono lo stesso percorso di localizzazione, così lo schermo non parla una lingua e ne mostra un'altra.
Anche i problemi ordinari di produzione contavano
Non ogni speaker curato funzionava in ogni locale testato. Se una voce selezionata non è disponibile, Katto riprova una volta con un default noto per il genere scelto. L'anteprima live dell'editor chiama lo stesso motore Google. Un campione da un altro modello permetterebbe all'utente di scegliere una voce che non riceverà mai.
La chiave API di produzione è ristretta all'indirizzo IPv4 del VPS, ma il VPS preferiva IPv6 quando raggiungeva Google. Richieste valide venivano rifiutate finché la chiamata TTS non è stata forzata attraverso IPv4. L'API, la chiave e il codice erano corretti. Il percorso di rete no.
Il dubbing produce una variante video separata. Se traduzione, sintesi, rendering dei sottotitoli o remuxing falliscono, la clip originale rimane intatta. Per le otto lingue originali, Kokoro resta disponibile quando il percorso Google è disabilitato o non configurato.
Cosa è cambiato e cosa no
Il risultato visibile è stata un'espansione da 8 a 19 lingue di dubbing, più voci selezionabili e anteprime live.
Il miglioramento più profondo è stato architetturale. Traduzione, parlato, sottotitoli, overlay e rendering video ora condividono un'unità temporale: il segmento di frase.
Il sistema non clona lo speaker originale, non esegue lip sync né inventa timestamp generati a livello di parola. Traduzioni molto lunghe possono ancora eccedere il loro slot ideale. Questi limiti sono meglio che dichiarare una precisione che la pipeline non può garantire.
Pensavo di sostituire un motore vocale. Ho finito per stringere il contratto tra quasi ogni stadio della pipeline media.
La chiamata API era la parte facile. Far appartenere il risultato alla timeline originale è stato il lavoro vero.
Katto trasforma video lunghi in clip verticali brevi e ora può doppiare quelle clip in 19 lingue. Se stai costruendo video multilingue, mi interesserebbe sapere come gestisci il timing senza far sembrare la voce affrettata.
Riferimenti
Pronto a trasformare i tuoi video in clip virali?
Katto taglia, sottotitola e riformatta automaticamente i tuoi video lunghi in contenuti brevi.
Prova Katto gratis →