Der Aufbau von Audio-Pipelines mit extrem niedriger Latenz mithilfe der neuen OpenAI Realtime API ermöglicht es Entwicklern, menschenähnliche, konversationelle Sprachagenten (Voice Agents) in der Produktion einzusetzen. Traditionell bedeutete der Aufbau einer Sprachschnittstelle die Verkettung von drei separaten Modellschichten: automatische Spracherkennung (ASR), eine textbasierte LLM-Logikschicht und Text-to-Speech-Synthese (TTS). Diese mehrstufige Pipeline verursachte erhebliche Verzögerungen bei der Netzwerkübertragung, was eine natürliche Konversation unmöglich machte. Die native Audioverarbeitung über eine permanente WebSocket-Verbindung ändert dies und senkt die Netzwerklatenz auf unter 300 Millisekunden. Dieser Leitfaden erklärt, wie Sie Verbindungszustände herstellen, rohe Audio-Puffer streamen und Session-Konfigurationen optimieren.
[!IMPORTANT] API-Sicherheitswarnung: Exponieren Sie Ihren OpenAI-API-Schlüssel niemals direkt in clientseitigen Browser-Skripten. Leiten Sie die WebSocket-Verbindung immer über eine sichere Edge-Middleware (wie einen Cloudflare Worker) um, die die Autorisierungs-Header anhängt, bevor sie Pakete an OpenAI weiterleitet.
Wichtige Erkenntnisse:
- WebSocket-Verbindung: Verbinden Sie sich über Edge-Proxys direkt mit dem Realtime-WebSocket-Gateway von OpenAI.
- Native Modalitäten: Geben Sie in Ihrem anfänglichen Session-Update-Konfigurations-Payload sowohl
textals auchaudioan.- Audio-Format: Streamen Sie die Sprache des Benutzers als Base64-codierte Mono-PCM16-Chunks mit 24 kHz.
- Sprachunterbrechung: Überwachen Sie die
speech-started-Signale des Servers, um die clientseitige Wiedergabe sofort zu stoppen.
Die Architektur nativer Audio-LLMs
Traditionelle Sprach-Stacks behandeln sowohl Spracherkennungs- als auch Synthesemodelle als externe Hüllen um ein zentrales Textmodell. Native Audiomodelle eliminieren diesen Overhead, indem sie Sprache direkt verarbeiten.
Mit den Realtime-Modellen von OpenAI verarbeitet das Netzwerk Audioeingaben und -ausgaben nativ. Das Modell empfängt rohe Audiowellenformen, analysiert Tonfall, Modulation sowie Inhalt und generiert direkt eine natürliche Sprachausgabe. Dadurch eliminiert die Pipeline ASR-Transkriptionsfehler und TTS-Syntheseengpässe.
Die Verwaltung dieser permanenten Verbindung basiert auf WebSockets. Die Verbindung bleibt während des gesamten Gesprächs geöffnet, sodass der Agent seine Ausgabe unterbrechen kann, sobald er Benutzersprache erkennt – wodurch das Erlebnis einem echten Telefonat gleicht.
Holen Sie sich KI-IntegrationsdiensteVoraussetzungen
Stellen Sie vor dem Schreiben von Code sicher, dass Ihre Umgebung bereit ist. Dieses Tutorial setzt voraus, dass Sie mit asynchronem JavaScript vertraut sind und Folgendes eingerichtet haben:
- Ein OpenAI-Konto mit Realtime-Zugriff und einem aufgeladenen, aktiven API-Schlüssel.
- Node.js 20 oder neuer oder ein Cloudflare Workers-Projekt, das mit
npm create cloudflare@latesterstellt wurde. - Ein WebSocket-Client – das
ws-Paket für ein Node.js-Gateway oder das native globaleWebSocket, das in Workers verfügbar ist. - Ein Browser-Frontend, das Mikrofon-Audio über die Web Audio API aufzeichnen kann (
getUserMediaplus einAudioWorkletfür das Resampling). - Grundkenntnisse über Base64 und PCM-Audio, da jeder gesendete oder empfangene Frame ein Base64-codierter PCM16-Payload ist.
Planen Sie etwas Zeit für die Kontoeinrichtung ein: Realtime-Zugriff und Abrechnung müssen in Ihrer Organisation aktiviert sein, bevor das Gateway eine Session akzeptiert.
Herstellen von WebSocket-Verbindungen
Zuerst öffnen Sie eine Verbindung zum OpenAI Realtime-Gateway und geben das GPT-realtime-Modell in Ihren Headern an.
Der folgende JavaScript-Code zeigt, wie Sie die Verbindung initialisieren, Session-Modalitäten konfigurieren und ein- sowie ausgehende Streaming-Audio-Puffer verarbeiten:
1import WebSocket from "ws";
2
3export async function startVoiceAgent(env) {
4 // Connect to the OpenAI Realtime WebSocket gateway
5 const url = "wss://api.openai.com/v1/realtime?model=gpt-realtime";
6 const ws = new WebSocket(url, {
7 headers: {
8 "Authorization": `Bearer ${env.OPENAI_API_KEY}`,
9 "OpenAI-Beta": "realtime=v1"
10 }
11 });
12
13 ws.on("open", () => {
14 console.log("WebSocket connection established with OpenAI Realtime API");
15
16 // Configure session modalities and voice parameters
17 const sessionConfig = {
18 type: "session.update",
19 session: {
20 modalities: ["text", "audio"],
21 instructions: "You are a helpful customer service assistant for Mecanik.",
22 voice: "alloy",
23 input_audio_format: "pcm16",
24 output_audio_format: "pcm16",
25 temperature: 0.7
26 }
27 };
28 ws.send(JSON.stringify(sessionConfig));
29 });
30
31 ws.on("message", (data) => {
32 const event = JSON.parse(data);
33
34 // Handle incoming audio content from the server
35 if (event.type === "response.audio.delta") {
36 const audioBuffer = Buffer.from(event.delta, "base64");
37 // Output buffer to client audio player
38 playAudioChunk(audioBuffer);
39 }
40 });
41}
Achten Sie beim Erstellen dieses Handlers darauf, dass Ihr API-Schlüssel vor dem Client-Browser verborgen bleibt. Richten Sie insbesondere eine Edge-Middleware auf Ihrem Server ein, um die Autorisierung zu verarbeiten, bevor Sie die WebSocket-Verbindung tunneln. Um mehr über Edge-API-Konfigurationen zu erfahren, lesen Sie unseren Leitfaden zum Erstellen einer serverlosen API mit Cloudflare Workers .
Aufbau des sicheren Edge-Proxys
Das obige Snippet verbindet sich von einem vertrauenswürdigen Server aus, zeigt aber nicht den Teil, der Ihren Schlüssel schützt: den Proxy selbst. Auf Cloudflare Workers können Sie dem new WebSocket()-Konstruktor keine benutzerdefinierten Header hinzufügen. Stattdessen öffnen Sie die Upstream-Verbindung mit fetch und einem Upgrade-Header. Der Worker akzeptiert den Socket des Browsers, wählt OpenAI mit Ihrem geheimen Schlüssel an und leitet dann die Frames zwischen den beiden Gegenstellen weiter.
1export default {
2 async fetch(request, env) {
3 if (request.headers.get("Upgrade") !== "websocket") {
4 return new Response("Expected a WebSocket upgrade", { status: 426 });
5 }
6
7 // 1. Accept the browser <-> Worker socket
8 const [client, server] = Object.values(new WebSocketPair());
9 server.accept();
10
11 // 2. Open the Worker <-> OpenAI socket with the secret key attached
12 const upstreamResponse = await fetch(
13 "https://api.openai.com/v1/realtime?model=gpt-realtime",
14 {
15 headers: {
16 Upgrade: "websocket",
17 Authorization: `Bearer ${env.OPENAI_API_KEY}`,
18 "OpenAI-Beta": "realtime=v1"
19 }
20 }
21 );
22
23 const upstream = upstreamResponse.webSocket;
24 if (!upstream) {
25 return new Response("Upstream refused the upgrade", { status: 502 });
26 }
27 upstream.accept();
28
29 // 3. Pipe frames in both directions
30 server.addEventListener("message", (e) => upstream.send(e.data));
31 upstream.addEventListener("message", (e) => server.send(e.data));
32
33 const close = () => { try { server.close(); upstream.close(); } catch {} };
34 server.addEventListener("close", close);
35 upstream.addEventListener("close", close);
36
37 return new Response(null, { status: 101, webSocket: client });
38 }
39};
Speichern Sie den Schlüssel als verschlüsseltes Secret mit wrangler secret put OPENAI_API_KEY statt in der wrangler.toml, damit er niemals in Ihr Repository gelangt. Der Browser verbindet sich nun mit wss://your-worker.workers.dev und sieht die Zugangsdaten nie. Cloudflare dokumentiert dieses bidirektionale Muster in seiner Workers WebSockets-Referenz
.
Verarbeiten des Benutzer-Audiostreams
Sobald das Session-Update akzeptiert wurde, muss Ihr Client die Mikrofoneingabe aufzeichnen, in 24 kHz Mono-PCM16-Daten komprimieren und als Base64-Segmente streamen. Da die Verbindung permanent ist, ist der Umgang mit Netzwerkunterbrechungen entscheidend. Ein lokaler Chunk-Puffer stellt sicher, dass kurze Mobilfunkunterbrechungen nicht zu Audio-Paketverlusten oder unruhigen Agentenantworten führen: Der Client behält den Puffer und spielt ihn sofort nach der Wiederverbindung ab.
1// Example of streaming user microphone data
2function streamMicrophoneChunk(ws, base64AudioChunk) {
3 const audioEvent = {
4 type: "input_audio_buffer.append",
5 audio: base64AudioChunk
6 };
7 ws.send(JSON.stringify(audioEvent));
8}
Sobald der Benutzer aufhört zu sprechen, verarbeitet der Server den angesammelten Audio-Puffer automatisch und löst eine Agentenantwort aus. Eine vollständige Liste der API-Events finden Sie im OpenAI Realtime Guide .
Implementieren Sie außerdem eine Echounterdrückung in Ihrem Frontend-Player. Wenn das Mikrofon die Lautsprecherausgabe erfasst, interpretiert der Agent seine eigene Stimme als Unterbrechung durch den Benutzer, was zum Fehlschlagen der Session führt. Um mehr über die Frontend-Optimierung zu erfahren, lesen Sie unseren Leitfaden zu WordPress vs. maßgeschneiderte Webentwicklung .
Verwaltung von Sprecherwechseln und Unterbrechungen
Standardmäßig müssen Sie dem Modell mitteilen, wann ein Sprecherwechsel stattfindet. Die Aktivierung der serverseitigen Sprachaktivitätserkennung (VAD - Voice Activity Detection) übergibt diese Aufgabe an OpenAI: Das Gateway überwacht den eingehenden Puffer, entscheidet, wann der Benutzer aufgehört hat zu sprechen, und löst automatisch eine Antwort aus. Fügen Sie dem Session-Update, das Sie während des Handshakes senden, einen turn_detection-Block hinzu.
1const sessionConfig = {
2 type: "session.update",
3 session: {
4 modalities: ["text", "audio"],
5 voice: "alloy",
6 input_audio_format: "pcm16",
7 output_audio_format: "pcm16",
8 turn_detection: {
9 type: "server_vad",
10 threshold: 0.5,
11 prefix_padding_ms: 300,
12 silence_duration_ms: 500
13 }
14 }
15};
Wenn VAD aktiv ist, sendet der Server das Event input_audio_buffer.speech_started in dem Moment, in dem er hört, dass der Benutzer dem Agenten ins Wort fällt. Behandeln Sie dieses Event als harten Stopp: Verwerfen Sie alle noch in Ihrem Player gepufferten Chunks, da sonst die vorherige Antwort weiterspielt, während die neue eintrifft.
1let playbackQueue = [];
2
3ws.on("message", (raw) => {
4 const event = JSON.parse(raw);
5 if (event.type === "input_audio_buffer.speech_started") {
6 // User is interrupting: drop everything still buffered
7 playbackQueue = [];
8 stopSpeaker();
9 }
10});
Ein Erhöhen von silence_duration_ms lässt den Agenten länger warten, bevor er antwortet, was für langsame oder zögerliche Sprecher geeignet ist. Ein Senken des Werts lässt das Gespräch dynamischer wirken, birgt jedoch das Risiko, Menschen mitten im Satz zu unterbrechen.
Schritt-für-Schritt-Bereitstellung des Sprachagenten
Um Ihre Sprachagenten-Middleware bereitzustellen, konfigurieren Sie zunächst ein sicheres WebSocket-Routing-Gateway auf serverlosen Edge-Knoten, um Ihre OpenAI-Zugangsdaten zu schützen. Dies verhindert, dass Scraper Ihre Schlüssel auslesen können.
Entwerfen Sie als Nächstes Ihre System-Prompts und Verhaltensregeln sorgfältig. Legen Sie Tonfall, Vokabular und Antwortanweisungen im Payload des anfänglichen Session-Update-Events fest. Dadurch wird ein klarer Rahmen für die Gesprächsverläufe geschaffen.
Implementieren Sie dann eine robuste Logik für Sprecherunterbrechungen. Sie sollten auf das Event input_audio_buffer.speech_started lauschen und die Audiowiedergabe in Ihrem Frontend-Player sofort stoppen. Optimieren Sie schließlich die globale Latenz, indem Sie Ihre Workers in enger regionaler Nähe zu Ihren Benutzern bereitstellen, um Routing-Hops zu reduzieren. Um Edge-Hosting-Optionen zu erkunden, lesen Sie unser Cloudflare Workers AI-Tutorial
.
Häufige Fehler und Fehlerbehebung
Die meisten Fehler beim ersten Start resultieren aus einer Handvoll vorhersehbarer Fehler. Die folgende Tabelle ordnet Fehler ihrer Ursache und Behebung zu:
| Symptom | Wahrscheinliche Ursache | Behebung |
|---|---|---|
Verbindung schließt sofort mit 401 | Fehlender oder fehlerhafter Authorization-Header | Stellen Sie sicher, dass der Proxy Bearer <Schlüssel> anhängt und der Schlüssel Realtime-Zugriff besitzt |
| Agent hört nur Stille oder verzerrte Sprache | Audio wurde mit der falschen Samplerate oder Bittiefe gesendet | Resampeln Sie vor der Base64-Codierung auf 24 kHz Mono-PCM16 |
| Modell antwortet nie, nachdem der Benutzer gesprochen hat | turn_detection ist deaktiviert und es wurde kein manueller Commit gesendet | Aktivieren Sie server_vad oder senden Sie input_audio_buffer.commit gefolgt von response.create |
| Agent spricht gleichzeitig mit dem Benutzer | Der speech_started-Handler leert die Wiedergabe-Queue nicht | Leeren Sie den Wiedergabepuffer und stoppen Sie den Lautsprecher bei diesem Event |
| Antworten werden mitten im Satz abgeschnitten | max_response_output_tokens ist zu niedrig eingestellt | Erhöhen Sie das Limit oder lassen Sie es auf inf |
Zwei subtilere Probleme verdienen Aufmerksamkeit. Ein rate_limits.updated-Event, das mit einem niedrigen verbleibenden Kontingent eintrifft, ist Ihre Frühwarnung, dass gleichzeitige Sessions gedrosselt werden könnten. Protokollieren Sie dies und drosseln Sie die Verbindungen, anstatt Verbindungsversuche zu wiederholen. Wenn der Agent gelegentlich seinen eigenen letzten Satz beantwortet, erfasst das Mikrofon die Lautsprecherausgabe. Verbessern Sie in diesem Fall die Echounterdrückung oder lassen Sie die Tester Headsets verwenden.
Testen und Überlegungen für die Produktion
Lokales Testen ist anspruchsvoll, da Sie einen echten Audiomix in beide Richtungen benötigen. Der schnellste Weg ist, den Worker mit wrangler dev auszuführen, eine einfache Browserseite darauf zu richten und den Event-Stream in der Konsole zu beobachten, bevor Sie sich um die Audioqualität sorgen. Protokollieren Sie während der Entwicklung jeden eingehenden Eventtyp. Sobald die Abfolge von session.updated, speech_started, response.audio.delta und response.done korrekt aussieht, wissen Sie, dass die Verbindung steht.
Berücksichtigen Sie vor dem Livegang einige Produktionsrealitäten:
- Kosten. Realtime-Audio wird pro Minute eingehender und ausgehender Audio-Token abgerechnet, was weitaus teurer ist als reine Text-Token. Begrenzen Sie die Session-Länge und erwägen Sie ein Text-Fallback für lange, rein informative Antworten.
- Latenz. Platzieren Sie den Proxy so nah wie möglich bei Ihren Benutzern und halten Sie ihn schlank. Jeder zusätzliche Hop zwischen Browser, Edge und OpenAI erhöht die Umlaufzeit, die Sie minimieren möchten.
- Wiederverbindung. Sockets brechen in Mobilfunknetzen häufig ab. Halten Sie einen kurzen rollierenden Puffer auf dem Client bereit und spielen Sie ihn nach der Wiederverbindung ab, damit ein verlorener Frame das Gespräch nicht unterbricht.
- Observability. Generieren Sie strukturierte Logs für Session-Starts, Unterbrechungen und Fehlerereignisse, damit Sie Leistungseinbußen erkennen können, bevor Benutzer sich beschweren.
- Sicherheit und Datenschutz. Sprache sind persönliche Daten. Machen Sie die Datenaufbewahrung transparent und fügen Sie eine serverseitige Moderation für Transkripte hinzu, wenn Ihr Agent sensible Workflows verarbeitet.
Ein kurzer Testlauf mit echten Anrufern wird Akzent-, Rausch- und Unterbrechungs-Grenzfälle aufzeigen, die kein skriptbasierter Test abdeckt. Führen Sie diesen daher vor einem breiten Rollout durch.
Wichtige Erkenntnisse
- Die OpenAI Realtime API verarbeitet Audio nativ über permanente WebSockets und hält die Latenz unter 300 ms.
- Konfigurieren Sie Modalitäten, Formate und Prompts immer während des ersten WebSocket-Handshakes.
- Streamen Sie Benutzer-Audio in Echtzeit als Mono-PCM16-Base64-Segmente.
- Reagieren Sie auf Sprecherunterbrechungen, indem Sie das
speech_started-Event überwachen. - Schützen Sie Ihre API-Zugangsdaten, indem Sie Verbindungsdetails über Edge-Worker-Router tunneln.
Häufig gestellte Fragen (FAQ)
Was ist die OpenAI Realtime API? Die OpenAI Realtime API ist eine WebSocket-Schnittstelle, die es Entwicklern ermöglicht, rohe Audiodaten in das Modell hinein und aus ihm heraus zu streamen, wodurch separate ASR/TTS-Module überflüssig werden. Durch die native Audioverarbeitung bleiben Tonfall, Akzente und Sprachnuancen erhalten, während die Latenzzeit unter 300 Millisekunden sinkt.
Wie gehe ich mit Sprachunterbrechungen um?
Lauschen Sie auf das serverseitige Event input_audio_buffer.speech_started. Sobald dieses empfangen wird, leeren Sie Ihre Frontend-Audio-Puffer und stoppen Sie die Lautsprecherwiedergabe sofort. Dies schafft einen natürlichen Gesprächsfluss und sorgt dafür, dass die KI sofort verstummt, wenn der Benutzer zu sprechen beginnt.
Welche Audioformate unterstützt die API? Die API unterstützt nativ 24 kHz Mono-PCM16 (rohe vorzeichenbehaftete 16-Bit-Ganzzahlen) und G.711 (u-law und a-law) Audioformate. Entwickler müssen Mikrofondaten auf der Client-Seite erfassen, in diese spezifischen Formate konvertieren und sie als Base64-codierte Strings in JSON-WebSocket-Frames streamen.
Benötige ich einen separaten Server, um den WebSocket-Verkehr zu koordinieren? Ja. Die Verwendung eines serverlosen Edge-Koordinators (wie Cloudflare Workers oder ein leichtgewichtiges Node.js-Gateway) wird dringend empfohlen. Der Proxy empfängt Mikrofoneingaben von Client-Browsern, hängt sichere Autorisierungs-Header an und leitet den Binärstream an das Gateway von OpenAI weiter.
Wie verhindere ich Echoschleifen bei Echtzeit-Sprachagenten? Echoschleifen entstehen, wenn die Audioausgabe des Lautsprechers wieder in das Mikrofon des Clients gelangt und fälschlicherweise Unterbrechungs-Events auslöst. Entwickler müssen clientseitige Echounterdrückungsalgorithmen implementieren oder beim Testen Kopfhörer verwenden, um Feedbackschleifen zu vermeiden.
Kommentare