For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navegación principal
Theme

WebSockets

Conecta flujos de audio que gestiona el servidor mediante WebSockets.

Elige tu API para ver cómo conectarte y qué eventos se usan durante la sesión.

Conectar un servidor a GPT-Live

Recomendamos WebRTC para las conexiones de audio con GPT-Live, incluidas las integraciones entre servidores.

También puedes usar WebSockets. La conexión WebSocket principal transmite audio y eventos JSON en ambos sentidos. Guarda la clave de API del proyecto en tu servidor de confianza.

Esta guía explica cómo transmitir audio a GPT-Live. Para supervisar o controlar una sesión existente, consulta Controles del lado del servidor. Para conectar un backend de razonamiento y herramientas a la API de Responses, consulta Modo WebSocket de Responses.

Autenticarse e iniciar la sesión

  1. Conéctate a wss://api.openai.com/v1/live/sessions sin parámetros de consulta. Autentícate con Authorization: Bearer $OPENAI_API_KEY e incluye los encabezados de conexión que se muestran en el ejemplo.
  2. Envía session.start como primer mensaje. Incluye el modelo, las instrucciones de conversación, el formato de audio, la voz y la configuración de delegación en el objeto session.
  3. Espera a recibir session.started antes de enviar audio o comandos de la aplicación. Este evento contiene la configuración efectiva de la sesión y su ID.

El siguiente ejemplo usa la voz Marin, audio PCM16 a 24 kHz y un backend de Responses con búsqueda web. Usa instrucciones de conversación breves. Para configurar las instrucciones del backend, las herramientas y sus permisos, sigue la guía de Delegación y herramientas.

Transmitir audio con un SDK

Para Node.js, instala openai y ws con npm install openai ws y guarda el ejemplo de JavaScript como client.mjs. Para Python en macOS o Linux, instala openai[realtime] y guarda el ejemplo de Python como client.py. Define OPENAI_API_KEY en el entorno del servidor. Estos ejemplos requieren una versión del SDK compatible con Live. El ejemplo lee audio PCM16 mono sin procesar a 24 kHz de la entrada estándar y escribe el audio recibido en el mismo formato en la salida estándar. Conecta estos flujos a los sistemas de captura y reproducción de audio de tu aplicación. Los registros y los eventos de transcripción se envían a la salida de error estándar para evitar que alteren el flujo de audio.

Para Go, usa Go 1.26 o posterior, guarda el ejemplo como main.go, inicializa un módulo con go mod init live-demo e instala github.com/openai/openai-go/v3@v3.85.1 con go get. Para Java, usa Java 17 o posterior, agrega la dependencia de Maven com.openai:openai-java:4.95.0 y usa la clase LiveConnectionWebsocketExample. Para Ruby 3.3 o posterior, instala el SDK con gem install openai -v 0.110.0, instala su dependencia de WebSocket con gem install async-websocket y guarda el ejemplo como client.rb.

import OpenAI from "openai";
import { LiveWS } from "openai/resources/live/ws";

// stdin and stdout carry raw mono PCM16 audio at 24 kHz, not WAV files.
// Supply microphone bytes continuously and play stdout in the same format.
process.stdin.pause();
const ws = new LiveWS(new OpenAI());
let started = false;
let closing = false;
let finalized = false;
let pendingByte = Buffer.alloc(0);

let closeTimeout;

ws.socket.on("open", () => {
  ws.send({
    type: "session.start",
    event_id: "event_start",
    session: {
      model: "gpt-live-1",
      instructions:
        "Be concise. Delegate requests needing current information to the backend, which can search the web.",
      audio: {
        format: { type: "audio/pcm", rate: 24000 },
        output: { voice: "marin" },
      },
      delegation: {
        type: "responses",
        responses: {
          model: "gpt-5.6-luna",
          tools: [{ type: "web_search" }],
          tool_choice: "auto",
        },
      },
    },
  });
});

process.stdin.on("data", (chunk) => {
  if (!started || closing || ws.socket.readyState !== 1) return;
  const bytes = Buffer.concat([pendingByte, chunk]);
  const completeLength = bytes.length - (bytes.length % 2);
  pendingByte = bytes.subarray(completeLength);
  if (completeLength) {
    ws.send({
      type: "session.input_audio.append",
      audio: bytes.subarray(0, completeLength).toString("base64"),
    });
  }
});

// Register the final-event handler before any close command can be sent.
ws.on("event", (event) => {
  if (event.type === "session.started") {
    started = true;
    console.error("Session ready", event.session.id);
    process.stdin.resume();
  } else if (event.type === "session.output_audio.delta") {
    process.stdout.write(Buffer.from(event.delta, "base64"));
  } else if (event.type === "session.closed") {
    finalized = true;
    clearTimeout(closeTimeout);
    process.stdin.pause();
    console.error("Final session usage", event.usage);
    ws.close();
  } else {
    // Includes transcript deltas and nested response.event usage.
    console.error(JSON.stringify(event));
  }
});

process.on("SIGINT", () => {
  if (closing) return;
  if (!started || ws.socket.readyState !== 1) {
    ws.socket.platformSocket.terminate();
    return;
  }
  closing = true;
  process.stdin.pause();
  ws.send({ type: "session.close" });
  closeTimeout = setTimeout(() => {
    console.error("Incomplete finalization: session.closed was not received");
    process.exitCode = 1;
    ws.socket.platformSocket.terminate();
  }, 15_000);
});
ws.on("error", (error) => {
  console.error(error.message);
  process.exitCode = 1;
});
ws.socket.on("close", () => {
  clearTimeout(closeTimeout);
  process.stdin.pause();
  if (!finalized) {
    console.error("Connection closed without final session usage");
    process.exitCode = 1;
  }
});

