Gran parte del ritardo nella traduzione in diretta è attesa: attesa del flusso, della parola successiva, della frase. L'unica parte su cui hai controllo è la modalità di latenza: meno ritardo oppure meno revisioni.
Un ascoltatore che legge una traduzione in diretta vede ogni riga qualche secondo dopo che l'oratore l'ha pronunciata. Questo ritardo non è unico, ma la somma di più ritardi lungo una catena, e la maggior parte di essi è una forma di attesa. Capire quale attesa è quale rende facile la scelta della modalità di latenza, e dice a uno sviluppatore che sta costruendo un lettore cosa mostrare, e quando.
Un utile metro di paragone prima dei numeri: un interprete simultaneo umano di solito parla con due-quattro secondi di ritardo rispetto a chi parla. Gli interpreti chiamano questo scarto ear-voice span e, nelle lingue con il verbo in fondo, non aspettano il verbo ma lo anticipano, oppure spezzano la frase in parti che possono reggersi da sole. Uno o due secondi di ritardo non sono un difetto del software: è più o meno ciò che fa un ottimo interprete umano.
Ogni trascrizione in diretta su VocalStack attraversa le stesse fasi, nello stesso ordine, e ciascuna attende quella precedente.
Il testo nella lingua originale arriva a chi legge quasi nel momento in cui viene pronunciato. La traduzione segue da uno a due secondi dopo, e la frase pronunciata arriva dopo la sua traduzione, per questo una clip vocale arriva sempre per ultima. Il primo effetto visibile della catena, però, si manifesta molto prima di qualsiasi voce: il testo stesso si muove.
La prima cosa che si nota in una trascrizione in diretta è che le parole più recenti si spostano. Una frase compare, cambia e si stabilizza. È la fase di bozza al lavoro, e ha una ragione che vale per ogni riconoscitore vocale.
Un riconoscitore stabilisce una parola guardando cosa viene dopo. «Ho un'idea» e «o un'idea» suonano quasi uguali finché non arriva la parola successiva; una consonante finale può appartenere a questa parola o alla successiva. Finché non c'è audio alla destra di una parola, la sua grafia è un'ipotesi, quindi le parole più recenti di qualsiasi trascrizione in diretta sono sempre le meno certe. Una bozza è semplicemente quell'ipotesi mostrata in anticipo anziché nascosta.
Ogni bozza sostituisce interamente la coda in diretta: le parole ascoltate dall'ultimo commit, che stanno ancora cambiando. Un commit è definitivo. Non cambia mai, porta i tempi a livello di parola, e i commit sono numerati senza buchi, così chi legge può capire se ne ha perso uno.
Per uno sviluppatore è questa la regola che l'API realtime impone: mostrare ogni segmento committato, poi l'ultima bozza dopo di essi, e cancellare la bozza quando arriva un commit. Accodare le bozze invece di sostituirle produce testo duplicato e lampeggiante; il commit consuma semplicemente la coda. Il tutorial WebSocket costruisce un lettore proprio attorno a questo principio.
Per un ospite, il testo che si sposta è il prezzo di un ritardo basso. Mostrare le parole prima che la frase sia finita è ciò che rende la trascrizione viva. La traduzione, invece, non può permettersi questo trucco, perché una parola può essere indovinata da metà frase, ma una traduzione no.
È l'ordine delle parole a impedire alla traduzione di tenere il passo della bozza. Un verbo tedesco può trovarsi alla fine della sua proposizione, e il giapponese mette il verbo in ultima posizione. Qualsiasi traduttore ha bisogno dell'intera proposizione per renderla fedelmente. Tradurre parola per parola consegna a chi ascolta frammenti che devono restare in sospeso fino alla chiusura della proposizione. Il tedesco ha costretto gli interpreti ad aspettare il verbo molto prima che il software ci provasse.
VocalStack quindi traduce frasi, non segmenti. Le frasi sono attive per impostazione predefinita e, con questa opzione attiva, il server assembla i commit in una frase e traduce la frase intera. Finché la frase è aperta la sua traduzione è provvisoria; una volta chiusa, la traduzione è definitiva. Chi legge tiene un'unica voce per frase e la sostituisce man mano che arrivano gli aggiornamenti.
La voce attende ancora di più. Viene letta solo una frase chiusa, perché una frase che sta ancora cambiando verrebbe sintetizzata di nuovo a ogni revisione. Una frase lunga viene letta a pezzi, così il primo può essere riprodotto mentre gli altri vengono generati.
Con le frasi disattivate, ogni commit ottiene invece il proprio fotogramma di traduzione. Questo percorso non attende nulla, ma le frasi intere si leggono molto meglio.
Tutte queste attese si misurano dal momento in cui l'audio arriva a VocalStack. Per molte trasmissioni, l'audio era già in ritardo quando è arrivato.
Quando la sorgente è uno stream e non un microfono, l'audio è già indietro prima che venga trascritto nulla. Resta indietro rispetto al live edge, cioè il momento più recente che lo stream ha pubblicato.
Un normale stream audio HTTP, il tipo che usano la maggior parte delle radio online, di solito accusa un ritardo da uno a tre secondi. Il server mantiene un burst buffer: alcuni secondi di audio recente, inviati tutti insieme perché il player di un nuovo ascoltatore possa partire senza bloccarsi. Ogni ascoltatore, VocalStack compreso, si unisce con questo ritardo. HLS è peggio: le sue playlist fanno partire il client tre segmenti indietro rispetto al live edge, il che in pratica significa diversi secondi fino a mezzo minuto, a seconda della durata dei segmenti. Il DASH standard di solito rientra nello stesso intervallo dell'HLS; solo la sua variante a bassa latenza scende sensibilmente sotto. Lo stream «in diretta» di una radio può essere in diretta nel senso in cui una lettera è «attuale».
Queste cifre sono approssimative e riguardano lo stream, non la trascrizione: nessuna impostazione lato VocalStack può recuperarle. Se quei secondi sono importanti per un evento, invia l'audio alla sorgente da un microfono o da un encoder anziché da uno stream pubblico. Il ritardo dello stream è fissato prima che VocalStack senta una parola; la modalità di latenza è ciò che puoi davvero spostare.
La modalità di latenza fa una sola cosa: stabilisce il bilanciamento tra ritardo e precisione. L'impostazione si trova sotto Advanced quando si crea una trascrizione in diretta, e nella scheda Speed mentre è in corso. Lì il chip mostra AUTO, SPEED o ACCURACY (Fast compare come SPEED). Tramite API, session.update cambia la modalità durante lo stream.
Il compromesso è quello che suggeriscono i nomi. Fast fa uscire il testo prima, ma ne revisiona di più; Accuracy richiede un po' più di tempo e revisiona meno. Un pubblico seduto che legge sottotitoli tradotti raramente nota un secondo in più, ma nota le parole che continuano a cambiare. Accuracy è quindi spesso l'impostazione più gentile, purché il grafico del ritardo resti piatto. Auto mostra le sue carte: una riga che ha accelerato per chiudere un divario porta un badge FAST MODE nella trascrizione dell'ospite, con una nota che avverte che lì la precisione potrebbe essere inferiore.
Qualunque sia la modalità, la trascrizione deve essere pronta prima della prima parola, e prepararla è l'unico ritardo che la catena paga una sola volta.
Con alcuni piani una trascrizione in diretta impiega alcuni secondi per partire. Quanto dipende dal piano: la riga Start-up speed nella pagina dei prezzi va da un avvio a freddo fino a 15 secondi con pay as you go fino a un'istanza sempre calda con Enterprise.
Tramite API, l'attesa si manifesta con i fotogrammi session.loading mentre la sessione parte, poi con session.ready; il client invia audio solo dopo. Un ascoltatore che nel frattempo apre il link vede «In diretta. La prima riga compare a momenti.» Una volta che la trascrizione è in esecuzione, questo ritardo è alle spalle, e l'unica domanda rimasta è quanto del ritardo residuo stai portando con te.
Mentre una trascrizione in diretta è in corso, la scheda Speed dell'ospite mostra il risultato complessivo di tutto questo: il divario attuale tra chi parla e il testo, con accanto il chip della modalità, e un grafico di quel divario lungo tutta la registrazione con la media e il picco. Nella trascrizione, una riga arrivata in ritardo agli ascoltatori porta un badge con il numero di secondi tra il momento in cui è stata pronunciata e quello in cui è arrivata.
Un grafico che resta basso e piatto significa che la modalità si adatta all'audio. Un grafico in salita significa che la pipeline è in ritardo. Su Accuracy, potrebbe essere il momento di passare ad Auto, che scambia un po' di precisione con la velocità finché il divario non si chiude.
Per gli sviluppatori c'è invece un solo numero. Quando una sessione realtime termina, session.done riporta stats.realtimeFactor, cioè l'audio trascritto diviso per il tempo impiegato a trascriverlo. Un avvertimento sulla convenzione: nella letteratura sul riconoscimento vocale, real-time factor di solito indica il contrario, cioè tempo di elaborazione diviso tempo dell'audio, dove un valore più basso è migliore. VocalStack lo riporta al contrario, quindi qui più alto è meglio: una sessione in diretta si attesta intorno a 1, e sotto 1 significa che l'audio è arrivato più in fretta di quanto la pipeline riesca a trascriverlo.
Nessuno di questi secondi è misterioso. Alcuni appartengono allo stream, alcuni a una parola che attende la successiva, alcuni alla frase di cui una traduzione ha bisogno, e il resto alla modalità di latenza che hai scelto. Il riferimento API contiene il dettaglio fotogramma per fotogramma, e la demo nella home page mostra la catena in funzione.