Escolha a API para ver como estabelecer a conexão e quais eventos ocorrem durante a sessão.
Conecte um servidor ao GPT-Live
Recomendamos o WebRTC para conexões de áudio com o GPT-Live, inclusive em integrações entre servidores.
Também há suporte a WebSockets. A conexão WebSocket principal transporta áudio e eventos JSON nos dois sentidos. Mantenha a chave de API do projeto no seu servidor de confiança.
Este guia mostra como transmitir áudio para o GPT-Live. Para monitorar ou controlar uma sessão existente, consulte Controles no servidor. Para conectar um backend de raciocínio e ferramentas à Responses API, consulte Modo WebSocket da Responses API.
Autentique a conexão e inicie a sessão
- Conecte-se a
wss://api.openai.com/v1/live/sessionssem parâmetros de consulta. UseAuthorization: Bearer $OPENAI_API_KEYpara autenticar a conexão e inclua os cabeçalhos de conexão mostrados no exemplo. - Envie
session.startcomo primeira mensagem. Inclua o modelo, as instruções da conversa, o formato de áudio, a voz e a configuração de delegação no objetosession. - Aguarde
session.startedantes 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 a seguir usa a voz Marin, áudio PCM16 a 24 kHz e um backend da Responses API com pesquisa na Web. Mantenha as instruções da conversa curtas. Para configurar as instruções do backend, as ferramentas e suas permissões, siga o guia 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 em JavaScript como client.mjs. Para Python no macOS ou Linux, instale openai[realtime] e salve o exemplo em Python como client.py. Defina OPENAI_API_KEY no ambiente do servidor. Esses exemplos exigem uma versão do SDK compatível com o Live. O exemplo lê áudio bruto PCM16 mono a 24 kHz da entrada padrão e grava o áudio recebido na saída padrão, no mesmo formato. Conecte esses fluxos aos recursos de 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 preservar o fluxo de áudio.
Para Go, use a versão 1.26 ou posterior, salve o exemplo como main.go, inicialize um módulo com go mod init live-demo e instale github.com/openai/openai-go/v3@v3.85.1 com go get. Para Java, use a versão 17 ou posterior, adicione a dependência Maven com.openai:openai-java:4.95.0 e use a classe LiveConnectionWebsocketExample. Para Ruby 3.3 ou posterior, instale o SDK com gem install openai -v 0.110.0, instale a dependência de WebSocket com gem install async-websocket e salve o exemplo 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;
}
});Com a fonte de áudio e o reprodutor conectados, execute node client.mjs, python client.py, go run ., ruby client.rb ou seu aplicativo Java. Quando aparecer Session ready, envie um fluxo contínuo de áudio do microfone, respeitando a taxa de amostragem da gravação. Enviar um arquivo inteiro de uma só vez por um pipe não simula um microfone ao vivo. O fim da entrada de áudio (EOF) 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, quando necessário, da reamostragem. Teste essas etapas com seus dispositivos e sua rede antes de avaliar o comportamento do modelo.
Escolha o formato de áudio
Defina session.audio.format ao iniciar a sessão. O mesmo formato se aplica à entrada e à saída e não pode ser alterado durante a sessão.
{"type":"audio/pcm","rate":24000}: PCM mono de 16 bits com sinal, em ordem little-endian, a 24 kHz (formato padrão).{"type":"audio/pcm","rate":16000}: PCM mono de 16 bits com sinal, em ordem little-endian, a 16 kHz.{"type":"audio/pcmu","rate":8000}: G.711 μ-law a 8 kHz, com um byte por amostra.{"type":"audio/pcma","rate":8000}: G.711 A-law a 8 kHz, com um byte por amostra.
Codifique os bytes brutos em Base64, sem cabeçalho WAV ou de outro contêiner. Cada bloco PCM precisa conter amostras completas de 16 bits, portanto seu tamanho em bytes deve ser par. Se sobrar um byte no fim de um bloco de entrada, o exemplo o inclui no início do próximo. Respeitada essa condição, você pode dividir o áudio em blocos em qualquer ponto, desde que mantenha a continuidade e a ordem do fluxo.
Faça a reamostragem do áudio quando a 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 codificados de cada bloco sem aplicar o alinhamento de dois bytes específico do PCM e configure o reprodutor de saída para usar o mesmo codec. Um fluxo G.711 compatível pode ser transmitido sem conversão para PCM. Para conectar uma chamada telefônica, consulte Integrações de telefonia.
Envie e receba eventos
Envie cada evento como uma mensagem de texto em JSON. Essas mensagens transportam o áudio codificado em Base64.
- Envio de áudio: envie
session.input_audio.appendcom os bytes brutos codificados em Base64 no campoaudio. Não há confirmação de recebimento para os blocos de áudio enviados. - Recebimento de áudio: decodifique o campo
deltade cada eventosession.output_audio.deltae coloque o áudio na fila de reprodução, na ordem de recebimento e no formato configurado. - Recebimento de transcrições: acrescente o texto do campo
deltados eventossession.input_transcript.deltaesession.output_transcript.deltaà transcrição correspondente. - Recebimento de eventos do backend: ao usar a delegação para a Responses API, processe o campo
eventcontido em cada enveloperesponse.event. - Tratamento de erros: trate os comandos rejeitados e os erros de sessão informados nos eventos
error. Useerror.client_event_id, quando presente, para identificar o comando.
Acompanhe a reprodução pela fila de áudio do seu aplicativo. A conexão WebSocket principal do GPT-Live envia o áudio de saída sem campos de temporização e sem emitir um evento que indique o fim desse áudio. Use as marcas de tempo da transcrição para organizar as legendas e os eventos do backend para acompanhar as tarefas delegadas.
Enquanto o áudio é transmitido continuamente, o GPT-Live determina quando ouvir e quando falar. Use response.create para iniciar ou continuar uma tarefa delegada ao backend. Consulte Delegação e ferramentas para conhecer esse fluxo.
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 definidos no início da sessão e permanecem fixos. Use session.update para alterar as configurações compatíveis com o modo de delegação atual. As configurações omitidas mantêm seus valores. Quando a atualização é bem-sucedida, a API retorna session.updated com a configuração efetiva da sessão.
Use session.instructions.append para acrescentar 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 as tarefas 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 dados de uso.
Encerre a sessão
Envie session.close quando a conversa terminar. Antes de enviar o comando, registre um listener para session.closed. Continue recebendo eventos até que esse evento chegue e só então libere a conexão. O exemplo aguarda até 15 segundos e informa que o encerramento ficou incompleto se o evento final não chegar.
Guarde os dados finais de uso de voz de session.closed e os eventos de uso do backend já recebidos. Cada atualização da duração de voz informa o total acumulado até aquele momento. Não some esses valores. Se ocorrer uma falha de transporte ou o tempo de espera se esgotar antes de session.closed, os dados finais de uso ficam sem confirmação. Consulte Gerenciamento de sessões para conhecer o ciclo de vida completo.
A API de WebSockets oferece transferência de dados em tempo real, tem amplo suporte e é uma ótima opção para conectar aplicativos à Realtime API da OpenAI em integrações entre servidores. Para clientes em navegadores ou dispositivos móveis, recomendamos a conexão via WebRTC.
Em uma integração entre servidores com a Realtime API, seu backend se conecta diretamente à API via WebSocket. Você pode usar uma chave de API padrão para autenticar a conexão, pois o token ficará disponível apenas no servidor seguro do backend.
Conecte-se via WebSocket
Os exemplos a seguir mostram como se conectar à Realtime API via WebSocket. Além de usar a URL de WebSocket indicada nos exemplos, envie um cabeçalho de autenticação com sua chave de API da OpenAI. Se o seu aplicativo atribui identificadores de segurança, envie no cabeçalho OpenAI-Safety-Identifier o identificador estável que preserva a privacidade do usuário final.
É possível usar WebSocket em navegadores com um token temporário de API, conforme descrito no guia de conexão via WebRTC. Porém, se a conexão partir de um cliente como um navegador ou aplicativo móvel, o WebRTC será uma solução mais robusta na maioria dos casos.
Módulo ws (Node.js)
import WebSocket from "ws";
const url = "wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1";
const ws = new WebSocket(url, {
headers: {
Authorization: "Bearer " + process.env.OPENAI_API_KEY,
"OpenAI-Safety-Identifier": "hashed-user-id",
},
});
let connected = false;
ws.on("message", function incoming(message) {
const event = JSON.parse(message.toString());
if (event.type === "error") throw new Error(event.error.message);
if (event.type === "session.created") {
connected = true;
console.log(`Connected to the Realtime API: ${event.session.id}`);
ws.close(1000);
}
});
ws.on("close", () => {
if (!connected)
throw new Error("Connection closed before the session was created");
});# example requires websocket-client library:
# pip install websocket-client
import os
import json
import websocket
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
url = "wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1"
headers = [
"Authorization: Bearer " + OPENAI_API_KEY,
"OpenAI-Safety-Identifier: hashed-user-id",
]
session_created = False
def on_message(ws, message):
global session_created
data = json.loads(message)
if data["type"] == "session.created":
session_created = True
print("Connected to the Realtime API:", data["session"]["id"])
ws.close()
elif data["type"] == "error":
ws.close()
ws = websocket.WebSocketApp(
url,
header=headers,
on_message=on_message,
)
ws.run_forever()
if not session_created:
raise RuntimeError("Connection closed before the Realtime session was created.")Instale as gems necessárias com
gem install openai async-websocket.
require "openai"
client = OpenAI::Client.new(
default_headers: { "OpenAI-Safety-Identifier" => "hashed-user-id" }
)
client.realtime.connect(model: "gpt-realtime-2.1") do |connection|
created = connection.find do |event|
raise event.error.message if event.is_a?(OpenAI::Realtime::RealtimeErrorEvent)
next unless event.is_a?(OpenAI::Realtime::SessionCreatedEvent)
puts("Connected to the Realtime API: #{event.session[:id]}")
true
end
raise "Connection closed before the session was created" unless created
endUse Java 17 ou posterior com com.openai:openai-java:4.75.1.
import com.openai.client.okhttp.OkHttpClient;
import com.openai.core.ClientOptions;
import com.openai.helpers.RealtimeConnection;
import com.openai.helpers.RealtimeWebSocketOptions;
import com.openai.models.realtime.*;
var http = OkHttpClient.builder().build();
var options =
ClientOptions.builder()
.fromEnv()
.httpClient(http)
.putHeader("OpenAI-Safety-Identifier", "hashed-user-id")
.build();
try (http;
var connection =
RealtimeConnection.connect(
options,
RealtimeWebSocketOptions.builder().model("gpt-realtime-2.1").build())) {
while (true) {
var event = connection.receive();
if (event.error().isPresent())
throw new IllegalStateException(event.error().orElseThrow().toString());
if (event.sessionCreated().isPresent()) {
System.out.println("Connected to server.");
System.out.println(event);
break;
}
}
}Use Go 1.26 ou posterior e instale o SDK com
go get github.com/openai/openai-go/v3@v3.85.1. O SDK gerencia
o transporte de dados pelo socket. Seu aplicativo trata os eventos, captura
e reproduz o áudio e restaura o estado da sessão após uma reconexão.
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
client := openai.NewClient()
conn, err := client.Realtime.Connect(ctx, realtime.RealtimeConnectionOptions{}, option.WithQuery("model", "gpt-realtime-2.1"), option.WithHeader("OpenAI-Safety-Identifier", "hashed-user-id"))
if err != nil {
return err
}
defer conn.Close()Instale o SDK com
dotnet add package OpenAI –version 2.14.0. A Realtime API
usa tipos experimentais do SDK. O exemplo inclui a diretiva necessária
para lidar com o aviso do compilador.
using OpenAI.Realtime;
#pragma warning disable OPENAI002
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
RealtimeClient client = new(key);
RealtimeSessionClientOptions options = new();
options.Headers["OpenAI-Safety-Identifier"] = "hashed-user-id";
using CancellationTokenSource timeout = new(TimeSpan.FromSeconds(30));
using RealtimeSessionClient session = await client.StartConversationSessionAsync("gpt-realtime-2.1", options, cancellationToken: timeout.Token);
await foreach (RealtimeServerUpdate update in session.ReceiveUpdatesAsync(timeout.Token))
{
if (update is RealtimeServerUpdateError error)
throw new InvalidOperationException(error.Error.Message);
if (update is RealtimeServerUpdateSessionCreated)
{
Console.WriteLine("Connected to server.");
Console.WriteLine(System.ClientModel.Primitives.ModelReaderWriter.Write(update));
return;
}
}
throw new InvalidOperationException("Connection closed before session creation.");/*
Note that in client-side environments like web browsers, we recommend
using WebRTC instead. It is possible, however, to use the standard
WebSocket interface in browser-like environments like Deno and
Cloudflare Workers.
*/
const ws = new WebSocket(
"wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1",
[
"realtime",
// Use a short-lived token fetched from your application server.
"openai-insecure-api-key." + OPENAI_REALTIME_EPHEMERAL_KEY,
]
);
ws.addEventListener("open", function open() {
console.log("Connected to server.");
});
ws.addEventListener("message", function incoming(event) {
console.log(event.data);
});Envio e recebimento de eventos
O gerenciamento de sessões da Realtime API combina eventos enviados pelo cliente, que você emite pelo seu código, e eventos enviados pelo servidor, que a Realtime API gera para indicar o que acontece ao longo do ciclo de vida da sessão.
Em uma conexão WebSocket, você envia e recebe eventos serializados em JSON como strings de texto. O exemplo a seguir usa Node.js, e os mesmos princípios se aplicam a outras bibliotecas de WebSocket.
import WebSocket from "ws";
const url = "wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1";
const ws = new WebSocket(url, {
headers: {
Authorization: "Bearer " + process.env.OPENAI_API_KEY,
"OpenAI-Safety-Identifier": "hashed-user-id",
},
});
ws.on("open", function open() {
console.log("Connected to server.");
// Send client events over the WebSocket once connected
ws.send(
JSON.stringify({
type: "session.update",
session: {
type: "realtime",
instructions: "Be extra nice today!",
},
})
);
});
// Listen for and parse server events
ws.on("message", function incoming(message) {
console.log(JSON.parse(message.toString()));
});A interface WebSocket talvez seja a de mais baixo nível disponível para interagir com um modelo Realtime. Ao usá-la, você fica responsável por enviar e processar blocos de áudio codificados em Base64 pela conexão de socket.
Para saber como enviar e receber áudio via WebSockets, consulte o guia de conversas em tempo real.