Ejecuta node client.mjs, python client.py, go run ., ruby client.rb o tu aplicación Java con la fuente de audio y el reproductor conectados. Cuando aparezca Session ready, envía un flujo continuo de audio del micrófono a la misma velocidad a la que se capturan las muestras. Enviar un archivo completo de una sola vez por una tubería no simula un micrófono en vivo. La indicación de fin de archivo (EOF) en la fuente de audio no termina la conversación. Envía SIGINT al proceso para solicitar un cierre ordenado.

El ejemplo conecta los flujos de audio. Tu aplicación se encarga de la captura, el almacenamiento en búfer, la reproducción y, cuando sea necesario, el remuestreo. Prueba estas funciones con tus dispositivos y tu red antes de evaluar el comportamiento del modelo.

Elegir el formato de audio

Configura session.audio.format al iniciar la sesión. La entrada y la salida usan el mismo formato, que no se puede cambiar durante la sesión.

  • {"type":"audio/pcm","rate":24000}: audio PCM mono de 16 bits con signo en orden little-endian a 24 kHz. Es el formato predeterminado.
  • {"type":"audio/pcm","rate":16000}: audio PCM mono de 16 bits con signo en orden little-endian a 16 kHz.
  • {"type":"audio/pcmu","rate":8000}: codificación G.711 con ley μ a 8 kHz, con un byte por muestra.
  • {"type":"audio/pcma","rate":8000}: codificación G.711 con ley A a 8 kHz, con un byte por muestra.

Codifica los bytes sin procesar en base64, sin incluir un encabezado WAV ni de otro contenedor. Cada bloque PCM debe contener muestras completas de 16 bits, por lo que su longitud en bytes debe ser par. Si sobra un byte al final de un bloque de entrada, el ejemplo lo incorpora al siguiente. Fuera de esa condición, puedes dividir el audio en bloques donde quieras, siempre que el flujo sea continuo y conserve el orden.

Remuestrea el audio si su frecuencia de muestreo difiere de la configurada. Cambiar el formato en la configuración no convierte los bytes de entrada. Para adaptar el ejemplo a G.711, reenvía los bytes codificados de cada bloque sin aplicar la lógica de alineación en pares de bytes propia de PCM y configura el reproductor de salida para que use el mismo códec. Si el flujo G.711 coincide con el formato configurado, puedes transmitirlo sin convertirlo a PCM. Para conectar una llamada telefónica, consulta Integraciones de telefonía.

Enviar y recibir eventos

Envía cada evento como un mensaje de texto JSON. El audio se transmite en base64 dentro de esos mensajes.

  • Enviar audio: envía session.input_audio.append con los bytes sin procesar codificados en base64 en el campo audio. Al agregar audio, no recibirás una confirmación.
  • Recibir audio: decodifica delta de cada evento session.output_audio.delta y coloca el audio en la cola para reproducirlo en orden con el formato configurado.
  • Recibir transcripciones: agrega el texto del campo delta de los eventos session.input_transcript.delta y session.output_transcript.delta al final de la transcripción correspondiente.
  • Recibir eventos del backend: cuando uses la delegación a Responses, procesa el campo event anidado en cada mensaje response.event.
  • Manejar errores: usa los eventos error para manejar los comandos rechazados y los errores de sesión. Si está presente, usa error.client_event_id para identificar el comando.

Usa la cola de audio de tu aplicación para seguir el avance de la reproducción. La conexión WebSocket principal de GPT-Live envía el audio de salida sin campos de tiempo ni un evento que indique el fin de ese audio. Usa las marcas de tiempo de la transcripción para organizar los subtítulos y los eventos del backend para seguir el trabajo delegado.

Mientras el audio se transmite de forma continua, GPT-Live decide cuándo escuchar y cuándo hablar. Usa response.create para iniciar o continuar el trabajo delegado al backend. Consulta Delegación y herramientas para conocer ese flujo de trabajo.

Configurar una sesión en curso

El modelo Live, las instrucciones iniciales de conversación, el formato de audio, la voz y el modo de delegación quedan fijos al iniciar la sesión. Usa session.update para cambiar los ajustes admitidos por el modo de delegación actual. Los ajustes que omitas conservarán sus valores. Si la actualización se completa correctamente, recibirás session.updated con la configuración efectiva de la sesión.

Usa session.instructions.append para agregar instrucciones de conversación y session.input_audio.mute o session.input_audio.unmute para controlar el audio entrante. Silenciar la entrada no cancela el trabajo del backend ni detiene la voz generada. Consulta Administración de sesiones para obtener más información sobre las actualizaciones de contexto, las transcripciones, los controles de entrada y el uso.

Cerrar la sesión

Cuando termine la conversación, envía session.close. Antes de enviarlo, registra el controlador de session.closed. Sigue recibiendo eventos hasta que llegue ese evento y luego libera la conexión. El ejemplo espera hasta 15 segundos e informa que el cierre quedó incompleto si no llega el evento final.

Conserva los datos finales de uso de voz de session.closed y los eventos de uso del backend que ya recibiste. Cada actualización de la duración de voz indica el total acumulado hasta ese momento. No sumes esos valores. Si se produce un error de transporte o se agota el tiempo de espera antes de recibir session.closed, el uso final queda sin confirmar. Consulta Administración de sesiones para conocer el ciclo de vida completo.