1 Punkte von GN⁺ 4 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • WebRTC priorisiert wie bei Konferenzgesprächen niedrige Latenz und verwirft bei schlechter Netzwerkqualität Audiopakete aggressiv, doch bei Voice AI kann beschädigter Sprach-Input die Antwortqualität stärker verschlechtern als eine langsamere Antwort
  • TTS kann Audio schneller als in Echtzeit erzeugen, sodass kurzes Netzwerkversagen durch Client-seitiges Puffern verborgen werden kann. WebRTC erfordert wegen Rendering nach Ankunftszeit und kleinem Jitter-Buffer jedoch künstliches Warten, damit Pakete rechtzeitig gesendet werden
  • WebRTC macht Verbindungsaufbau und Betrieb durch temporäre Ports, ICE, DTLS, SCTP usw. komplex, und bei Multiplexing über einen einzelnen Port ist es schwierig, STUN-, SRTP/SRTCP-, DTLS- und TURN-Pakete an die jeweilige Verbindung zu routen
  • Selbst wenn OpenAI einen schnellen Verbindungsaufbau verlangt, kann WebRTC durch die Kombination aus Signalisierung und Medienserver-Prozeduren mindestens 8 RTT benötigen, und wegen der P2P-Unterstützung ist derselbe Ablauf selbst dann nötig, wenn der Server eine feste IP hat
  • Als Alternativen werden WebSockets und QUIC/WebTransport genannt; QUIC unterstützt über CONNECTION_ID, QUIC-LB und preferred_address Single-Port-Betrieb, Adresswechsel, zustandsloses Load Balancing sowie die Kombination aus Anycast und Unicast auf einfachere Weise

Warum WebRTC nicht zu Voice AI passt

  • WebRTC wurde für schnelle Hin-und-zurück-Gespräche wie Konferenzanrufe entworfen und verwirft bei schlechter Netzqualität Audiopakete aggressiv, um die Latenz niedrig zu halten
  • Bei Voice AI ist es wichtiger, dass der Prompt korrekt übertragen wird, selbst wenn Nutzer etwas länger auf die Antwort warten müssen
    • Wenn zum Beispiel ein Sprach-Prompt wie „ob man zur Autowaschanlage laufen oder fahren soll“ beschädigt wird, kann sich auch die Qualität der nachfolgenden Antwort verschlechtern
  • Die WebRTC-Audioimplementierung im Browser setzt stark auf Echtzeitlatenz; bei Versuchen mit Discord war eine erneute Übertragung von WebRTC-Audiopaketen nicht möglich
    • In einem Update meinten einige WebRTC-Beteiligte zwar, dass sich Audio-NACK eventuell aktivieren lasse, doch bei Discord fand man keine korrekte Methode zur SDP-Manipulation, und die Einschränkung eines sehr kleinen WebRTC-Jitter-Buffers bleibt bestehen
  • Selbst wenn Voice-AI-Agenten irgendwann Gesprächslatenz erreichen, gibt es beim Senken der Latenz Trade-offs, und es ist unklar, ob es sinnvoll ist, Sprach-Prompts dafür absichtlich zu verschlechtern

Pufferprobleme bei TTS und WebRTC

  • Text-to-Speech (TTS) kann Audio schneller als in Echtzeit erzeugen
    • Wenn etwa eine GPU in 2 Sekunden Audio für 8 Sekunden erzeugt, könnte man idealerweise während dieser 2 Sekunden das Audio streamen, während der Client es 8 Sekunden lang abspielt und lokal Puffer aufbaut
    • So könnten kurze Netzwerkausfälle auftreten, ohne dass Nutzer sie bemerken
  • WebRTC passt nicht gut zu diesem Ansatz
    • WebRTC puffert nicht und rendert anhand der Ankunftszeit; Zeitstempel gelten dabei nicht als strenger Wiedergabemaßstab
    • Mit Video wird das Problem noch komplizierter
  • Dienste wie OpenAI müssen vor dem Senden jedes Audiopakets künstlich warten, damit es genau zu dem Zeitpunkt ankommt, an dem es abgespielt werden soll
    • Bei Netzüberlastung geht das betreffende Audiopaket verloren und wird nicht erneut übertragen
  • Im Ergebnis entsteht eine Struktur, in der erst künstliche Verzögerung eingefügt und dann für „niedrige Latenz“ aggressiv verworfen wird. Das ist ähnlich, als würde man ein YouTube-Video ohne Buffering per Bildschirmfreigabe zeigen
  • WebRTC nutzt für Audio einen dynamisch angepassten Jitter-Buffer von 20 ms bis 200 ms, um Netzwerk-Jitter abzufedern. Wenn aber schneller als in Echtzeit gesendet werden kann, sei das nicht nötig

