Az alacsony látenciájú audiopályák kiépítése az új OpenAI Realtime API segítségével lehetővé teszi a fejlesztők számára, hogy emberi társalgáshoz hasonló hangágenseket (Voice Agents) indítsanak el éles környezetben. Korábban a hangalapú felületek felépítése három különálló modellréteg egymás után kapcsolását jelentette: automatikus beszédfelismerés (ASR), szövegalapú LLM logikai réteg, majd szövegfelolvasás (TTS). Ez a többlépcsős folyamat jelentős hálózati késleltetést okozott, ami lehetetlenné tette a természetes társalgást. A natív audio-feldolgozás egy folyamatos WebSocket kapcsolaton keresztül ezt megváltoztatja, és a hálózati látenciát 300 ezredmásodperc alá csökkenti. Ez az útmutató elmagyarázza a kapcsolatok felépítését, a nyers audiopufferek streamelését és a munkamenetek konfigurálását.

[!IMPORTANT] API biztonsági figyelmeztetés: Soha ne tegye közzé az OpenAI API-kulcsát közvetlenül a kliensoldali böngésző szkriptekben. A WebSocket kapcsolatot mindig egy biztonságos peremhálózati middleware-en (például egy Cloudflare Worker-en) keresztül irányítsa át, amely hozzáadja a hitelesítési fejléceket, mielőtt a csomagokat továbbítaná az OpenAI felé.

Fő tanulságok:

  • WebSocket kapcsolat: Csatlakozzon közvetlenül az OpenAI Realtime WebSocket átjárójához edge proxykon keresztül.
  • Natív modalitások: Határozza meg a text és audio típusokat az első munkamenet-frissítési konfigurációs csomagban.
  • Audioformátum: Streamelje a felhasználó beszédét base64 kódolású mono PCM16 adatrészletekben, 24 kHz-en.
  • Beszéd félbeszakítása: Figyelje a szerver beszédkezdési jelzéseit a kliensoldali lejátszás azonnali leállításához.

A natív audio LLM-ek architektúrája

A hagyományos hangalapú rendszerek a beszédfelismerő és beszédgeneráló modelleket külső wrapperként kezelik a központi szöveges modell körül. A natív audiomodellek kiküszöbölik ezt a felesleges overheadet a beszéd közvetlen feldolgozásával.

Az OpenAI modellcsalád megjelenésével a hálózat natív módon dolgozza fel az audio bemeneteket és kimeneteket. A modell közvetlen hanghullámokat kap, elemzi a hangszínt, az intonációt és a tartalmat, majd közvetlenül természetes hangot generál. Ennek eredményeként a rendszer megszünteti az ASR transzkripciós hibákat és a TTS beszédgenerálási szűk keresztmetszeteket.

A folyamatos kapcsolat kezelése WebSockets technológiára épül. A kapcsolat a hívás során végig nyitva marad, így az ágens azonnal képes megszakítani a saját beszédét, ha a felhasználó megszólal, így a felhasználói élmény egy valódi telefonhívásra hasonlít.

Kérjen MI-integrációs szolgáltatásokat

Előfeltételek

A kód megírása előtt győződjön meg arról, hogy a környezet készen áll. Ez a fejlesztés feltételezi, hogy magabiztosan kezeli az aszinkron JavaScriptet, és rendelkezik a következőkkel:

  • Egy OpenAI-fiók Realtime hozzáféréssel és egy feltöltött, aktív API-kulccsal.
  • Node.js 20 vagy újabb verzió, vagy egy Cloudflare Workers projekt, amelyet az npm create cloudflare@latest paranccsal hozott létre.
  • Egy WebSocket kliens – a ws csomag egy Node.js átjáróhoz, vagy a Workers-ben elérhető natív globális WebSocket.
  • Egy böngésző frontend, amely képes rögzíteni a mikrofon hangját a Web Audio API-n keresztül (getUserMedia és egy AudioWorklet az újramintavételezéshez).
  • Alapszintű ismeretek a base64 és PCM audióról, mivel minden elküldött vagy fogadott adatkeret egy base64 kódolású PCM16 csomag.

Szánjon egy kis időt a fiók beállítására is: a Realtime hozzáférést és a számlázást engedélyezni kell a szervezeténél, mielőtt a gateway elfogadná a munkamenetet.


