Перейти к основному содержимому

Realtime

WSS wss://test.kailin.com.cn/v1/realtime

Голосовое общение в реальном времени на основе WebSocket (протокол OpenAI Realtime) — создано для голосовых ассистентов, синхронного перевода и других сценариев с низкой задержкой.

Подключение​

Название модели передаётся в строке запроса; аутентификация такая же, как у HTTP-эндпоинтов:

wss://test.kailin.com.cn/v1/realtime?model=gpt-4o-realtime-preview
const ws = new WebSocket(
'wss://test.kailin.com.cn/v1/realtime?model=gpt-4o-realtime-preview',
{
headers: {
Authorization: 'Bearer sk-your-token',
'OpenAI-Beta': 'realtime=v1',
},
}
);
Примечание

Браузерный new WebSocket не позволяет задавать пользовательские заголовки. Либо передайте токен через параметры субпротокола, либо проксируйте WebSocket через собственный бэкенд (рекомендуется — токен не попадает на фронтенд).

Формат сообщений​

Все сообщения — текстовые кадры JSON с полем type.

Настройка сессии​

После подключения сервер отправляет session.created. Клиенты обычно сначала отправляют session.update, чтобы настроить голос и детекцию реплик:

{
"type": "session.update",
"session": {
"instructions": "You are a voice assistant. Keep answers short.",
"voice": "alloy",
"input_audio_format": "pcm16",
"output_audio_format": "pcm16",
"input_audio_transcription": { "model": "whisper-1" },
"turn_detection": { "type": "server_vad" }
}
}

Отправка пользовательского аудио​

Аудио отправляется фрагментами в виде Base64-кодированного PCM16 (24 кГц, моно):

{ "type": "input_audio_buffer.append", "audio": "<base64 pcm16>" }
{ "type": "input_audio_buffer.commit" }

При включённом server_vad сервер сам определяет конец речи и выполняет фиксацию автоматически — вручную вызывать commit не нужно.

Запуск ответа​

{
"type": "response.create",
"response": { "modalities": ["text", "audio"], "instructions": "Be enthusiastic." }
}

События сервера​

СобытиеОписание
session.created / session.updatedСессия создана / конфигурация применена
input_audio_buffer.speech_started / _stoppedVAD обнаружил начало / конец речи
input_audio_buffer.committedАудиобуфер зафиксирован
conversation.item.createdСоздан элемент диалога
response.audio_transcript.delta / _doneДельта / завершение транскрипта ответа
response.audio.delta / _doneДельта аудио ответа (Base64 PCM16)
response.text.delta / _doneДельта текстового ответа (только текст)
response.doneТекущий ответ завершён
errorСобытие ошибки

Полный пример последовательности​

const ws = new WebSocket(url);

ws.onopen = () => {
ws.send(JSON.stringify({
type: 'session.update',
session: { voice: 'alloy', turn_detection: { type: 'server_vad' } },
}));
// send an audio chunk…
ws.send(JSON.stringify({
type: 'input_audio_buffer.append',
audio: btoa(String.fromCharCode(...pcmChunk)),
}));
};

ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
switch (msg.type) {
case 'response.audio.delta':
playPcmChunk(atob(msg.delta));
break;
case 'response.audio_transcript.delta':
appendSubtitle(msg.delta);
break;
case 'response.done':
console.log('turn finished', msg.response.usage);
break;
}
};
Осторожно

Realtime-эндпоинты тарифицируются по длительности аудио и обходятся заметно дороже текста. Во время тестирования следите за длительностью сессии. Доступность зависит от моделей, настроенных в вашем канале.