Grenzen bei Ports und Verbindungsidentifikation

  • Ein TCP-Server öffnet normalerweise einen Port wie 443 und nimmt Verbindungen an; identifiziert werden sie über die Kombination aus Quell-/Ziel-IP und Port
    • Beispiel: 123.45.67.89:54321 -> 192.168.1.2:443
  • Wechselt ein Smartphone von WLAN auf Mobilfunk oder ändert NAT die Quell-IP bzw. den Quell-Port, bricht die TCP-Verbindung ab und muss neu aufgebaut werden
    • TCP- und TLS-Handshakes benötigen mindestens 2 bis 3 RTT, weshalb Nutzer bei Live-Streaming eine Netzunterbrechung spüren können
  • WebRTC setzt zur Lösung dieses Problems darauf, für jede Verbindung einen temporären Ziel-Port zuzuweisen
    • Wenn die Sitzung nur über Ziel-IP und Ziel-Port identifiziert wird, kann derselbe Nutzer auch dann erkannt werden, wenn sich Quell-IP und Quell-Port ändern
  • In Kombination mit der OpenAI-Architektur wird dieser Ansatz im großen Betrieb jedoch problematisch
    • Die Zahl nutzbarer Ports auf einem Server ist begrenzt
    • Firewalls blockieren temporäre Ports häufig
    • Auch zu Kubernetes passt das nicht gut

Warum WebRTC-Dienste zu Single-Port-Multiplexing übergehen

  • Viele Dienste folgen der WebRTC-Spezifikation nicht strikt, sondern multiplexen mehrere Verbindungen über einen einzelnen Port
  • Bei Twitch liefen WebRTC-Server auf UDP:443
    • Eigentlich ist 443 ein HTTPS-/QUIC-Port, doch so ließ sich mehr Firewalls passieren
    • Im internen Amazon-Netzwerk seien nur rund 30 Ports erlaubt gewesen
  • Discord nutzt je CPU-Kern einen Port aus 50000-50032
    • Dieser Ansatz kann in mehr internen Netzwerken blockiert werden
  • Das große Problem beim Single-Port-Multiplexing ist, dass WebRTC ein Verbund mehrerer Standards ist
    • Es gibt fünf Protokolle direkt über UDP. Zu erkennen, zu welchem Protokoll ein Paket gehört, ist nicht schwer, aber es ist schwierig, es an die richtige Verbindung zu routen
  • Routing-Probleme je Protokoll

    • STUN
      • Man kann ein eindeutiges ufrag wählen und danach routen
    • SRTP/SRTCP
      • Der Browser wählt einen beliebigen ssrc-Wert; meist kann darauf basierend geroutet werden
    • DTLS
      • Man muss mit breiter Unterstützung von RFC9146 rechnen
    • TURN
      • Es wird offengelegt, dass damit keine Implementierungserfahrung besteht
    • OpenAI erklärt, nur STUN zu parsen und anschließend DTLS, RTP und RTCP mithilfe gecachten Zustands undurchsichtig zu behandeln
    • Das lässt sich so lesen, dass erwartet wird, dass sich Quell-IP und Quell-Port des Nutzers nicht ändern
    • Browser könnten denselben ssrc-Wert zufällig identisch erzeugen
    • Bei Kollisionen und ohne Mapping von Quell-IP/Port identifiziert Discord Verbindungen offenbar, indem Pakete mit allen möglichen Entschlüsselungsschlüsseln entschlüsselt werden, bis der passende Schlüssel gefunden ist

Round-Trip-Latenz beim WebRTC-Verbindungsaufbau

  • OpenAI nennt als Anforderung einen „schnellen Verbindungsaufbau, damit Nutzer sofort nach Sitzungsbeginn sprechen können“, doch für den WebRTC-Verbindungsaufbau werden mindestens 8 RTT angesetzt
  • Beispiel für einen Signalisierungsserver

    • Bei einem Signalisierungsserver wie WHIP wären folgende Round-Trips nötig
      • 1 RTT für TCP
      • 1 RTT für TLS 1.3
      • 1 RTT für HTTP
  • Medienserver

    • 1 RTT für ICE
    • 2 RTT für DTLS 1.2
    • 2 RTT für SCTP
    • Manche Protokolle lassen sich per Pipelining um 0,5 RTT verkürzen, daher ist die exakte Rechnung komplex, insgesamt sind aber viele Round-Trips nötig
    • Diese Prozedur entsteht daraus, dass WebRTC P2P unterstützen muss; selbst wenn der Server eine feste IP hat, läuft derselbe Prozess ab
    • Wenn Signalisierungsserver und Medienserver auf demselben Host oder im selben Prozess laufen, finden doppelte und teure Handshakes zweimal statt