WebSocket kapcsolatok felépítése

Első lépésként nyisson meg egy kapcsolatot az OpenAI Realtime átjárójához, megadva a GPT-realtime modellt a fejlécekben.

Az alábbi JavaScript kód bemutatja a kapcsolat inicializálását, a munkamenet modalitásainak konfigurálását, valamint a bejövő és kimenő audiopufferek kezelését:

 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}

A kezelő megírásakor ügyeljen arra, hogy az API-kulcs rejtve maradjon a böngésző elől. Pontosabban, hozzon létre egy peremhálózati middleware-t a szerverén a jogosultságok kezelésére, mielőtt a WebSocket kapcsolatot átirányítaná. Az edge API konfigurációkról bővebben a szerver nélküli API építése Cloudflare Workers segítségével útmutatónkban olvashat.


A biztonságos Edge Proxy felépítése

A fenti kódrészlet egy megbízható szerverről csatlakozik, de nem mutatta be a kulcs biztonságát szolgáló legfontosabb részt: magát a proxyt. Cloudflare Workers alatt nem csatolhat egyedi fejléceket a new WebSocket() konstruktorhoz, ezért az upstream kapcsolatot a fetch és egy Upgrade fejléc segítségével kell megnyitnia. A Worker elfogadja a böngésző socketjét, tárcsázza az OpenAI-t a titkos kulccsal, majd közvetíti a kereteket a két oldal között.

 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};

A kulcsot titkosított adatként tárolja a wrangler secret put OPENAI_API_KEY parancs segítségével a wrangler.toml helyett, így az soha nem kerül be a verziókövető rendszerbe. A böngésző mostantól a wss://your-worker.workers.dev címhez csatlakozik, és soha nem látja a hitelesítő adatokat. A Cloudflare részletesen dokumentálja ezt a kétirányú mintát a Workers WebSockets dokumentációjában .


Felhasználói audio streamelése

A munkamenet-frissítés elfogadása után a kliensnek rögzítenie kell a mikrofon bemenetét, tömörítenie kell azt 24 kHz-es mono PCM16 adattá, és base64 szegmensekként kell streamelnie. Mivel a kapcsolat folyamatos, a hálózati kimaradások kezelése kritikus fontosságú. Egy helyi puffertár biztosítja, hogy a rövid mobilhálózati kimaradások ne vezessenek adatvesztéshez vagy akadozó válaszokhoz: a kliens megőrzi a puffert, és az újracsatlakozás után azonnal lejátszásba helyezi.

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}

Amikor a felhasználó befejezi a beszédet, a szerver automatikusan feldolgozza az összegyűlt audiopuffert és válaszadást vált ki a modellből. Az API-események teljes listájáért tekintse meg az OpenAI Realtime dokumentációját .

Emellett implementáljon visszhang-kioltást a frontend oldalon. Ha a mikrofon rögzíti a hangszóró kimenetét, az ágens saját hangját felhasználói félbeszakításként értelmezi, ami a kapcsolat megszakadásához vezet. A frontend-optimalizációról bővebben a WordPress vs. egyedi webfejlesztés cikkünkben olvashat.


Társalgási irányítás és a félbeszakítások kezelése

Alapesetben manuálisan kell jeleznie a modellnek, ha véget ért a mondanivalója. A szerveroldali hangaktivitás-érzékelés (VAD) engedélyezése ezt a feladatot átadja az OpenAI-nak: az átjáró figyeli a bejövő puffert, eldönti, mikor fejezte be a beszédet a felhasználó, és automatikusan elindítja a választ. Adjon hozzá egy turn_detection blokkot a kézfogás során elküldött konfigurációhoz.

 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};

Aktív VAD mellett a szerver elküldi az input_audio_buffer.speech_started eseményt abban a pillanatban, amikor érzékeli, hogy a felhasználó az ágens szavába vág. Kezelje ezt az eseményt azonnali leállításként: töröljön minden várólistára helyezett audiorészletet a lejátszóból, különben a korábbi válasz tovább szól, miközben az új már megérkezett.

 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});

