Ugrás a tartalomhoz
← Vissza a Naplóhoz

Realtime voice agent — amit egy 280 ms-os latency-budget tanított nekünk

WebRTC, OpenAI Realtime API, ElevenLabs fallback, és egy magyar nagyi, aki belebeszélt a botba. Hogyan tartottuk az end-to-end latency-t 300 ms alatt.

A voice agent nem akkor jó, ha gyorsan válaszol. Akkor jó, ha bármikor félbe lehet szakítani — és nem zavarodik össze.

Amikor 2026 márciusában elindítottuk a Nortinia Voice-t a 16 weboldalon, az első prod-incidensünk egy nagymama volt. Bejött az oldalra, megnyomta a mikrofon-gombot, és azt mondta: "Halló, halló, halló kedves, nem akarom én ezt, csak…". A bot szépen megvárta, amíg befejezi, és válaszolt 2.8 másodperc múlva — addigra a nagymama már letette. A barge-in handling, a latency-budget és a kapcsolat-csere-stratégia ekkor lett a hetünk fő témája, és most leírom, mit tanultunk 8 hét gyártás alatt.

A latency-budget per leg

A célunk egy 300 ms-os end-to-end first-token-latency volt, mert ezen a határon a beszélgetés "élővé" válik. Ezt kellett szétosztanunk a hálózati hopok között. A budget így néz ki éles üzemben.

  • Mikrofon → böngésző capture: 8–12 ms (Opus encoder, 20 ms frame)
  • Böngésző → OpenAI Realtime WebRTC: 35–80 ms (EU-régió, sticky session)
  • OpenAI VAD + first token: 120–180 ms (gpt-4o-realtime-preview)
  • TTS first chunk → böngésző: 25–45 ms (server-side streaming)
  • Böngésző → hangszóró: 8–15 ms (AudioWorklet, jitter buffer 40 ms)

Fallback: ElevenLabs, amikor az OpenAI elesik

A live OpenAI Realtime API havi 1-2 alkalommal 5-15 percre kiesik EU-régióban. Mi ezt nem szerettük volna a felhasználóknak megmutatni, ezért egy mint-time provider failover logikát építettünk az engine VoiceSessionMintService-be: a session-token kiosztásakor a backend végigmegy egy tenant-priority listán (OpenAI → ElevenLabs → WebSpeech), és circuit-breaker-rel kihagyja azt, amelyik az utolsó 60 másodpercben hibázott. A panel oldali kód már discriminated union-nal kezeli a `session.kind`-ot, így a frontend változatlan maradt. Az ElevenLabs latency-je ~420 ms, ami érezhetően lassabb, de "működik" és "nem működik" között ez a különbség.

Barge-in: a legnehezebb mérnöki probléma

A felhasználó beszélni akar, amikor a bot beszél. Ez egyszerűen hangzik, de három alrendszer kell hozzá: szerver-oldali VAD, ami az input-stream-en érzékeli a beszédet (OpenAI Realtime ezt natívan adja); kliens-oldali audio-cancellation, hogy a bot saját hangja ne triggerelje a VAD-ot (AEC az AudioWorklet-ben); és egy clean abort-szignál, ami megszakítja a folyamatban lévő `response.create`-et és törli a TTS-queue-t. A 2.97.43-as panel-verziónktól ez 110 ms alatt működik — és pont ezért tud a nagymama is félbeszakítani.

A latency 0 ms-tól 300 ms-ig egy mérnöki probléma. 300-tól 1000 ms-ig egy UX-probléma. 1000 felett egy üzleti probléma.
Norbert Kubinyi

Kiemelten érdekel egy téma?

Írj nekünk, és ha van tapasztalatunk benne, publikáljuk.