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

WebSockets

Conecta flujos de audio administrados por el servidor a través de WebSockets.

Elige la API que usa tu aplicación. Cada API tiene sus propios mecanismos de autenticación y creación de sesiones, y su propio contrato de eventos.

Conecta un servidor a GPT-Live

Usa un WebSocket principal cuando tu servidor capture audio o retransmita un flujo de audio para un cliente. Transporta audio y eventos JSON en ambas direcciones. Mantén la clave de API del proyecto en ese servidor de confianza. Para aplicaciones móviles y de navegador, comienza con WebRTC.

Esta guía aborda la conexión principal de audio. Una conexión de banda lateral permite que un servidor observe y controle una sesión de Live existente. Un WebSocket de Responses conecta tu backend a la API Responses para usar razonamiento y herramientas. Ninguna de estas conexiones reemplaza la conexión principal de audio.

Autentícate e inicia 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 dentro del objeto session.
  3. Espera a recibir session.started antes de enviar audio o comandos de la aplicación. Contiene la configuración resuelta de la sesión y su ID.

El siguiente ejemplo usa Marin, audio PCM16 a 24 kHz y un backend de Responses con búsqueda web. Mantén breves las instrucciones de conversación. Configura las instrucciones del backend, las herramientas y sus permisos siguiendo Delegación y herramientas.

Transmite 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 desde la entrada estándar y escribe el audio recibido en el mismo formato en la salida estándar. Conecta estos flujos a la 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 que no corrompan el flujo de audio.

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 o python client.py con la fuente de audio y el reproductor conectados. Después de que aparezca Session ready, proporciona un flujo continuo de micrófono al ritmo de la frecuencia de muestreo con la que se grabó. Enviar un archivo completo de una sola vez por una tubería no simula un micrófono en vivo. Un EOF en la fuente de audio no finaliza 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 el remuestreo cuando sea necesario. Prueba estos componentes con tus dispositivos y tu red antes de evaluar el comportamiento del modelo.

Elige el formato de audio

Define session.audio.format al iniciar. Se aplica un mismo formato tanto a la entrada como a la salida y no se puede cambiar durante la sesión.

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

Codifica en base64 los bytes sin procesar, sin encabezado WAV ni de otro contenedor. Los fragmentos PCM deben contener muestras completas de 16 bits, por lo que su longitud en bytes debe ser par. El ejemplo traslada el byte sobrante al siguiente fragmento de entrada. Fuera de ese requisito, los límites de los fragmentos son arbitrarios: mantén un flujo continuo y ordenado.

Remuestrea el audio cuando su frecuencia de muestreo difiera de la frecuencia configurada. Cambiar la configuración del formato no convierte los bytes de entrada. Para adaptar el ejemplo a G.711, reenvía los bytes del códec de cada fragmento sin la lógica de alineación de dos bytes específica de PCM y configura el reproductor de salida para el mismo códec. Un flujo G.711 que coincida con la configuración puede pasar sin convertirse a PCM. Consulta Integraciones de telefonía para conectar una llamada telefónica.

Envía y recibe eventos

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

  • Envía audio: envía session.input_audio.append con bytes sin procesar codificados en base64 en audio. Las operaciones de adición de audio no reciben confirmación.
  • Recibe audio: decodifica delta de cada evento session.output_audio.delta y coloca el audio en una cola para reproducirlo en orden con el formato configurado.
  • Recibe transcripciones: agrega el texto de delta de los eventos session.input_transcript.delta y session.output_transcript.delta a la transcripción correspondiente.
  • Recibe eventos del backend: cuando uses la delegación a Responses, procesa el event anidado en cada mensaje contenedor response.event.
  • Maneja los errores: maneja los comandos rechazados y los errores de sesión a partir de los eventos error. Usa error.client_event_id, cuando esté presente, para identificar el comando.

Los eventos de audio de salida no tienen campos de tiempo y GPT-Live no emite un evento output-audio-done. Lleva un control de la cola de reproducción para saber qué audio recibido ya se reprodujo. Las marcas de tiempo de las transcripciones describen intervalos en la línea de tiempo de la sesión; no indican que la reproducción del audio haya terminado. Que se complete una respuesta del backend tampoco significa que el asistente haya terminado de hablar.

GPT-Live administra cuándo escuchar y hablar mientras se transmite el audio. No usa el ciclo de turnos de voz de Realtime basado en la confirmación del búfer de entrada y response.create. En Live, response.create inicia o continúa el trabajo delegado al backend. Consulta Delegación y herramientas para conocer ese flujo de trabajo.

Configura una sesión en curso

El modelo de Live, las instrucciones iniciales de conversación, el formato de audio, la voz y el modo de delegación quedan fijos al iniciar. Usa session.update para los ajustes admitidos dentro del modo de delegación existente; los ajustes omitidos conservan sus valores actuales. Una actualización exitosa devuelve session.updated con la configuración resuelta 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 información sobre las actualizaciones de contexto, las transcripciones, los controles de entrada y el uso.

Cierra la sesión

Envía session.close cuando termine la conversación. Primero registra el listener de session.closed, sigue recibiendo hasta que llegue ese evento y luego libera la conexión. El ejemplo espera hasta 15 segundos e informa que la finalización quedó incompleta si el evento final nunca llega.

Conserva los datos finales de uso de voz de session.closed y los eventos de uso del backend que ya recibiste. Las actualizaciones de duración de voz son instantáneas acumulativas; no las sumes. Si se produce una falla 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.