Tal till text i realtid under 200 ms: En arkitekturguide
- Publicerad
- Senast uppdaterad
LyssnaLyssna på den här artikeln
Tal till text (STT) i realtid transkriberar aktivt ljud medan en person talar och returnerar orden som text inom några hundra millisekunder. Men att hålla STT-latensen låg är lika mycket en arkitekturfråga som en modellfråga. Utvecklare måste planera för transport, chunking, slutpunktsdetektering och insamlingskedjan, som alla bidrar till latensen. Ineffektivitet i någon av dem kan överskrida din budget på 200 ms.
Den här guiden ger dig ett praktiskt upplägg för att bygga pipelines för tal till text i realtid, från transportlagret och uppåt. Vi utgår från Scribe v2 Realtime, som producerar partiella transkriberingar med cirka 150 ms modellatens, stöder fler än 90 språk, tar emot PCM-ljud (8 kHz–48 kHz) och mu-law-ljud samt erbjuder Voice Activity Detection och manuell commit-kontroll för att slutföra segment.
Vi går igenom hur ljudet når servern, hur hypoteser utvecklas till bekräftad text, vad funktioner i strömmen kostar och hur du samlar in och vidarebefordrar ljud korrekt.
Sammanfattning
- Att skapa system för tal till text i realtid kräver finjustering av arkitekturen så att latensen hålls låg genom hela pipelinen.
- WebSocket är rätt standardval för de flesta pipelines, även om WebRTC erbjuder flera fördelar och är mer komplext.
- Voice Activity Detection hanterar handsfree-segmentering, medan manuell commit ger dina applikationer möjlighet att åsidosätta den när de vet att turen är slut.
- Partiella resultat är preliminära och slutliga resultat är bekräftade, vilket innebär att du bör visa dem på olika sätt.
- Små PCM-chunkar på omkring 100 ms minimerar latensen till det första partiella resultatet.
WebSocket jämfört med WebRTC för tal till text i realtid
Innan någon transkribering kan ske måste ljudet färdas från källan till igenkännaren. Kanalen du väljer sätter lägstanivån för latensen i allt som följer. Det finns två möjliga alternativ för att få ljud till transkriberingslagret.
WebSocket är en långlivad, ordnad, tillförlitlig och dubbelriktad kanal över TCP. Du öppnar en anslutning, skickar upp binära ljudramar och läser ner transkriptionshändelser. Den är enkel att använda både på klient- och serversidan, passerar företagsproxyservrar och brandväggar som redan tillåter HTTPS och stöds av alla webbläsare och servermiljöer.
Begränsningen med WebSocket är att den körs över TCP. Om ett paket förloras skickar TCP om det och håller tillbaka senare data tills luckan har fyllts. Under goda nätverksförhållanden märks detta inte. Vid paketförlust skapas head-of-line-blockering: ett kort stopp där ljudet köas upp och sedan kommer i en burst.
WebRTC är byggt för realtidsmedia. Det kör media över UDP (via SRTP), så ett förlorat paket stoppar inte strömmen; pipelinen fortsätter. Det innehåller en jitterbuffert som hanterar variationer i paketens ankomsttid, förhandlar NAT-traversering med ICE/STUN/TURN så att parter bakom routrar kan ansluta och har egen funktionalitet för ljudinsamling och kodning.
Du behöver vanligtvis TURN-servrar för klienter som inte kan ansluta direkt, och serversidan måste avsluta en medieström i stället för att läsa en byteström.
Här är avvägningen i korthet:
För de flesta användningsfall är WebSocket rätt alternativ. Använd det när dina klienter har god anslutning och du kontrollerar insamlingskedjan: server-till-server-pipelines, skrivbordsappar, webbläsarappar med bredbandsanslutning och de flesta contact center-backends där ljudet redan når din server på något annat sätt.
Välj WebRTC när du samlar in ljud direkt från konsumentenheter på opålitliga mobilnät, när du redan kör en WebRTC-stack för tvåvägsljud, till exempel en röstagent som också svarar med tal, eller när realtidsbeteende med låg paketförlust är viktigare än enkel implementering.
Resten av guiden använder WebSocket-transport för anslutningen till igenkännaren, eftersom den gör delarna i systemet tydliga och är en bra startpunkt för de flesta team. Inget av detta är specifikt för WebSocket, så du kan senare lägga till ett WebRTC-medialed framför, avkoda ljudet till PCM på servern och skicka samma chunkar vidare i pipelinen.
Partiella och slutliga transkript: förklarade mellanresultat
En igenkännare i realtid väntar inte på en fullständig mening innan den ger resultat. I stället skickar den en löpande ström av gissningar som förfinas när mer ljud kommer in och sedan låses. Att förstå skillnaden mellan dessa två tillstånd är vad som skiljer ett levande transkript från ett som känns trasigt.
En partiell hypotes är modellens bästa gissning utifrån ljudet den hittills har tagit emot. Partiella resultat är avsiktligt instabila. När mer ljud kommer in reviderar modellen tidigare ord: ”Jag vill ha” kan bli ”Jag vill ha två biljetter” när senare kontext löser tvetydigheten. De kommer snabbt – det är vad siffran på cirka 150 ms latens beskriver – och är avsedda att skrivas över.
En slutlig hypotes är ett bekräftat segment som inte kommer att ändras. När ett segment har slutförts går igenkännaren vidare, och efterföljande hypoteser beskriver senare ljud. Slutliga resultat är det du sparar, skickar till en LLM eller lagrar som ett transkript.
Skillnaden mellan partiella och slutliga resultat styr tre saker som du får fel om du blandar ihop dem:
- Användarupplevelse: Att visa partiella resultat får ett transkript att kännas levande: användaren ser ord visas medan hen talar, vilket bekräftar att mikrofonen fungerar och att systemet lyssnar.
- Slutpunktsdetektering: Partiella resultat ger dig en kontinuerlig signal om talaktivitet. Tillsammans med VAD kan de hjälpa dig avgöra när talaren faktiskt har slutat.
- Timing i efterföljande steg: I en pipeline för röstagenter är stegen ljud in, sedan tal till text, sedan en LLM, sedan text till tal, sedan ljud ut. Du kan påbörja spekulativt arbete på partiella resultat och bekräfta det på slutliga resultat, vilket minskar den upplevda svarstiden men ibland innebär att spekulativt arbete måste kasseras.
Visa partiella och slutliga resultat på olika sätt. Ett enkelt och effektivt mönster är att ha en enda föränderlig ”aktuell rad” kopplad till det senaste partiella resultatet och bekräfta den i ett transkript som bara utökas när ett slutligt resultat kommer:
Visa bekräftad text som fast text och den aktuella texten i en ljusare eller kursiv stil, så att användaren förstår att den fortfarande kan ändras.
Slutpunktsdetektering och röstaktivitetsdetektering (VAD)
Att veta vad som sades är bara halva arbetet. En igenkännare måste också veta när en tanke har avslutats. Det avgör när du slutför ett segment och, i en agent, när systemet börjar svara.
Slutpunktsdetektering är beslutet att ett yttrande har avslutats. Om du slutför för tidigt avbryts användare mitt i en mening. Om du slutför för sent förblir en agent tyst efter att användaren tydligt har pratat färdigt.
Scribe v2 Realtime ger dig två kompletterande mekanismer:
- Voice Activity Detection segmenterar ljud utifrån tystnad: Igenkännaren upptäcker när tal övergår i ihållande tystnad och använder den gränsen för att automatiskt slutföra ett segment. VAD är rätt standardval för konversationsgränssnitt eftersom det anpassar sig till naturlig talrytm utan att du behöver hålla koll på tiden manuellt.
- Manuell commit-kontroll: Med manuell commit-kontroll kan din applikation avgöra när det aktuella segmentet ska slutföras, oberoende av tystnad. Du skickar en commit-signal, igenkännaren stänger det aktuella segmentet och skickar ett slutligt resultat. Det är rätt verktyg när din applikation redan vet att turen är över: när en push-to-talk-knapp släpps, vid en ”skicka”-åtgärd eller enligt en extern policy för turordning.
De två fungerar bra tillsammans. En typisk röstagent använder VAD för handsfree-användning och erbjuder manuell commit som en åsidosättning. Då avbryts inte en användare som pausar för att tänka, medan en användare som trycker på en knapp får en omedelbar gräns.
Tystnadströskeln innebär en verklig avvägning utan något universellt korrekt värde:
- En kort timeout efter talets slut, till exempel slutförande efter cirka 200–400 ms tystnad, gör att systemet känns responsivt. Men den avbryter också användare som naturligt pausar mellan satser, delar upp en tanke i flera segment och kan i en agent utlösa ett för tidigt svar.
- En lång timeout, till exempel cirka 800–1 200 ms, tolererar naturliga pauser och håller yttranden sammanhängande, men innebär en märkbar fördröjning innan systemet reagerar.
Det finns ingen global konstant att använda här; anpassa tröskeln till interaktionen:
- Diktering och anteckningar tolererar längre pauser eftersom användare tänker mitt i meningar. Välj hellre längre timeouter och använd VAD.
- Kommando- och kontrollagenter samt transaktionsagenter gynnas av kortare timeouter tillsammans med manuell commit, eftersom turerna är korta och tydliga.
- Flerspråkiga talare eller talare med språket som andraspråk pausar mer, så avsätt mer tystnad innan du slutför.
Med de här tipsen kan du bygga ett effektivt system för slutpunktsdetektering och komma närmare tal till text i realtid.
Funktioner i strömmen: språkidentifiering och talardiarisering
Strömmande igenkänning kan göra mer än att producera ord. Men varje extra signal du begär påverkar latensen och stabiliteten. Tumregeln är att bara aktivera det som behövs för liveupplevelsen och skjuta upp resten till en batchkörning.
Automatisk språkidentifiering låter Scribe v2 Realtime identifiera det talade språket bland fler än 90 språk som stöds, i stället för att kräva att du anger det i förväg. Kostnaden är att modellen behöver ett kort ljudavsnitt för att avgöra språket säkert, så de första partiella resultaten i en ström kan vara mindre stabila medan språket fastställs. Om du redan känner till språket tar en specifikation av det bort den tvetydigheten och ger vanligtvis stabilare tidiga partiella resultat.
Talardiarisering tillskriver tal till olika talare och identifierar vem som sa vad. I batchtranskribering är detta jämförelsevis enkelt eftersom modellen ser hela filen. Vid strömning är det svårare: igenkännaren måste tilldela en talaretikett baserat enbart på ljudet hittills, och en etikett som ges till tidigt ljud kan behöva revideras när mer av talarens röst har hörts. Hantera talaretiketter i strömmande ljud på samma sätt som partiell text: de är preliminära tills segmentet slutförs.
Ordtiming och entitetskontext följer samma logik. Ju mer metadata per token du begär, desto mer måste både modellen och anslutningen bära. I de flesta realtidsgränssnitt behöver du bara texten och segmentgränserna live, och du kan skjuta upp detaljerad metadata till en batchkörning efter samtalet med Scribe v2.
Ljudformat för strömning: PCM och mu-law
Transport- och igenkänningslogik får mest uppmärksamhet, men förvånansvärt många verkliga buggar uppstår ett lager längre ner, i hur du kodar och chunkar ljudet. Att välja rätt format och chunkstorlek är det billigaste sättet att minska latensen för tal till text.
PCM (linjärt, 16-bitars signerat, little-endian) är formatet att använda när du kontrollerar insamlingen. Högre samplingsfrekvenser ger mer akustisk detalj: 16 kHz är standardnivån för taligenkänning och räcker vanligtvis, medan 8 kHz är telefonkvalitet och förlorar högfrekvent innehåll. Använd frekvensen som matchar din källa. Det finns ingen fördel med att sampla upp telefoni-ljud på 8 kHz till 48 kHz, eftersom informationen inte går att återskapa.
Mu-law vid 8 kHz är telefoni-formatet. Om du tar emot samtal från en leverantör som Twilio kommer ljudet som 8 kHz mu-law, och du bör vidarebefordra det i det formatet i stället för att omkoda det två gånger. Att matcha källformatet undviker omsamplingsartefakter och ett onödigt konverteringssteg.
Chunkstorleken är den faktor som mest direkt formar den upplevda latensen. Du skickar ljud i chunkar, och igenkännaren producerar partiella resultat när chunkarna kommer in. Mindre chunkar innebär tätare uppdateringar och lägre latens till det första partiella resultatet; större chunkar innebär färre meddelanden och något mer kontext per inferens. Ett praktiskt intervall är 20–250 ms ljud per chunk. Vid mono-PCM på 16 kHz och 16 bitar är en sekund ljud 32 000 byte, så en chunk på 100 ms är cirka 3 200 byte.
Samla in mikrofoninmatning i webbläsaren
I webbläsaren är rätt verktyg Web Audio API tillsammans med en AudioWorklet. Workleten körs på tråden för ljudrendering, tar emot ljud i små ramar och påverkas inte av fördröjningar i huvudtråden på samma sätt som den äldre ScriptProcessorNode. Dess uppgift är att konvertera webbläsarens inbyggda float-samplingar till 16-bitars PCM och skicka dem till huvudtråden, som vidarebefordrar dem via WebSocket.
Kärnan i worklet-processorn är konverteringen från float till PCM:
Pipelinen i kod
Pipelinen har tre delar: en webbläsarklient som samlar in mikrofonljud och strömmar PCM till din server, en Node-server som vidarebefordrar ljud till Scribe v2 Realtime och skickar tillbaka transkript samt en skriptbar klient som strömmar PCM från en fil eller telefonibrygga.
Servern vidarebefordrar i stället för att exponera igenkännaren direkt för webbläsaren av en viktig anledning: din ElevenLabs API-nyckel är hemlig och får aldrig förekomma i kod på klientsidan. Nyckeln finns på servern. Om webbläsaren ändå måste kommunicera direkt med igenkännaren skapar du en kortlivad engångstoken på serversidan och ger klienten den i stället för API-nyckeln.
Webbläsarklient
Klienten öppnar en WebSocket till din server, samlar in mikrofonljud via workleten ovan och vidarebefordrar varje PCM-ram när den produceras. Inkommande händelser, som servern redan har normaliserat till { type, text }, styr tillståndet för partiella och slutliga resultat från tidigare:
Servervidarebefordran
Servern öppnar en igenkännaranslutning per klient, behåller API-nyckeln på servern, vidarebefordrar binär PCM direkt och normaliserar igenkännarhändelser till det stabila formatet { type, text } som klienten använder:
Allt som är specifikt för en endpoint är begränsat till de två adapterfunktionerna nedan. Ersätt fältnamnen med de exakta namnen från Speech to Text-referensen; resten av pipelinen ändras inte:
Skriptbar backendklient
För backendpipelines och för benchmarken nedan fungerar samma igenkännaranslutning utan en webbläsare: läs PCM från valfri källa, skicka den i realtidskadens för chunkar och läs tillbaka händelser. API-nyckeln och URL:en kommer från miljön, precis som på servern.
Benchmarking av latens för tal till text och ordfelfrekvens
Både latens och ordfelfrekvens varierar med talaren, språket, de akustiska förhållandena, ljudets längd, din nätverksväg till varje leverantörs närmaste region och den aktuella belastningen på varje tjänst.
Ett resultat som mäts från en bärbar dator i en stad går inte att generalisera till din produktionsmiljö i en annan. Kör testverktyget från infrastruktur som liknar produktionen, med ljud som liknar din verkliga indata, och rapportera intervall och fördelningar i stället för enskilda siffror.
De enda siffror för latens och precision som spelar roll är de du mäter på ditt eget ljud från infrastruktur som liknar produktionen. Här är en guide till benchmarking av latens för tal till text.
Vad du ska mäta för latens i tal till text
Nedan är de viktigaste måtten du bör mäta när du benchmarkar latens för tal till text i realtid:
- Tid till första partiella resultat: Från att den första ljudchunken skickas tills det första icke-tomma partiella resultatet tas emot.
- Fördröjning från partiellt till slutligt resultat: Från den sista ljudchunken i ett yttrande till den slutliga hypotesen.
- Ordfelfrekvens (WER): WER för det slutförda transkriptet jämfört med en mänsklig referens, beräknad på samma sätt för alla system.
- Stabilitetsförändringar: Hur många partiella resultat som skrivs om före slutförandet. Måttet är en indikator på hur mycket det visuella gränssnittet verkar förändras live.
Kontroller
För att undvika opålitliga data bör du införa flera kontroller i experimentet för att hålla förutsättningarna konsekventa.
Här är de viktigaste kontrollerna vid benchmarking av latens för tal till text:
- Identiskt ljud: Använd samma filer, samplingsfrekvens och kodning för varje system.
- Identisk kadens: Strömma varje system med samma realtidskadens för chunkar, till exempel chunkar på 100 ms.
- Upprepa och rapportera fördelningar: Kör varje fil många gånger under dagen och rapportera median och svansvärden (p50/p95).
- Identiska referenser och poängsättning: Normalisera texten på samma sätt, med versaler/gemener, skiljetecken och siffror, innan du beräknar WER.
- Redovisa region och nätverk: Ange var testverktyget kördes och vägen till varje leverantör.
Genom att hålla alla dessa delar identiska får du mer exakta mätvärden.
Grundstruktur för testverktyget
Mätkärnan tar en leverantörsadapter och registrerar tid till första partiella resultat, fördröjning till slutförande och förändringar i partiella resultat:
Ordfelfrekvens är ett standardmått baserat på Levenshtein-avstånd på tokennivå över normaliserad text. Gör om både referens och hypotes till gemener och ta bort skiljetecken på identiskt sätt innan beräkningen, annars mäter du din normaliserare snarare än modellen. Kör måttet i en loop som kör varje fil cirka 10 gånger per leverantör och rapporterar median för tid till första partiella resultat och median-WER (p50/p95), eftersom ett enskilt prov främst påverkas av nätverksvariation.
För att få det att fungera behöver du tillhandahålla två saker. För det första skriver du en StreamFn-adapter per system. Den skriptbara klienten ovan är redan en sådan, och adaptrarna för de andra följer samma kontrakt, (audioPath, onEvent, result), och anger result.lastChunkSentAt när den sista ljudchunken skickas. För det andra laddar du dina ljudfiler och referenser och anropar mätningar för dem. Kör det från en maskin som representerar din driftsättning, med ljud som representerar dina användare, så får du en jämförelse som går att reproducera.
Sammanfattning: så uppnår du tal till text i realtid
Vi har gått igenom många arkitekturändringar i den här artikeln som gör att du stegvis kan förbättra ditt system och närma dig tal till text i realtid.
Ett produktionssystem för STT i realtid handlar om ett fåtal beslut:
- Transport: Välj WebSocket för enkelhet och kontrollerade nätverk, och WebRTC när du behöver tåla paketförluster och samlar in ljud från konsumentenheter.
- Partiella och slutliga resultat: Behandla partiella resultat som preliminära och slutliga resultat som bekräftade, och visa dem på olika sätt så att användarna litar på live-texten.
- Slutpunktsdetektering: Använd VAD för handsfree-segmentering, manuell commit som åsidosättning och anpassa tystnadströskeln till interaktionen i stället för att använda en konstant.
- Funktioner i strömmen: Aktivera funktioner i strömmen endast där liveupplevelsen behöver dem och skjut upp resten till en batchkörning med Scribe v2.
- Ljudformat: Samla in små PCM-ramar, skicka chunkar på cirka 100 ms och matcha källformatet för telefoni.
- Benchmarking: Ställ in reglagen för precision kontra latens empiriskt mot ditt eget ljud och målvärde.
- API-säkerhet: Behåll din API-nyckel på servern, eller skapa engångstoken för direkta klientanslutningar.
Om du vill se hur du kan optimera latensen i en röstagent, har vi också skrivit en guide om det.
Bygg system för tal till text i realtid med Scribe v2 Realtime
Scribe v2 Realtime producerar partiella resultat med cirka 150 ms modellatens. Om dina användare upplever den latensen eller något högre beror på arkitekturen runt omkring, vilket är den del du kontrollerar. Genom att använda strategierna i den här artikeln kan du bygga en bättre pipelinearkitektur som minskar latensen och förbättrar kundupplevelsen.
Om du vill gå djupare kan du läsa översikten över funktionerna i Speech to Text, gå igenom vår modellreferens för en fullständig lista över funktioner och språk samt besöka produktsidorna för realtid: Speech to Text API i realtid och Speech to Text i realtid.
När du är redo att bygga, skapa ett kostnadsfritt ElevenLabs-konto och strömma ditt första transkript i dag.



