For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navegação principal

WebSockets

Conecte fluxos de áudio gerenciados pelo servidor por WebSockets.

Escolha a API que seu aplicativo usa. Cada API tem seus próprios mecanismos de autenticação e criação de sessões, além de seu próprio contrato de eventos.

Conecte um servidor ao GPT-Live

Use um WebSocket principal quando seu servidor capturar áudio ou retransmitir um fluxo de áudio para um cliente. Ele transporta áudio e eventos JSON nas duas direções. Mantenha a chave de API do projeto nesse servidor confiável. Para aplicativos de navegador e dispositivos móveis, comece com WebRTC.

Este guia aborda a conexão principal de áudio. Uma conexão de banda lateral permite que um servidor observe e controle uma sessão Live existente. Um WebSocket da Responses conecta seu backend à API Responses para raciocínio e ferramentas. Nenhuma dessas conexões substitui a conexão principal de áudio.

Autentique-se e inicie a sessão

  1. Conecte-se a wss://api.openai.com/v1/live/sessions sem parâmetros de consulta. Autentique-se com Authorization: Bearer $OPENAI_API_KEY e inclua os cabeçalhos de conexão mostrados no exemplo.
  2. Envie session.start como a primeira mensagem. Coloque o modelo, as instruções da conversa, o formato de áudio, a voz e a configuração de delegação dentro do objeto session.
  3. Aguarde session.started antes de enviar áudio ou comandos do aplicativo. Esse evento contém a configuração efetiva da sessão e o ID da sessão.

O exemplo abaixo usa Marin, áudio PCM16 a 24 kHz e um backend da Responses com pesquisa na Web. Mantenha as instruções da conversa curtas. Configure as instruções do backend, as ferramentas e as permissões das ferramentas conforme descrito em Delegação e ferramentas.

Transmita áudio com um SDK

Para Node.js, instale openai e ws com npm install openai ws e salve o exemplo JavaScript como client.mjs. Para Python no macOS ou Linux, instale openai[realtime] e salve o exemplo Python como client.py. Defina OPENAI_API_KEY no ambiente do servidor. Esses exemplos exigem uma versão do SDK com suporte ao Live. O exemplo lê áudio PCM16 bruto, mono, a 24 kHz da entrada padrão e grava o áudio retornado no mesmo formato na saída padrão. Conecte esses fluxos à captura e à reprodução de áudio do seu aplicativo. Os logs e os eventos de transcrição são enviados para a saída de erro padrão para não corromper o fluxo de áudio.

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

Execute node client.mjs ou python client.py com sua fonte de áudio e seu reprodutor conectados. Depois que Session ready aparecer, forneça um fluxo contínuo do microfone no ritmo da taxa de amostragem usada na gravação. Enviar um arquivo inteiro de uma só vez por um pipe não simula um microfone ao vivo. O EOF na fonte de áudio não encerra a conversa. Envie SIGINT ao processo para solicitar um encerramento normal.

O exemplo conecta os fluxos de áudio; seu aplicativo cuida da captura, do armazenamento em buffer, da reprodução e da reamostragem, quando necessária. Teste essas partes com seus dispositivos e sua rede antes de avaliar o comportamento do modelo.

Escolha o formato de áudio

Defina session.audio.format na inicialização. Um único formato se aplica tanto à entrada quanto à saída e não pode mudar durante a sessão.

  • {"type":"audio/pcm","rate":24000}: PCM mono de 16 bits com sinal, little-endian, a 24 kHz; o padrão.
  • {"type":"audio/pcm","rate":16000}: PCM mono de 16 bits com sinal, little-endian, a 16 kHz.
  • {"type":"audio/pcmu","rate":8000}: G.711 μ-law a 8 kHz, um byte por amostra.
  • {"type":"audio/pcma","rate":8000}: G.711 A-law a 8 kHz, um byte por amostra.

Codifique os bytes brutos em base64, sem cabeçalho WAV ou de outro contêiner. Os blocos PCM devem conter amostras completas de 16 bits, portanto seu tamanho em bytes deve ser par. O exemplo transfere um byte restante no final para o próximo bloco de entrada. Fora isso, os limites dos blocos são arbitrários: preserve um fluxo contínuo e ordenado.

Reamostre o áudio quando sua taxa de amostragem for diferente da taxa configurada. Alterar a configuração de formato não converte os bytes de entrada. Para adaptar o exemplo ao G.711, encaminhe os bytes do codec de cada bloco sem a lógica de alinhamento de dois bytes específica do PCM e configure o reprodutor de saída para o mesmo codec. Um fluxo G.711 compatível pode passar sem conversão para PCM. Consulte Integrações de telefonia para conectar uma chamada telefônica.

Envie e receba eventos

Envie cada evento como uma mensagem de texto JSON. O áudio é transportado em base64 dentro dessas mensagens.

  • Envie áudio: envie session.input_audio.append com bytes brutos codificados em base64 em audio. As operações de acréscimo de áudio não recebem confirmação.
  • Receba áudio: decodifique delta de cada evento session.output_audio.delta e coloque o áudio na fila para reprodução em ordem, usando o formato configurado.
  • Receba transcrições: acrescente o texto de delta dos eventos session.input_transcript.delta e session.output_transcript.delta à transcrição correspondente.
  • Receba eventos do backend: ao usar a delegação para a Responses, processe o event aninhado em cada envelope response.event.
  • Trate erros: trate comandos rejeitados e erros de sessão informados nos eventos error. Use error.client_event_id, quando presente, para identificar o comando.

Os eventos de áudio de saída não têm campos de tempo, e o GPT-Live não emite um evento output-audio-done. Acompanhe sua fila de reprodução para saber qual áudio recebido já foi reproduzido. Os carimbos de data/hora das transcrições descrevem intervalos na linha do tempo da sessão; eles não indicam a conclusão da reprodução do áudio. A conclusão de uma resposta do backend também não significa que o assistente terminou de falar.

O GPT-Live gerencia quando ouvir e falar durante a transmissão de áudio. Ele não usa o ciclo de turnos de voz do Realtime, baseado na confirmação do buffer de entrada e em response.create. No Live, response.create inicia ou continua o trabalho delegado ao backend. Consulte Delegação e ferramentas para conhecer esse fluxo de trabalho.

Configure uma sessão em andamento

O modelo Live, as instruções iniciais da conversa, o formato de áudio, a voz e o modo de delegação são fixados na inicialização. Use session.update para alterar as configurações compatíveis com o modo de delegação existente; as configurações omitidas mantêm seus valores atuais. Uma atualização bem-sucedida retorna session.updated com a configuração efetiva da sessão.

Use session.instructions.append para adicionar instruções à conversa e session.input_audio.mute ou session.input_audio.unmute para controlar o áudio de entrada. Silenciar a entrada não cancela o trabalho do backend nem interrompe a fala gerada. Consulte Gerenciamento de sessões para saber mais sobre atualizações de contexto, transcrições, controles de entrada e uso.

Encerre a sessão

Envie session.close quando a conversa terminar. Primeiro, registre o ouvinte de session.closed, continue recebendo até esse evento chegar e, então, libere a conexão. O exemplo aguarda até 15 segundos e informa que a finalização ficou incompleta se o evento de encerramento não chegar.

Preserve os dados finais de uso de voz de session.closed e os eventos de uso do backend já recebidos. As atualizações de duração de voz são registros cumulativos; não some seus valores. Uma falha de transporte ou um tempo limite excedido antes de session.closed deixa o uso final sem confirmação. Consulte Gerenciamento de sessões para conhecer o ciclo de vida completo.