A silence_duration_ms értékének növelésével az ágens hosszabb ideig vár a válaszadással, ami ideális a lassabban beszélők számára; az érték csökkentése gyorsabbá teszi a párbeszédet, de fennáll a veszélye, hogy félbeszakítja a felhasználót a mondat közepén.


Hangágens lépésről lépésre történő élesítése

A hangágens köztes szoftverének (middleware) telepítéséhez először konfiguráljon egy biztonságos WebSocket átjárót a szerver nélküli edge csomópontokon, hogy megvédje az OpenAI hitelesítő adatait. Ez megakadályozza, hogy az adatokat kaparó robotok hozzáférjenek a kulcsaihoz.

Ezt követően határozza meg a rendszer promptjait és szabályait. Állítsa be a hangnemet, a szókincset és a válaszadási utasításokat a kezdeti konfigurációs esemény során. Ez egyértelmű kereteket ad a beszélgetések számára.

Végül valósítson meg megbízható félbeszakítás-kezelést a lejátszóban. Figyelje a input_audio_buffer.speech_started eseményt, és azonnal állítsa le a hang lejátszását a kliens oldalon. Végezetül optimalizálja a látenciát azáltal, hogy a Workers példányokat a felhasználókhoz földrajzilag közel helyezi el, így csökkentve a hálózati ugrások számát. A peremhálózati hosztolásról bővebben a Cloudflare Workers AI útmutatónkban olvashat.


Gyakori hibák és elhárításuk

A legtöbb kezdeti hiba néhány jól ismert probléma miatt következik be. Az alábbi táblázat bemutatja a leggyakoribb hibákat, azok okait és javításukat:

JelenségValószínű okMegoldás
A kapcsolat azonnal megszakad 401-es hibávalHiányzó vagy hibás Authorization fejlécEllenőrizze, hogy a proxy csatolja-e a Bearer <key> fejlécet, és a kulcs rendelkezik-e Realtime hozzáféréssel
Az ágens csak csendet vagy torz beszédet észlelAz audio nem megfelelő mintavételezési rátával lett elküldveVégezzen újramintavételezést 24 kHz mono PCM16 formátumra a base64 kódolás előtt
A modell soha nem válaszol, miután a felhasználó beszéltA turn_detection ki van kapcsolva, és nincs kézi véglegesítésKapcsolja be a server_vad-ot, vagy küldjön input_audio_buffer.commit majd response.create eseményt
Az ágens a felhasználó szavába vágA speech_started kezelő nem üríti a lejátszási sortÜrítse a lejátszási puffert és állítsa le a hangszórót az esemény érkezésekor
A válaszok félbeszakadnak a mondat közepénA max_response_output_tokens túl alacsonyra van állítvaNövelje a limitet, vagy hagyja inf értéken

Két apróbb problémára érdemes odafigyelni. A rate_limits.updated esemény megérkezése alacsony fennmaradó egyenleggel korai figyelmeztetés arra, hogy a párhuzamos munkamenetek hamarosan korlátozásra kerülnek; naplózza ezt és csökkentse a hívások ütemét az újracsatlakozások erőltetése helyett. Továbbá, ha az ágens időnként a saját előző mondatára válaszol, akkor a mikrofon rögzíti a hangszóró kimenetét; ilyenkor javítsa a visszhang-kioltást vagy kérje meg a tesztelőket, hogy használjanak fülhallgatót.


Tesztelés és üzemeltetés

A lokális tesztelés nehézkes lehet, mivel valós kétirányú audióra van szükség. A leggyorsabb módszer a Worker futtatása a wrangler dev segítségével, majd egy egyszerű böngészőlap rányitása a konzolos eseménynaplók megfigyeléséhez, még mielőtt a hangminőség miatt aggódna. Naplózzon minden bejövő eseményt a fejlesztés alatt; ha a session.updated, speech_started, response.audio.delta és response.done sorrendje megfelelő, akkor a kapcsolat stabil.