Eine Architektur, die praktisch zu einem WebRTC-Fork führt

  • Wegen vieler Einschränkungen führt WebRTC aus dieser Sicht faktisch zu einem Protokoll-Fork
  • WebRTC besteht aus rund 45 RFCs und De-facto-Standardentwürfen wie TWCC und REMB, was die Implementierung schwergewichtig macht
  • Browser-Implementierungen gehören Google und seien auf Google Meet ausgerichtet, was für Konferenz-Apps als existenzielle Bedrohung gesehen wird
  • Dass Konferenz-Apps außer Google Meet zur Installation nativer Apps drängen, wird ebenfalls als Versuch interpretiert, WebRTC zu vermeiden
  • Discord hat WebRTC im nativen Client stark geforkt und implementiert den Großteil von SDP, ICE, STUN, TURN, DTLS, SCTP und SRTP nicht, muss für den Web-Client aber weiterhin den kompletten Stack unterstützen
  • Auch wenn OpenAI ausreichend Mittel habe, sei es besser, WebRTC nicht zu forken, sondern durch einen anderen browserunterstützten Ansatz zu ersetzen

Alternativen: WebSockets und QUIC

  • Als Alternative zu WebRTC für Voice AI werden zunächst WebSockets genannt
    • Bestehende TCP-/HTTP-Infrastruktur kann weiterverwendet werden
    • Es ist kein eigener WebRTC-Load-Balancer nötig
    • Es passe gut zu Kubernetes und lasse sich skalieren
  • Head-of-line Blocking sei in diesem Kontext kein Nachteil, sondern möglicherweise die wünschenswertere Nutzererfahrung
    • Die Annahme ist, dass eine geordnete Übertragung besser ist, als wenn Teile eines Sprach-Prompts verloren gehen
  • Falls irgendwann der Punkt erreicht wird, an dem einzelne Pakete verworfen oder priorisiert werden müssen, sollte OpenAI laut diesem Argument auf WebTransport wie bei MoQ setzen
  • Der QUIC-Verbindungsaufbau ist mit QUIC+TLS 1 RTT möglich und damit einfacher als die vielen Handshakes bei WebRTC

Vorteile der QUIC Connection ID

  • QUIC verzichtet auf Routing anhand von Quell-IP und Quell-Port und trägt stattdessen in jedem Paket eine CONNECTION_ID
    • CONNECTION_ID kann 0 bis 20 Byte lang sein
    • Entscheidend ist, dass der Empfänger diesen Wert auswählt
  • Ein QUIC-Server kann für jede Verbindung eine eindeutige CONNECTION_ID erzeugen
    • So lässt sich bei Nutzung eines einzelnen Ports auch eine Verbindung identifizieren, deren Quell-IP oder Quell-Port sich geändert hat
    • Wenn sich die Quelladresse ändert, bricht QUIC die Verbindung nicht wie TCP ab, sondern wechselt automatisch auf die neue Adresse
  • Die Idee in RFC9146 wird hier als aus QUIC übernommen beschrieben

Zustandsloses Load Balancing

  • Der Load Balancer von OpenAI hängt wie viele andere Load Balancer von geteiltem Zustand ab
    • Es muss ein Mapping von Quell-IP/Port auf Backend-Server gespeichert werden
    • Da Load Balancer neu starten oder abstürzen können, wird dafür ein Speicher benötigt
  • OpenAI verwendet eine Redis-Instanz, um das Mapping von Quell-IP/Port zu Backend-Servern zu speichern
    • Das wird als einfach und unkompliziert bewertet
  • QUIC-LB bietet ohne Datenbank einen einfacheren Ansatz
    • Wenn der Client eine QUIC-Verbindung aufbaut, leitet der Load Balancer die Pakete an einen regulären Backend-Server weiter
    • Beim Abschluss des Handshakes kodiert der Backend-Server seine eigene ID in die CONNECTION_ID
    • Danach enthalten alle QUIC-Pakete die ID des Backend-Servers
  • Der Load Balancer muss dann ohne Verschlüsselungsschlüssel oder Routing-Tabelle nur die ersten Bytes dekodieren und an den passenden Server weiterleiten
    • Selbst wenn der Server neu startet, kann dieses Verfahren bestehen bleiben
  • Zustandslos bedeutet auch: kein globaler Zustand
    • Der Load Balancer kann an einer globalen Anycast-Adresse empfangen und global an den markierten Backend-Server weiterleiten
    • Cloudflare nutze das umfassend
  • AWS NLB bietet QUIC-Load-Balancing mit QUIC-LB an

Kombination aus Anycast und Unicast

  • Aus Sicht von OpenAI scheint die Architektur Verbindungen regionalen Load Balancern zuzuweisen; funktional arbeitet das, doch Anycast wird als besserer Ansatz dargestellt
  • preferred_address in QUIC wird als wichtige Funktion für Load Balancing bewertet
  • Funktionsweise

    • Mehrere Backend-Server weltweit announcen dieselbe Anycast-Adresse 1.2.3.4
    • Wenn ein Client eine Verbindung zu 1.2.3.4 aufbaut, leiten Internet-Router die Pakete an einen dieser Server weiter
    • Jeder QUIC-Server kann zusätzlich eine eigene Unicast-Adresse wie 5.6.7.8 haben
    • Anycast wird für den Handshake verwendet, zustandsbehaftete Verbindungen bleiben auf Unicast
  • Beispielablauf

    • Der Server empfängt QUIC-Pakete auf 1.2.3.4 und 5.6.7.8
    • Der Client sendet QUIC-Handshake-Pakete an 1.2.3.4
    • Der Server erstellt eine QUIC-Verbindung und kündigt preferred_address=5.6.7.8 an
    • Danach sendet der Client weitere Pakete an 5.6.7.8
    • Ist der Server überlastet und möchte keine neuen Verbindungen mehr annehmen, kann er die Ankündigung von 1.2.3.4 einstellen
    • Bestehende Verbindungen bleiben bestehen, da sie auf Unicast laufen
    • Die Anycast-Adresse wirkt damit praktisch wie ein Health Check
    • In dieser Struktur sei kein separater Load Balancer nötig

