Det mesta av fördröjningen i livesöversättning är väntan: på strömmen, på nästa ord, på meningen. Den del du kan styra är latensläget: mindre fördröjning eller färre revideringar.
En lyssnare som läser en livesöversättning ser varje rad några sekunder efter att talaren sagt den. Gapet är inte en enda fördröjning utan flera, adderade längs en kedja, och de flesta av dem är en form av väntan. Att veta vilken väntan som är vilken gör valet av latensläge enkelt, och säger till en utvecklare som bygger en läsare vad som ska renderas, och när.
En användbar måttstock innan siffrorna: en mänsklig simultantolk ligger vanligtvis två till fyra sekunder efter talaren. Tolkar kallar gapet för ear-voice span, och de klarar språk med verbet sist inte genom att vänta in verbet utan genom att förutse det, eller genom att dela upp meningen i bitar som kan stå på egna ben. En eller två sekunders fördröjning är inget fel i programvaran; det är ungefär vad en mycket bra människa åstadkommer.
Varje livetranskribering hos VocalStack passerar samma steg, i samma ordning, och varje steg väntar på det föregående.
Textens originalspråk når läsaren nästan i samma stund som det sägs. Översättningen kommer en till två sekunder senare, och den talade meningen kommer efter sin översättning, vilket är anledningen till att ett röstklipp alltid kommer sist. Kedjans första synliga effekt kommer dock långt före någon röst: själva texten rör sig.
Det första man lägger märke till i ett livetranskript är att de nyaste orden rör sig. En fras dyker upp, ändras och sätter sig. Det är utkaststeget som arbetar, och det finns av en orsak som gäller för varje taligenkännare.
En taligenkännare avgör ett ords stavning genom att titta på vad som kommer efter det. "I scream" och "ice cream" låter likadant tills nästa ord kommer, och ett avslutande "s" kan höra till det här ordet eller nästa. Tills det finns ljud till höger om ett ord är dess stavning en gissning, så de nyaste orden i varje livetranskript är alltid de minst säkra. Ett utkast är helt enkelt den gissningen, visad tidigt i stället för gömd.
Varje utkast ersätter hela livesvansen: orden som hörts sedan den senaste bekräftelsen och som fortfarande ändras. En bekräftelse är slutgiltig. Den ändras aldrig, den bär ordvisa tidsstämplar, och bekräftelserna är numrerade utan luckor så att en läsare kan se om någon har missats.
För en utvecklare är detta den enda regel som realtids-API:et kräver: rendera varje bekräftat segment, sedan det senaste utkastet efter dem, och rensa utkastet när en bekräftelse kommer. Lägger man i stället utkast efter varandra blir texten dubbel och flimrig; bekräftelsen förbrukar helt enkelt svansen. WebSocket-handledningen bygger en läsare kring just detta.
För en värd är rörliga ord priset för låg fördröjning. Att visa ord innan frasen är klar är det som gör att transkriptet känns levande. Översättningen har dock inte råd med det knepet, eftersom ett ord kan gissas utifrån en halv fras, men en översättning kan inte gissas på samma sätt.
Ordföljden är anledningen till att översättningen inte kan hålla jämna steg med utkastet. Ett tyskt verb kan stå sist i sitt led, och japanska sätter verbet sist. En översättare behöver hela ledet innan den kan återge det troget. Att översätta ord för ord ger lyssnaren fragment som måste läsas om när ledet är slut. Tolkar har fått vänta på verbet i tyska meningar sedan långt innan programvara började försöka.
VocalStack översätter därför meningar, inte segment. Meningar är påslaget som standard, och med dem på sätter servern ihop bekräftelser till en mening och översätter hela den. Medan meningen är öppen är dess översättning preliminär; när den stängs är översättningen slutgiltig. En läsare håller en post per mening och ersätter den när uppdateringar kommer.
Talet väntar ännu längre. Endast en stängd mening talas upp, eftersom en mening som fortfarande ändras skulle syntetiseras om vid varje revidering. En lång mening läses upp i bitar, så att den första kan spelas medan resten görs.
Med meningar avstängda får varje bekräftelse i stället en egen översättningsram. Den vägen väntar på ingenting, men hela meningar läses betydligt bättre.
Alla dessa väntetider mäts från det ögonblick ljudet når VocalStack. För många sändningar var ljudet redan försenat när det kom fram.
När källan är en ström i stället för en mikrofon ligger ljudet redan efter innan något transkriberas. Det släpar efter livekanten, det senaste ögonblick strömmen har publicerat.
En vanlig HTTP-ljudström, den typ som de flesta internetradiostationer publicerar, ligger vanligtvis en till tre sekunder efter. Servern håller en burst-buffert: några sekunder av det senaste ljudet, skickat på en gång så att en ny lyssnares spelare kan starta utan att fastna. Varje lyssnare, VocalStack inräknat, ansluter så långt bak. HLS är värre: dess spellistor startar en klient tre segment bakom livekanten, vilket i praktiken betyder flera sekunder till en halv minut beroende på segmentlängd. Standard-DASH hamnar oftast i samma intervall som HLS; bara dess lågfördröjningsvariant kommer under det med bred marginal. En stations ”live”-ström kan vara live på samma sätt som ett brev är aktuellt.
Siffrorna är ungefärliga, och de hör till strömmen, inte till transkriberingen: ingen inställning på VocalStacks sida kan hämta tillbaka dem. Om de sekunderna spelar roll för ett evenemang, mata in ljudet från en mikrofon eller en encoder i stället för från en offentlig ström. Strömfördröjningen är fast innan VocalStack hör ett ord; det är latensläget du faktiskt kan flytta.
Latensläget gör en enda sak: det sätter balansen mellan fördröjning och noggrannhet. Inställningen finns under Advanced när en livetranskribering skapas, och på fliken Speed medan den körs. Där visar etiketten AUTO, SPEED eller ACCURACY (Fast visas som SPEED). Via API:et ändrar session.update läget mitt i strömmen.
Avvägningen är den namnen antyder. Fast får ut text tidigare men reviderar mer av den; Accuracy tar lite längre tid och reviderar mindre. En sittande publik som läser översatta undertexter märker sällan en extra sekund, men märker ord som hela tiden ändras. Accuracy är därför ofta den snällare inställningen, så länge fördröjningsdiagrammet är platt. Auto visar sina kort: en rad som den snabbade upp för att täcka ett gap bär en FAST MODE-märkning i värdens transkript, med en notering om att noggrannheten kan vara lägre där.
Oavsett läge måste transkriberingen vara redo före första ordet, och att göra den redo är den enda fördröjning som kedjan betalar bara en gång.
På vissa abonnemang tar en livetranskribering några sekunder att starta. Hur lång tid det tar beror på abonnemanget: raden Start-up speed på prissidan sträcker sig från en kallstart på upp till 15 sekunder på Pay as you go till alltid varm på Enterprise.
Via API:et visas väntan som session.loading-ramar medan sessionen startar, och sedan en session.ready; klienten skickar ljud först efter det. En lyssnare som öppnar länken under tiden ser "Live. Första raden visas strax." När transkriberingen väl körs är den här fördröjningen bakom dig, och den enda frågan kvar är hur mycket av den återstående fördröjningen du bär.
Medan en livetranskribering körs visar värdens flik Speed vad allt detta summerar till: det aktuella gapet mellan talaren och texten, med latensetiketten bredvid, och ett diagram över gapet under hela inspelningen med medelvärde och topp. I själva transkriptet bär en rad som nådde lyssnarna sent en märkning med antalet sekunder mellan när den sades och när den kom fram.
Ett diagram som ligger lågt och platt betyder att läget passar ljudet. Ett diagram som stiger betyder att pipelinen hamnar efter. På Accuracy kan det vara läget att gå över till Auto, som byter lite noggrannhet mot fart tills gapet krymper.
Utvecklare får ett enda tal i stället. När en realtidssession avslutas innehåller session.done stats.realtimeFactor, den transkriberade ljudlängden delat med tiden som gick åt till att transkribera den. Ett varningsord om konventionen: i taligenkänningslitteraturen betyder real-time factor vanligtvis det omvända, bearbetningstid delat med ljudtid, där lägre är bättre. VocalStack anger det åt andra hållet, så här är högre bättre: en livesession ligger nära 1, och under 1 betyder att ljudet kom fram snabbare än pipelinen kunde transkribera det.
Inga av dessa sekunder är mystiska. Vissa hör till strömmen, några till ett ord som väntar på nästa ord, några till meningen som en översättning behöver, och resten till latensläget du valde. API-referensen har detaljerna bild för bild, och demon på startsidan visar kedjan i drift.