Az élesítés előtt vegye figyelembe az alábbi szempontokat:

  • Költségek. A valós idejű audió számlázása a bejövő és kimenő audiotokenek percei alapján történik, ami jóval drágább, mint a sima szöveges tokenek. Korlátozza a munkamenetek hosszát, és használjon szöveges megoldást a hosszabb információs válaszokhoz.
  • Késleltetés. Helyezze el a proxyt a lehető legközelebb a felhasználókhoz, és tartsa azt minimális szinten. Minden plusz ugrás a böngésző, a peremhálózat és az OpenAI között növeli a látenciát.
  • Újracsatlakozás. Mobilhálózatokon a socket kapcsolatok megszakadhatnak. Tartson fenn egy rövid futó puffert a kliensen, és játssza le újra az újracsatlakozáskor, így a hálózati hiba nem szakítja meg a társalgást.
  • Obszervabilitás. Hozzon létre strukturált naplókat a munkamenetek indításáról, a félbeszakításokról és a hibaeseményekről, hogy észlelje a teljesítménycsökkenést, mielőtt a felhasználók panaszkodnának.
  • Biztonság és adatvédelem. A hang személyes adat. Tegye egyértelművé az adatmegőrzési szabályokat, és használjon szerveroldali moderációt a leiratokon, ha az ágens érzékeny munkafolyamatokat kezel.

Egy valós hívókkal végzett rövid tesztüzem felszínre hozza az akcentusokból, zajokból és félbeszakításokból eredő egyedi eseteket, amelyeket az automatizált tesztek nem fednek le, ezért mindenképpen végezzen ilyet a szélesebb körű bevezetés előtt.


Legfontosabb tanulságok

  • Az OpenAI Realtime API natív módon dolgozza fel az audiót folyamatos WebSockets kapcsolaton keresztül, 300 ms alatt tartva a látenciát.
  • Mindig konfigurálja a modalitásokat, formátumokat és promptokat a kezdeti kapcsolatfelvétel során.
  • Streamelje a felhasználói hangot mono PCM16 base64 szegmensekként valós időben.
  • Kezelje a félbeszakítási eseményeket a beszédérzékelési események követésével.
  • Védje meg az API hitelesítő adatait a kapcsolatok edge worker proxykon keresztül történő átirányításával.

Gyakran ismételt kérdések (GYIK)

Mi az az OpenAI Realtime API? Az OpenAI Realtime API egy olyan WebSocket interfész, amely lehetővé teszi a fejlesztők számára, hogy nyers hangfájlokat streameljenek a modellbe és onnan vissza, elkerülve a különálló ASR/TTS modulok használatát. Az audió natív feldolgozásával a modell megőrzi az érzelmi tónust, az akcentusok finomságait és a beszéd árnyalatait, 300 ezredmásodperc alatti késleltetést elérve.

Hogyan kezelhetem a hangalapú félbeszakításokat? Figyelje a szerveroldali input_audio_buffer.speech_started eseményt. Amikor megérkezik, ürítse a frontend audiopuffereket, és azonnal állítsa le a hangszóró lejátszását. Ez természetes beszélgetési folyamatot hoz létre, lehetővé téve az MI-ágens számára, hogy azonnal elhallgasson, amikor a felhasználó beszélni kezd.

Milyen audioformátumokat támogat az API? Az API natívan támogatja a 24 kHz-es mono PCM16 (nyers 16 bites előjeles egész szám) és a G.711 (u-law és a-law) audioformátumokat. A fejlesztőknek rögzíteniük kell a mikrofon adatait, át kell alakítaniuk azokat ezekre a formátumokra a kliens oldalon, majd base64 kódolású karakterláncként kell streamelniük a JSON WebSocket kereteken belül.

Szükségem van külön szerverre a WebSocket forgalom koordinálásához? Igen. Kifejezetten ajánlott egy szerver nélküli edge koordinátor (például Cloudflare Workers vagy egy könnyűsúlyú Node.js átjáró) futtatása. A proxy fogadja a kliens böngészőkből érkező mikrofonbemeneteket, hozzáadja a biztonságos hitelesítési fejléceket, majd a bináris folyamot az OpenAI átjárójához irányítja.

Hogyan előzhetem meg a visszhang-hurkokat a valós idejű hangágenseknél? Visszhang-hurkok akkor alakulnak ki, ha a hangszóró hangja visszajut a kliens mikrofonjába, hamis félbeszakítási eseményeket váltva ki. A fejlesztőknek visszhang-kioltó algoritmusokat kell alkalmazniuk a kliens oldalon, vagy fejhallgatót kell használniuk a tesztelés során a visszacsatolási hurkok elkerülése érdekében.