Grenzen und Fazit

  • Es wird anerkannt, dass die OpenAI-Ingenieure sehr stark sind und unter Druck stehen, sofort großflächig zu skalieren
  • Trotzdem wird argumentiert, dass WebRTC für Voice AI zwar naheliegend wirkt, aber weder beim Product-Fit noch bei der Skalierung gut passt
  • Auch MoQ passt nicht perfekt zu Voice AI
    • Bei 1:1-Audio sind viele Aspekte von Caching und Fanout-Semantik wenig nützlich
    • Dennoch lautet das Fazit, dass QUIC verwendet werden sollte

1 Kommentare

 
GN⁺ 4 시간 전
Hacker-News-Kommentare
  • Ich habe den Beitrag nicht ganz zu Ende gelesen, aber ich glaube, der Autor versteht den Zweck von WebRTC im Kern schon. Dass er sich als Experte bezeichnet und bei mehreren Firmen SFUs in Go/Rust gebaut hat, mag stimmen, aber der technische Lebenslauf garantiert nicht automatisch, dass die Schlussfolgerung richtig ist.
    Vielleicht habe ich es falsch verstanden, aber es wirkt so, als würde er STUN und DTLS beim Thema Round-Trip-Zeit als miteinander verknüpfte kumulative Faktoren behandeln, obwohl das in Wirklichkeit ziemlich orthogonale Elemente sind. Außerdem verliert er für mich den roten Faden, weil er zu viel Zeit auf die Aussage verwendet, dass keine Paket-Neuübertragung stattfindet, und wiederholt, wie viel Mühe Discord hineingesteckt habe.
    Das RTC in WebRTC steht für Echtzeitkommunikation, und Menschen mögen manchmal verlorene Audiopakete lieber als verzögertes Audio oder Audio mit stark schwankender Geschwindigkeit. Hier geht es um menschliche Sprache.
    Wenn man Paketverlust nicht in Kauf nehmen will, kann man statt UDP ein TCP-basiertes Protokoll verwenden. Aber wenn man Sprache über TCP durch ein schlechtes Netzwerk schickt, bleibt der Empfänger stehen, während er auf das nächste korrekte Paket wartet. Wenn die Pakete nach einigen Sekunden Verzögerung wieder eintreffen, muss man entscheiden, ob man das aufgelaufene Audio mit normaler Geschwindigkeit abspielt oder beschleunigt, um andere Kanäle einzuholen — und die meisten Menschen mögen diese Erfahrung nicht.
    Wenn man WebRTC kurz vergisst und nur TCP und UDP für Sprache betrachtet, dann gibt es einen Grund dafür, dass VoIP seit den 90ern auf UDP basiert.

  • Um zuerst auf den technischen Teil zu antworten: Ich denke schon, dass es eine Zukunft ohne WebRTC gibt. Ich weiß nur nicht, ob diese Richtung mit dem übereinstimmt, wohin WebTransport+WebCodecs und Ähnliches gehen.
    Die Aussage, Nutzer würden lieber 200 ms länger warten, damit ein langsamer/teurer Prompt genauer wird, ist das genaue Gegenteil des Feedbacks, das ich bekomme. Nutzer wollen sofortige Antworten. Wenn es Verzögerung bei der Antworterzeugung oder beim Unterbrechen gibt, verschwindet das magische Gefühl. Sie wollen außerdem nicht schneller als in Echtzeit senden. Wenn der Nutzer das Modell mitten im Satz unterbricht, verschwendet man Bandbreite, indem man ein 3-Minuten-Audio sendet, von dem nur 10 Sekunden abgespielt wurden.
    Zur Behauptung, TTS sei schneller als Echtzeit: Moderne/zielgerichtete Voice-AI entfernt sich von dem Ansatz, den der Autor beschreibt: https://research.nvidia.com/labs/adlr/personaplex/ — man arbeitet eher mit Ein- und Ausgabe in kleinen 20-ms-Stücken.
    Der Punkt, dass man möchte, dass sich die ursprüngliche IP/Port-Kombination des Nutzers nicht ändert, wird unterstützt. Wenn zu einem ufrag eine neue IP hereinkommt, kann das verarbeitet werden.
    Auch die Aussage, dass mindestens 8 Round-Trips nötig seien, ist falsch: https://datatracker.ietf.org/doc/draft-hancke-webrtc-sped/
    Die Entscheidung, Audio über WebSocket zu streamen, verliert Funktionen wie AEC und schiebt die Komplexität auf den Client. Gerade die Einfachheit von WebRTC, also der Ablauf createOffer -> setRemoteDescription, macht den Einstieg für viele leicht. Mit Realtime API + WebSocket hatten viele Entwickler Probleme, weil viel mehr Code nötig war und sie vieles selbst behandeln mussten.
    Wenn ich persönlich wählen dürfte, würde ich das Offer/Answer-Modell beibehalten, aber statt DTLS+SCTP QUIC verwenden. Vielleicht könnte man RTP auch über QUIC machen. Ich habe keine starke Präferenz für das Protokoll selbst, aber ich weiß nicht gut, wie man bei einem viel größeren Code-Footprint den Code an mehrere Clients und kundenseitige Clients ausliefert.

    • Natürlich wollen Nutzer geringe Latenz, aber sie wollen auch, dass das LLM weniger falsch versteht. Es wäre schön, den Trade-off zwischen Latenz und Qualität per A/B-Test fahren zu können, aber WebRTC macht diesen Regler schwer bedienbar.
      Ich bin kein TTS-Experte, aber ich sehe nicht, was der Vorteil daran sein soll, Ergebnisse Stück für Stück herauszuschieben. Silizium kümmert sich nicht darum, wie schnell eine Zeitzahl ansteigt.
      Es gibt Fälle, in denen der Client von seiner eigenen IP-Änderung weiß und ICE neu aushandeln kann, aber oft weiß er es nicht, und normalerweise erwartet man, dass der Server die Änderung erkennt. In der aktuellen Load-Balancer-Konfiguration ist das jedoch unmöglich. Kein großes Problem, aber schade, wenn man ohnehin schon viele Hürden hat.
      Wenn der Entwurf bedeutet, dass es nicht 8 RTT, sondern 7 RTT sind, dann könnte die tatsächliche Zahl niedriger sein, weil sich manches pipelinen lässt. Das eigentliche Problem ist aber, dass es allein deshalb, weil eventuell P2P verwendet werden könnte, einen verpflichtenden Signaling-Server und doppelte TLS-Handshakes gibt.
      WebRTC ist für neue Entwickler leicht, weil es eine Blackbox-Meeting-App ist. Aber bei einem großen Unternehmen wie OpenAI beginnt diese Blackbox Probleme zu erzeugen, die sich mit primitiveren Low-Level-Funktionen beheben ließen.
      RTP over QUIC würde ich wirklich gern einmal ausprobieren und wäre auch bereit zu helfen. Wenn Codegröße die Sorge ist: Browser und irgendwann auch Betriebssysteme liefern QUIC-Bibliotheken. Wenn man sich mehr in Richtung MoQ bewegt, kümmert sich QUIC um Fragmentierung, Neuübertragung, Congestion Control usw., und die Anwendung wird überraschend klein.
      Die große Einschränkung von RoQ/MoQ ist, dass QUIC auch für Datagramme Congestion Control macht, sodass man GCC nicht implementieren kann. Beim Senden aus dem Browser ist man daher erst einmal an cubic/BBR gebunden.
    • Ich bezweifle stark, dass ihr wirklich das Feedback bekommt, Nutzer würden eine sofortige falsche Antwort einer um 200 ms verzögerten richtigen Antwort vorziehen.
    • Man muss weder in 3 Minuten noch in 20-ms-Stücken senden — etwa 1 Sekunde pro Chunk reicht. 20 ms auf einmal zu senden ist ebenso dumm wie 10 Minuten am Stück.
    • WebRTC ist selbst dann komplex, wenn es als in den Browser eingebaute Bibliothek vorliegt. Für Client/Server-Sprachinteraktion sehe ich keinen zwingenden Grund dafür. Man kann Sprachsamples anders übertragen und sich für die Wiedergabe nur Teile der Jitter-Buffer-Logik ausleihen.
      Ich arbeite gerade an Sprach-/Videokonferenzen und 1:1-Anrufen, und die Komplexität von WebRTC ist enorm. Es hat geholfen, das Produkt schnell zu starten, aber wenn man merkwürdige Dinge tun will, ist es schwer zu reparieren — selbst mit einem Fork für den Client.
      Über TURN könnte ich eine lange Beschwerde schreiben. Eigentlich wirkt das ganze WebRTC-Protokollbündel so, als wäre es für ein Internet entworfen worden, das es gar nicht gibt.
      TURN sollte dem Client bei der Allokationsanfrage keine temporären Ports, sondern eine Rendezvous-ID zuweisen. Dann könnte der Peer den TURN-Server über einen Service-Port kontaktieren und eine Verbindung zu dieser Rendezvous-ID anfordern, und der Client müsste weder die Peer-Adresse kennen noch Permissions hinzufügen. Das würde die Zahl der Kommunikationen reduzieren, die überhaupt eine Ende-zu-Ende-Relay-Verbindung brauchen. Fortgeschrittene Cluster könnten Informationen in die ID kodieren, sodass Client und Peer jeweils einen nahen TURN-Server kontaktieren und die Server sich untereinander verbinden. Weniger fortgeschrittene Cluster müssten mit der ID die TURN-Server-IP und den Service-Port teilen.
    • Die Übertragung des ersten Phonems und die Übertragung wichtiger Informationen müssen nicht gekoppelt sein. Politiker im Fernsehen sind in diesem Trick sehr gut und haben eine ganze Sammlung von Floskeln, mit denen sie Zeit füllen, bis ihr Gehirn richtig angelaufen ist. Wir müssen nur die Lücken füllen, damit unser System 1 das Vertrauen in die Interaktion nicht verliert.
  • Die Stelle, an der gefragt wird, warum man überhaupt wissen müsse, welche echten Zeitpunkte den angezeigten Timestamps entsprechen, hat mich hart getroffen. Es wirkt, als hätte niemand, der WebRTC gebaut hat, je Datenströme aus unterschiedlichen Quellen mit Millisekunden-Genauigkeit synchronisiert.
    Ich habe im Browser eine Demo für Videostabilisierung mit Webcam und IMU-Modul gebaut, und die Latenz des Pfads video->rtc->browser und des Pfads sensor->websocket->browser war stark unterschiedlich und nicht konstant. Die naheliegende Lösung wäre gewesen, die Sensordaten mit UTC-Timestamps zu senden und im Browser zu synchronisieren, aber beim Video gab es keinen UTC-Zeitbezug, also war das unmöglich.
    Wenn man beide Enden der WebRTC-Pipe kontrolliert, kann man lustige Dinge tun wie beim Stream-Start den UTC-Timestamp mitzuschicken, aber das Browser-Jitter löst man damit nicht. Für einen Proof of Concept funktionierte es gut genug, aber die Gesamtlösung musste neu entworfen werden.

  • Ich habe in diesem Bereich viel Erfahrung und auch einige Patente angemeldet. Bei Alexa stellte das Gerät eine Verbindung zum Server her und hielt sie offen; wenn das Wake Word erkannt wurde, schickte es darüber im Grunde etwas, das HTTP2/SPDY ähnelte. Dadurch konnte man schon mit der STT-Verarbeitung beginnen, bevor der Nutzer zu Ende gesprochen hatte, und es blieb nur noch die Verzögerung der letzten paar Fragmente.
    Die Antwort kam über dieselbe Verbindung zurück.
    Im Fall von OpenAI ist es schwieriger, wie bei Alexa dauerhaft eine Verbindung offen zu halten, aber wenn man auf dem Smartphone HTTP2 verwendet, verwalten iOS und Android diese Verbindung fast von selbst.
    Der Autor hat recht. Ein Echtzeitprotokoll ist nicht zwingend nötig; wichtiger ist, alle Daten zu bekommen. Nutzer bemerken Latenz kaum, solange sie nicht über 500 ms liegt. Gerade im mobilen Zeitalter sind die meisten Menschen daran gewöhnt, dass selbst Echtzeitkommunikation zwischen Menschen Verzögerung hat.
    Wenn ich bei OpenAI oder Anthropic arbeiten würde, könnt ihr mich gern kontaktieren. Ich kann mehr dazu erzählen.

    • Mir scheint, ihr fokussiert euch zu stark auf die Übertragungslatenz und vergesst dabei, dass die LLM-Pipeline selbst nicht sofort fertig ist.
      Die Transportlatenz kommt nur noch obendrauf zu all den anderen bereits großen Verzögerungen.
      Deshalb denke ich, dass man die Lösung mit der geringstmöglichen Latenz gewählt hat, um die Ende-zu-Ende-Latenz der gesamten Pipeline zu reduzieren.
      Die Analogie zu Sprachlatenz zwischen Menschen passt nicht, weil man in diesem Fall den Menschen so behandelt, als hätte er keine Verzögerung.
    • Wenn man ungefähr 6.000 Sprachgespräche pro Tag mit einer Architektur aus WebRTC plus kaskadiertem STT/LLM/TTS verarbeitet, dann deckt sich die Behauptung, 500 ms seien eine vom Nutzer nicht wahrnehmbare Verzögerung, nicht mit meiner Erfahrung.
      500 ms sind bei heutigen hochmodernen Sprachimplementierungen eher der Bodenwert, wenn man Glück hat, kein Geld spart und sogar teure Techniken wie speculative decoding und reasoning einsetzt. Allein der LLM-Schritt dauert 450 ms. In kommerzieller Voice AI zählt jede Millisekunde, und schon 200–300 ms zusätzlich verschlechtern die Gesprächsqualität stark.
      Unser Geschäft dreht sich hauptsächlich um Sprache für nichttechnische Nutzer. Als die Verzögerung zwischen Gesprächszügen letztes Jahr bei 1200–1500 ms lag, gab es viel Nutzerverwirrung, Unterbrechungen, Gesprächsabbrüche und insgesamt eine unangenehme Erfahrung. Jetzt liegen wir je nach nötiger Tool-Nutzung bei etwa 700 ms und kommen einer brauchbaren Erfahrung näher, die mit echter menschlicher Interaktion vergleichbar ist. Um hier weitere 100 ms herauszuholen, geben wir ziemlich viel Geld aus.
      Wir machen sogar teure und verschwenderische Dinge wie speculative LLM passes und speculative tool execution. Während der Nutzer spricht, lassen wir mehrere LLM-Inferenzläufe laufen, führen aber keine nicht-idempotenten Tool-Aufrufe tatsächlich aus, bis wir wissen, dass der Durchlauf brauchbar ist und der Nutzer am Satzende nichts Entscheidendes mehr sagt — so sparen wir 100–200 ms. Zu sagen, 500 ms seien irrelevant, klingt für mich nach einem anderen Anwendungsfall als Sprachinteraktion Mensch-zu-AI.
      Die wirklich schwierigen Probleme in Voice AI sind nicht gelegentlich verlorene WebRTC-Pakete, sondern starker Hintergrundlärm, Echo und Akzente. Die ausgereifte AEC-Implementierung von WebRTC hilft zumindest beim Echo ziemlich gut. Ich verstehe, dass es auf OpenAI-Größe ein extrem lästiges Protokoll ist, aber für Anwendungen, die nicht hyperskalig sind, gibt es mit kommerziellen Anbietern wie Daily viele brauchbare Lösungen. Das eigentliche Problem liegt woanders. Wenn ich meinem Latenzbudget aber 500 ms hinzufüge, ist die Anwendung tot.
  • Leider gibt es kaum ein Protokoll, das man so ungern implementiert wie WebRTC. Schon um einen simplen Client zu starten, muss man sich schnell in SDP, TURN/STUN, ICE candidates, offer, P2P-Protokolle und jedes Mal wieder in einen komplexen Handshake einarbeiten, den man praktisch von null umsetzt.
    Sich diesen Trenchcoat aus Protokollschichten und unbeabsichtigten „Best Practices“ komplett neu anzuziehen, kann ich mir kaum vorstellen.

    • Ich frage mich, ob du schon einmal mit der Microsoft Graph API E-Mails verarbeitet hast.
    • Erst durch das Aufkommen von LLMs konnte ich überhaupt zum ersten Mal eine funktionierende WebRTC-datachannel-Konfiguration mit aiortc bauen. Vorher war das praktisch völlig unmöglich. Niemand wusste, was genau man wie tun muss, und es gab keine Beispiele. Ein wirklich schreckliches Protokoll, das verschwinden sollte.
    • Deshalb mag ich LiveKit, und der CEO ist auch in Ordnung.
    • Ich frage mich, für welche Plattform du entwickelt hast, dass es so schmerzhaft war. Schade, dass es so frustrierend war.
      Hoffentlich ist es mit mehr Lehrmaterial und Bibliotheken besser geworden. Erstaunlich ist auch, dass Tools wie Codex solche Dinge inzwischen ziemlich gut vorantreiben.
  • Bei der Stabilität von Browser-APIs insgesamt gibt es viele undokumentierte Randfälle, das ist nicht nur ein WebRTC-Problem.

  • Das ist ein frustrierend einseitiger Beitrag. WebRTC hat zwar Grenzen, aber wenn man sich auf den Standard stützt, gewinnt man viel Korrektheit und senkt langfristig die Engineering-Kosten. Dass WebRTC komplex ist, heißt nicht, dass es falsch ist — es heißt, dass Echtzeitmedien im öffentlichen Internet komplex sind.
    Netzwerke sind ihrem Wesen nach zustandsbehaftet. NAT traversal, Jitter-Buffer, Congestion Control, Paketverlust, Codec-Zustand, Verschlüsselung und Session-Routing verschwinden nicht einfach, nur weil man Audio über TCP oder WebSocket legt. So zu tun, als wäre das anders, ist keine architektonische Klarheit, sondern nur das Verschieben der Komplexität an eine weniger sichtbare Stelle.

    • Der Autor hat gleich zu Beginn seine eigene Vorgeschichte beschrieben. Vor 6 Jahren hat er bei Twitch eine WebRTC-SFU gebaut und zunächst wie OpenAI Pion (Go) verwendet, dann aber wegen zu schwacher Benchmarks geforkt und schließlich alle Protokolle neu geschrieben.
      Vor einem Jahr hat er bei Discord erneut eine WebRTC-SFU in Rust geschrieben; man erkennt also ein wiederkehrendes Muster.
      WebRTC besteht aus ungefähr 45 RFCs, die bis in die frühen 2000er zurückreichen, plus faktischen Standards, die technisch gesehen nur Entwürfe sind, wie TWCC oder REMB. Wenn man das alles implementieren muss, macht es überhaupt keinen Spaß.
      Er kann sich mit gutem Recht als ausgewiesenen WebRTC-Experten bezeichnen, und genau deshalb sagt er, dass er nie wieder WebRTC verwenden will.
      Er hat es auf konventionelle Weise gründlich genug versucht, um sich ein Urteil in die Gegenrichtung leisten zu können, würde ich sagen.
    • Gerade die Einseitigkeit wirkte erfrischend wie ein von einem Menschen geschriebener Text statt wie die heute überall herumliegenden KI-Aufzählungen nach dem Muster „beide Seiten haben recht“.
      Ich habe keine feste Position zum Thema selbst, aber der Text hatte eindeutig etwas Menschliches, und das mochte ich.
      Wenn das von KI geschrieben war, dann wäre das wirklich schlimm.
    • „Wie schwer kann es schon sein?“, fragte die Vogelscheuche.
      Es ist 2026 und Remote-Meetings sind immer noch ein Chaos. Da steckt Milliardenbudget dahinter, und selbst Zoom ist bestenfalls mittelmäßig und manchmal so schlecht wie dieses Ding von Microsoft. Ich habe noch nie erlebt, dass Remote-Meetings nicht holprig und chaotisch waren.
    • QUIC ist auch ein Standard.
  • Großartiger Beitrag. Ich wünschte, man könnte Blogposts auszeichnen, wenn der Autor auf dem Gebiet ein echter Experte ist.

  • Zur Aussage „WebRTC wurde dafür entworfen, meine Prompts in schlechten Netzwerken zu degradieren und zu verwerfen“: Wenn man Echtzeit will, muss man das in Kauf nehmen. Wenn man keine Echtzeit will und alles als STT -> Prompt -> TTS denkt, muss man Audio vielleicht von vornherein gar nicht über das Netzwerk schicken.

    • Hier der Autor. Bitte entschuldigt, dass meine Antworten in den Kommentaren nicht ganz so unterhaltsam sind wie der eigentliche Beitrag.
      Jede Low-Latency-Anwendung muss einen UX-Trade-off zwischen Qualität und Latenz festlegen. Congestion erzeugt Queuing, also Verzögerung, und um das zu vermeiden, muss man etwas überspringen, was die Qualität senkt.
      Bei WebRTC ist der Regler für Latenz versus Qualität fest verdrahtet. Für minimale Latenz ist das großartig, aber es fehlt an Flexibilität. Wegen der Browser-Unterstützung ist WebRTC trotzdem weiterhin eine der wenigen realistischen Optionen, deshalb werde ich es wohl weiter nutzen.
      Aber jetzt gibt es WebTransport. Damit kann man als General-Purpose-Protokoll ein Verhalten bauen, das WebRTC ähnelt. Die Anwendung kann selbst entscheiden, wie lange sie wartet, bevor Streams gedroppt oder zurückgesetzt werden, statt dass diese Entscheidung für sie getroffen wird.
      Der Kernpunkt des Beitrags ist, dass Nutzer Streaming meist wollen, Drops aber nicht. Audio-Ein- und -Ausgabe-Streaming ist natürlich auch ohne WebRTC möglich. Die Anwendung sollte selbst festlegen können, wann ein Audiopaket endgültig verloren ist — nach 50 ms, 500 ms oder 5000 ms. Die Aussage ist, dass Voice AI nicht die 50-ms-Option wählen sollte.
    • Ist der Kern nicht, dass der Anwendungsfall von OpenAI eigentlich keine Echtzeit verlangt?
      Wenn OpenAI antwortet, hat es den Großteil des Audios schon, bevor der Nutzer es hören muss. Es erzeugt Audio also schneller als in Echtzeit, weshalb ein Echtzeitprotokoll dafür die falsche Wahl ist.
    • Vielleicht habe ich zusätzliche Einstellungen zur Latenzreduktion übersehen, aber Clients scheinen die Latenz von STT -> Prompt -> TTS nicht in Kauf nehmen zu wollen. Wenn sich das Gespräch „echt“ anfühlt, nehmen sie gelegentliche Qualitätsprobleme offenbar gern in Kauf.
  • Wir betreiben die Gemini Live API auf einem verwalteten WebRTC-Cloud-Mesh, und es funktioniert sehr gut, seit 2 Jahren im Produktivbetrieb. Man kann natürlich WebSocket probieren und Dinge wie ephemere Schlüssel selbst handhaben, aber wenn man mit Leuten spricht, die in diesem Bereich Voice Agents in großem Maßstab betreiben, merkt man, dass mit WebRTC und Pipecat sowie mit den vielen Ressourcen, die in bereits gelöste Probleme geflossen sind, schon ziemlich viel abgedeckt ist.
    Es fühlt sich definitiv überdimensioniert an und ist es vielleicht auch tatsächlich, aber sobald die Verbindung steht, wirkt es ziemlich magisch. Auch Startzeit und Buffering sind für schnellere Sprachverbindungen bereits gelöst: https://github.com/pipecat-ai/pipecat-examples/tree/main/ins... Video ist noch schwieriger.