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 ett arkitekturproblem som ett modellproblem. Utvecklare måste planera för transport, chunkning, slutpunktsdetektering och fångstväg, som alla bidrar med latens. Ineffektivitet i någon av dessa kan överskrida din budget på 200 ms.
Den här guiden ger dig ett praktiskt system 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 ungefär 150 ms modellatens, stöder över 90 språk, tar emot PCM-ljud (8–48 kHz) och mu-law-ljud samt erbjuder Voice Activity Detection samt 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 fångar och vidarebefordrar ljud på rätt sätt.
Sammanfattning
- Att skapa system för tal till text i realtid kräver finjustering av arkitekturen, så att latensen hålls låg i hela pipelinen.
- WebSocket är rätt standardval för de flesta pipelines, även om WebRTC erbjuder flera fördelar men är mer komplext.
- Voice Activity Detection hanterar handsfree-segmentering, medan manuell commit ger dina applikationer möjlighet att åsidosätta när de vet att talomgången ä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 kontra WebRTC för tal till text i realtid
Innan någon transkribering kan ske måste ljudet färdas från källan till taligenkännaren. Kanalen du väljer sätter latensgolvet för allt som följer. Det finns två fungerande alternativ för att få ljudet till transkriberingslagret.
WebSocket är en långlivad, ordnad, tillförlitlig och dubbelriktad kanal över TCP. Du öppnar en anslutning, skickar binära ljudramar uppströms och läser transkriberingshändelser nedströms. Den är enkel på både klient och server, 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 det 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 uppstår 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 har en jitterbuffert som tar upp variationer i paketens ankomsttid, förhandlar NAT-traversering med ICE/STUN/TURN så att parter bakom routrar kan ansluta och har egen teknik för ljudfångst 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 fångstvägen: server-till-server-pipelines, skrivbordsappar, webbläsarappar på bredband och de flesta kontaktcenter-backends där ljudet redan når din server på något annat sätt.
Välj WebRTC när du fångar ljud direkt från konsumentenheter på opålitliga mobilnät, när du redan kör en WebRTC-stack för tvåvägsljud (exempelvis en röstagent som också talar tillbaka), eller när realtidsbeteende med låg paketförlust är viktigare än enkel implementering.
Resten av den här guiden använder WebSocket-transport för anslutningen till taligenkännaren, eftersom det gör de rörliga delarna synliga och är rätt startpunkt för de flesta team. Inget av detta är specifikt för WebSocket, så du kan senare lägga till en WebRTC-medialänk framför, avkoda ljudet till PCM på servern och vidarebefordra samma chunkar till pipelinen.
Partiella och slutliga transkript: förklaring av mellanresultat
En taligenkä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 låser sedan fast dem. Att förstå skillnaden mellan dessa två tillstånd är det som skiljer ett transkript som känns levande från ett som känns trasigt.
En partiell hypotes är modellens bästa gissning baserat på ljudet som har tagits emot hittills. 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 ~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 taligenkä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 påverkar tre saker som du kommer att göra fel om du suddar ut den:
- Användarupplevelse: Att visa partiella resultat får ett transkript att kännas levande: användaren ser ord dyka upp 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 låter de dig avgöra när talaren faktiskt har slutat.
- Timing nedströms: I en röstagent-pipeline är stegen ljud in, sedan tal till text, sedan en LLM, sedan text to speech, och sedan ljud ut. Du kan börja med spekulativt arbete på partiella resultat och bekräfta på slutliga resultat, vilket minskar den upplevda svarstiden men ibland kräver att spekulativt arbete 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 lägga till den i ett transkript som bara utökas när ett slutligt resultat kommer:
Visa bekräftad text som fastställd och den aktuella texten med 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 taligenkä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 avbryter du användare mitt i meningen. Om du slutför för sent förblir en agent tyst efter att användaren tydligt är klar.
Scribe v2 Realtime ger dig två kompletterande mekanismer att arbeta med:
- Voice Activity Detection segmenterar ljud utifrån tystnad: Taligenkä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å tid 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, taligenkännaren stänger det aktuella segmentet och skickar ett slutligt resultat. Det är rätt verktyg när din applikation redan vet att talomgången är slut: 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, så att en användare som pausar för att tänka inte avbryts, medan en användare som trycker på en knapp får en omedelbar gräns.
Tröskeln för tystnad är en verklig avvägning utan något universellt korrekt värde:
- En kort timeout efter talets slut (till exempel slutförande efter ~200–400 ms tystnad) får systemet att kännas 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 ~800–1200 ms) tolererar naturliga pauser och håller yttranden intakta, men medför en märkbar fördröjning innan systemet reagerar.
Det finns ingen global konstant att använda här; anpassa tröskeln efter interaktionen:
- Diktering och anteckningar tolererar längre pauser eftersom användare tänker mitt i meningen. Välj hellre längre timeouter och förlita dig på VAD.
- Kommando- och kontrollsystem samt transaktionsbaserade agenter gynnas av kortare timeouter tillsammans med manuell commit, eftersom talomgångarna är korta och tydliga.
- Flerspråkiga talare eller talare med ett annat modersmål pausar mer, så tillåt 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 taligenkänning kan göra mer än att producera ord. Men varje extra signal du begär påverkar latens och stabilitet. Tumregeln är att bara aktivera det som liveupplevelsen behöver och skjuta upp resten till en batchkörning.
Automatisk språkidentifiering låter Scribe v2 Realtime identifiera det talade språket bland de över 90 språk som stöds, i stället för att du måste ange det i förväg. Nackdelen är att modellen behöver ett kort ljudavsnitt för att avgöra språket med säkerhet, 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 specificering bort den tvetydigheten och ger oftast stabilare tidiga partiella resultat.
Talardiarisering tillskriver tal till olika talare och identifierar vem som sade vad. Vid batchtranskribering är detta jämförelsevis enkelt eftersom modellen ser hela filen. Vid strömning är det svårare: taligenkännaren måste tilldela en talaretikett utifrån enbart ljudet hittills, och en etikett som tilldelats tidigt ljud kan behöva revideras när mer av talarens röst har hörts. Behandla talaretiketter i strömmen på samma sätt som partiell text: som preliminära tills segmentet slutförs.
Timing på ordnivå 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 direkt, och 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 en förvånansvärt stor andel verkliga buggar uppstår ett lager längre ned, i hur du kodar och chunkar ljudet. Att välja rätt format och chunkstorlek är den billigaste möjliga förbättringen av latensen för tal till text.
PCM (linjärt, 16-bitars signerat, little-endian) är formatet att använda när du kontrollerar ljudfångsten. Högre samplingsfrekvenser ger mer akustisk detalj: 16 kHz är standardlägstanivån för taligenkänning och brukar räcka; 8 kHz har telefonkvalitet och saknar 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 finns där att återskapa.
Mu-law vid 8 kHz är telefoniformatet. Om du tar emot samtal från en leverantör som Twilio kommer ljudet som mu-law på 8 kHz, 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 artefakter från omsampling och ett onödigt konverteringssteg.
Chunkstorleken är den faktor som mest direkt formar den upplevda latensen. Du skickar ljud i chunkar, och taligenkä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. Som konkret riktmärke är en sekund ljud vid 16 kHz, mono och 16-bitars PCM 32 000 byte, så en chunk på 100 ms är ungefär 3 200 byte.
Fånga mikrofonindata i webbläsaren
I webbläsaren är rätt verktyg Web Audio API med en AudioWorklet. Workleten körs på tråden för ljudrendering, tar emot ljud i små ramar och påverkas inte av hack på 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 rörliga delar: en webbläsarklient som fångar mikrofonen och strömmar PCM till din server, en Node-server som vidarebefordrar ljud till Scribe v2 Realtime och transkript tillbaka, samt en skriptbar klient som strömmar PCM från en fil eller en telefonibrygga.
Servern vidarebefordrar i stället för att exponera taligenkännaren direkt för webbläsaren av en viktig anledning: din ElevenLabs API-nyckel är hemlig och får aldrig förekomma i klientkod. Servern har nyckeln. Om du behöver låta webbläsaren prata direkt med taligenkännaren skapar du en kortlivad token för engångsbruk på serversidan och ger klienten den i stället för API-nyckeln.
Webbläsarklient
Klienten öppnar en WebSocket till din server, fångar mikrofonen via workleten ovan och vidarebefordrar varje PCM-ram när den produceras. Inkommande händelser (som redan har normaliserats av servern till { type, text }) styr tillståndet för partiella/slutliga resultat från tidigare:
Servervidarebefordran
Servern öppnar en anslutning till taligenkännaren per klient, behåller API-nyckeln på servern, vidarebefordrar binär PCM direkt och normaliserar taligenkännarens händelser till det stabila formatet { type, text } som klienten använder:
Allt som är specifikt för slutpunkten ä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 riktmärket nedan fungerar samma anslutning till taligenkännaren utan webbläsare: läs PCM från valfri källa, skicka den i samma takt som realtids-chunkar och läs tillbaka händelser. API-nyckeln och URL:en kommer från miljön, precis som på servern.
Jämför latens för tal till text och ordfelsfrekvens
Både latens och ordfelsfrekvens varierar beroende på 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 kan inte generaliseras 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 siffrorna för latens och precision som betyder något är de du mäter på ditt eget ljud från infrastruktur som liknar produktionen. Här är en guide till att jämföra latens för tal till text.
Vad du ska mäta för latens i tal till text
Här är de viktigaste måtten du bör mäta när du jämför latens för tal till text i realtid:
- Tid till första partiella resultat: Från att den första ljudchunken skickas till att 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.
- Ordfelsfrekvens (WER): WER för det slutliga transkriptet jämfört med en mänsklig referens, beräknad på samma sätt i alla system.
- Stabilitetsförändringar: Hur många partiella resultat som skrivs om före slutförande. Måttet visar ungefär hur mycket användargränssnittet live kommer att se ut att förändras.
Kontroller
För att undvika opålitliga data bör du införa flera kontroller i experimentet för att hålla förhållandena konsekventa.
Här är de viktigaste kontrollerna att använda vid jämförelse av latens för tal till text:
- Identiskt ljud: Använd samma filer, samma samplingsfrekvens och samma kodning för varje system.
- Identisk takt: Strömma till varje system med samma takt för realtids-chunkar (till exempel chunkar på 100 ms).
- Upprepa och rapportera fördelningar: Kör varje fil många gånger under dagen; rapportera median och svansvärden (p50/p95).
- Identiska referenser och poängsättning: Normalisera text på samma sätt (versaler/gemener, interpunktion, 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 lika får du mer precisa mätvärden.
Testverktygets grundstruktur
Mätningens kärna tar en leverantörsadapter och registrerar tid till första partiella resultat, fördröjning vid slutförande och förändringar i partiella resultat:
Ordfelsfrekvens är ett standardmått baserat på Levenshtein-avstånd på tokennivå över normaliserad text. Konvertera till gemener och ta bort interpunktion på exakt samma sätt i både referens och hypotes innan du beräknar det, annars mäter du din normaliserare i stället för modellen. Kör måttet i en loop som kör varje fil omkring 10 gånger per leverantör och rapporterar median tid till första partiella resultat samt median-WER (p50/p95), eftersom ett enskilt prov domineras av nätverksvariation.
För att få det att köra behöver du tillhandahålla två saker. Först 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) samt sätter result.lastChunkSentAt när den sista ljudchunken skickas. Sedan 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 du kan reproducera.
Sammanfattning: så uppnår du tal till text i realtid
Vi har gått igenom många arkitektoniska förändringar i den här artikeln, så 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 tolerans för paketförlust och fångar ljud från konsumentenheter.
- Partiella och slutliga resultat: Behandla partiella resultat som preliminära och slutliga som bekräftade, och visa dem olika 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 efter interaktionen i stället för en konstant.
- Funktioner i strömmen: Aktivera bara funktioner i strömmen där liveupplevelsen behöver dem och skjut upp resten till en batchkörning med Scribe v2.
- Ljudformat: Fånga små PCM-ramar, skicka chunkar på ~100 ms och matcha källformatet för telefoni.
- Jämförelse: Ställ in avvägningarna mellan precision och latens empiriskt utifrån ditt eget ljud och mått du vill optimera.
- API-säkerhet: Behåll din API-nyckel på servern, eller skapa tokens för engångsbruk för direkta klientanslutningar.
Om du vill se hur du kan optimera latensen i en röstagent, har vi också skrivit en guide för det.
Bygg system för tal till text i realtid med Scribe v2 Realtime
Scribe v2 Realtime producerar partiella resultat med ungefär 150 ms modellatens. Om dina användare upplever den latensen eller något högre beror på arkitekturen runt omkring, och det är den delen du kontrollerar. Med strategierna i den här artikeln bygger du en bättre pipelinearkitektur som minskar latensen och förbättrar kundupplevelsen.
Om du vill fördjupa dig kan du läsa översikten över Speech to Text-funktioner, gå igenom vår modellreferens för hela listan över funktioner och språk, och 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 redan i dag.
Vanliga frågor om latens för tal till text i realtid
Tadas Petra är Developer Relations Engineer och hjälper utvecklare att bygga med ElevenLabs produkter. Han är också grundare av Hungrimind, en plattform för utvecklarutbildning. Tidigare var han Lead Developer Advocate på Agora och instruktör på Zero To Mastery.



