Взаимодействие в реальном времени
Обрабатывайте текст, аудио и вызовы функций в реальном времени через Realtime WebSocket.
OpenAI Realtime использует постоянное соединение и двунаправленные события для работы с текстом, аудио и вызовами функций в реальном времени. Клиент отправляет события сеанса, аудиобуфера, элементов диалога и управления ответами, а сервер непрерывно возвращает состояния сеанса, транскрипции, текст, аудио, аргументы функций и события ошибок.
Основной способ подключения на этой странице — WebSocket. При подключении замените MODEL_ID на ID модели, видимой текущему аккаунту и поддерживающей Realtime.
Типичные сценарии включают голосовой диалог в реальном времени, транскрипцию встреч и голосовых ассистентов, перевод и транскрипцию речи, интерактивную работу с кодом и серверные интеграции в реальном времени. Соединение может одновременно передавать текст и аудио, обрабатывая VAD, вызовы функций и обновления состояния через события.
wss://api.agtcloud.cn/v1/realtime?model=MODEL_IDАутентификация и подключение
Аутентификация WebSocket
Серверное приложение устанавливает соединение WSS с помощью Bearer-ключа API и передаёт Header Realtime Beta в запросе рукопожатия.
| Параметр | Значение |
|---|---|
| Адрес подключения | wss://api.agtcloud.cn/v1/realtime?model=MODEL_ID |
| Authorization | Bearer your-api-key |
| OpenAI-Beta | realtime=v1 |
Долгосрочный ключ API следует использовать только на доверенном сервере. Не добавляйте его в браузерный код, мобильный пакет или публичный репозиторий. Все соединения должны использовать HTTPS/WSS.
Временный токен
Перед подключением клиента доверенный сервер может создать временный токен со сроком действия в одну минуту, предназначенный только для одного соединения.
POST https://api.agtcloud.cn/v1/realtime/sessions
Content-Type: application/json
Authorization: Bearer your-api-key
{
"model": "MODEL_ID",
"voice": "verse"
}Процесс подключения
В основном процессе WebSocket сервер устанавливает соединение непосредственно с ключом API. После успешного рукопожатия по этому соединению отправляются клиентские события и принимаются серверные.
В процессе WebRTC клиент сначала запрашивает временный токен у сервера своего приложения, который создаёт его через интерфейс сеансов. Затем клиент создаёт SDP Offer, отправляет его на Endpoint Realtime и получает SDP Answer, после чего обменивается событиями JSON по каналу данных oai-events.
Примеры подключения WebSocket
Следующие примеры показывают Node.js, Python, отправку и получение событий. После подключения клиент отправляет события JSON, а сервер непрерывно возвращает результаты также в виде событий JSON.
import WebSocket from 'ws';
const ws = new WebSocket('wss://api.agtcloud.cn/v1/realtime?model=MODEL_ID', {
headers: {
Authorization: 'Bearer your-api-key',
'OpenAI-Beta': 'realtime=v1',
},
});
ws.on('open', () => {
console.log('Соединение с сервером установлено.');
});
ws.on('message', (message) => {
console.log(JSON.parse(message.toString()));
});Подключение WebRTC
Сейчас рекомендуется WebSocket. Перед использованием WebRTC проверьте его поддержку целевой моделью. Следующие примеры показывают базовую структуру подключения с временным токеном, SDP, аудиодорожкой и каналом данных.
Адрес подключения WebRTC — https://api.agtcloud.cn/v1/realtime?model=MODEL_ID. Клиент отправляет application/sdp с временным токеном. Канал данных называется oai-events, формат событий — JSON. Входное аудио отправляется через addTrack(), выходное принимается через ontrack.
Браузерный клиент и обмен SDP
async function init() {
const tokenResponse = await fetch('/session');
const data = await tokenResponse.json();
const ephemeralKey = data.client_secret.value;
const pc = new RTCPeerConnection();
const audioElement = document.createElement('audio');
audioElement.autoplay = true;
pc.ontrack = (event) => {
audioElement.srcObject = event.streams[0];
};
const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
pc.addTrack(mediaStream.getTracks()[0]);
const dataChannel = pc.createDataChannel('oai-events');
dataChannel.addEventListener('message', (event) => {
console.log(JSON.parse(event.data));
});
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const response = await fetch(
'https://api.agtcloud.cn/v1/realtime?model=MODEL_ID',
{
method: 'POST',
body: offer.sdp,
headers: {
Authorization: `Bearer ${ephemeralKey}`,
'Content-Type': 'application/sdp',
},
},
);
await pc.setRemoteDescription({
type: 'answer',
sdp: await response.text(),
});
}
init();Создание временного токена на сервере
import express from 'express';
const app = express();
app.get('/session', async (_request, response) => {
const result = await fetch('https://api.agtcloud.cn/v1/realtime/sessions', {
method: 'POST',
headers: {
Authorization: 'Bearer your-api-key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'MODEL_ID',
voice: 'verse',
}),
});
response.send(await result.json());
});
app.listen(3000);Отправка и получение событий по каналу данных
const dataChannel = pc.createDataChannel('oai-events');
dataChannel.addEventListener('message', (event) => {
const realtimeEvent = JSON.parse(event.data);
console.log(realtimeEvent);
});
dataChannel.send(JSON.stringify({
type: 'response.create',
response: {
modalities: ['text'],
instructions: 'Напишите хайку о коде',
},
}));Пример стандартного WebSocket в среде, подобной браузеру
Среды, подобные браузеру, например Deno и Cloudflare Workers, могут передавать данные аутентификации через подпротоколы. Перед использованием проверьте поддержку текущей средой и узлом. Размещать долгосрочный ключ API на обычной браузерной странице не рекомендуется.
const ws = new WebSocket(
'wss://api.agtcloud.cn/v1/realtime?model=MODEL_ID',
[
'realtime',
'openai-insecure-api-key.your-api-key',
'openai-organization.ORGANIZATION_ID',
'openai-project.PROJECT_ID',
'openai-beta.realtime-v1',
],
);
ws.addEventListener('open', () => {
console.log('Соединение с сервером установлено.');
});
ws.addEventListener('message', (event) => {
console.log(JSON.parse(event.data));
});Сеансы, аудио и диалоги
Realtime поддерживает текстовые, голосовые и смешанные текстово-аудиодиалоги. Конфигурация сеанса может включать форматы входного и выходного аудио, голос, температуру, максимальную длину вывода, инструменты и параметры VAD.
- Форматы входного и выходного аудио:
pcm16,g711_ulaw,g711_alaw. - Примеры вариантов голоса:
alloy,echo,shimmer. - Конфигурация VAD включает порог, аудиопрефикс перед речью и длительность тишины.
- Диалог развивается через сеанс, элементы диалога, части содержимого и события ответов.
Поля отдельных событий доступны в браузере событий ниже; общие параметры и допустимые значения собраны в разделе «Общие типы».
Справочник событий
Выберите событие, чтобы увидеть определения полей и пример JSON. Можно менять направление событий, фильтровать по категории или искать по названию события.
session.update
Обновляет конфигурацию сеанса по умолчанию.
| Поле | Тип | Обязательно | Описание | Пример |
|---|---|---|---|---|
event_id | string | Нет | Идентификатор события, созданный клиентом | event_123 |
type | string | Нет | Тип события | session.update |
modalities | string[] | Нет | Модальности, в которых модель может отвечать | ["text", "audio"] |
instructions | string | Нет | Системные инструкции, добавляемые перед вызовом модели | "Отвечайте кратко и точно." |
voice | string | Нет | Голос, используемый моделью | alloy, echo, shimmer |
input_audio_format | string | Нет | Формат входного аудио | pcm16, g711_ulaw, g711_alaw |
output_audio_format | string | Нет | Формат выходного аудио | pcm16, g711_ulaw, g711_alaw |
input_audio_transcription.model | string | Нет | Модель для транскрипции | whisper-1 |
turn_detection.type | string | Нет | Тип обнаружения речи | server_vad |
turn_detection.threshold | number | Нет | Порог активации VAD (0.0-1.0) | 0.8 |
turn_detection.prefix_padding_ms | integer | Нет | Длительность аудио, включаемого перед началом речи | 500 |
turn_detection.silence_duration_ms | integer | Нет | Длительность тишины для обнаружения окончания речи | 1000 |
tools | array | Нет | Список инструментов, доступных модели | [] |
tool_choice | string | Нет | Способ выбора инструментов моделью | auto/none/required |
temperature | number | Нет | Температура сэмплирования модели | 0.8 |
max_output_tokens | string or integer | Нет | Максимальное число Tokens в одном ответе | "inf"/4096 |
{
"event_id": "event_123",
"type": "session.update",
"modalities": [
"text",
"audio"
],
"instructions": "Отвечайте кратко и точно.",
"voice": "alloy, echo, shimmer",
"input_audio_format": "pcm16, g711_ulaw, g711_alaw",
"output_audio_format": "pcm16, g711_ulaw, g711_alaw",
"input_audio_transcription": {
"model": "whisper-1"
},
"turn_detection": {
"type": "server_vad",
"threshold": 0.8,
"prefix_padding_ms": 500,
"silence_duration_ms": 1000
},
"tools": [],
"tool_choice": "auto",
"temperature": 0.8,
"max_output_tokens": "inf"
}Общие типы
В следующих раскрываемых разделах собраны таблицы параметров лимитов частоты, вызовов функций, аудио, VAD, инструментов, моделей, событий, сеансов, элементов диалога, содержимого, ответов, транскрипции, аудиопотоков и WebRTC.
Параметры событий лимитов частоты4 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
name | string | Да | Название лимита | Пример: requests_per_min |
limit | integer | Да | Значение лимита | Пример: 60 |
remaining | integer | Да | Оставшаяся доступная квота | Пример: 45 |
reset_seconds | integer | Да | Время до сброса (секунды) | Пример: 35 |
Параметры вызова функции4 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
type | string | Да | Тип функции | Пример: function |
name | string | Да | Название функции | Пример: get_weather |
description | string | Нет | Описание функции | Пример: Получить текущую погоду |
parameters | object | Да | Определение аргументов функции | Пример: {"type": "object", "properties": {...}} |
Параметры формата аудио4 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
sample_rate | integer | — | Частота дискретизации | Допустимые значения: 8000, 16000, 24000, 44100, 48000 |
channels | integer | — | Число каналов | Допустимые значения: 1 (моно), 2 (стерео) |
bits_per_sample | integer | — | Разрядность сэмплов | Допустимые значения: 16 (pcm16), 8 (g711) |
encoding | string | — | Кодирование | Допустимые значения: pcm16, g711_ulaw, g711_alaw |
Параметры обнаружения речи3 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
threshold | number | — | Порог активации VAD | По умолчанию: 0.5; диапазон: 0.0-1.0 |
prefix_padding_ms | integer | — | Аудиопрефикс перед речью (миллисекунды) | По умолчанию: 500; диапазон: 0-5000 |
silence_duration_ms | integer | — | Длительность обнаружения тишины (миллисекунды) | По умолчанию: 1000; диапазон: 100-10000 |
Параметры выбора инструментов2 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
tool_choice | string | — | Способ выбора инструментов | Допустимые значения: auto, none, required |
tools | array | — | Список доступных инструментов | Допустимые значения: [{type, name, description, parameters}] |
Параметры конфигурации модели4 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
temperature | number | — | Температура сэмплирования | Диапазон/допустимые значения: 0.0-2.0; по умолчанию: 1.0 |
max_output_tokens | integer or string | — | Максимальная длина вывода | Диапазон/допустимые значения: 1-4096/"inf"; по умолчанию: "inf" |
modalities | string[] | — | Модальности ответа | Диапазон/допустимые значения: ["text", "audio"]; по умолчанию: ["text"] |
voice | string | — | Голос | Диапазон/допустимые значения: alloy, echo, shimmer; по умолчанию: alloy |
Общие параметры событий3 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
event_id | string | Да | Уникальный идентификатор события | Пример: event_123 |
type | string | Да | Тип события | Пример: session.update |
timestamp | integer | Нет | Временная метка события (миллисекунды) | Пример: 1677649363000 |
Параметры состояния сеанса3 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
status | string | — | Состояние сеанса | Допустимые значения: active, ended, error |
error | object | — | Сведения об ошибке | Допустимые значения: {"type": "error_type", "message": "сообщение об ошибке"} |
metadata | object | — | Метаданные сеанса | Допустимые значения: {"client_id": "web", "session_type": "chat"} |
Параметры состояния элементов диалога3 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
status | string | — | Состояние элемента диалога | Допустимые значения: completed, in_progress, incomplete |
role | string | — | Роль отправителя | Допустимые значения: user, assistant, system |
type | string | — | Тип элемента диалога | Допустимые значения: message, function_call, function_call_output |
Параметры типа содержимого3 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
type | string | — | Тип содержимого | Допустимые значения: text, audio, transcript |
format | string | — | Формат содержимого | Допустимые значения: plain, markdown, html |
encoding | string | — | Кодирование | Допустимые значения: utf-8, base64 |
Параметры состояния ответа3 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
status | string | — | Состояние ответа | Допустимые значения: completed, cancelled, failed, incomplete |
status_details | object | — | Сведения о состоянии | Допустимые значения: {"reason": "user_cancelled"} |
usage | object | — | Статистика использования | Допустимые значения: {"total_tokens": 50, "input_tokens": 20, "output_tokens": 30} |
Параметры транскрипции аудио4 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
enabled | boolean | — | Включена ли транскрипция | Пример: true |
model | string | — | Модель транскрипции | Пример: whisper-1 |
language | string | — | Язык транскрипции | Пример: en, zh, auto |
prompt | string | — | Подсказка для транскрипции | Пример: "Транскрипция разговора" |
Параметры аудиопотока3 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
chunk_size | integer | — | Размер аудиоблока (байты) | Допустимые значения: 1024, 2048, 4096 |
latency | string | — | Режим задержки | Допустимые значения: low, balanced, high |
compression | string | — | Сжатие | Допустимые значения: none, opus, mp3 |
Параметры конфигурации WebRTC3 поля
| Поле | Тип | Обязательно | Описание | Варианты или пример |
|---|---|---|---|---|
ice_servers | array | — | Список серверов ICE | По умолчанию: [{"urls": "stun:stun.l.google.com:19302"}] |
audio_constraints | object | — | Ограничения аудио | По умолчанию: {"echoCancellation": true} |
connection_timeout | integer | — | Тайм-аут подключения (миллисекунды) | По умолчанию: 30000 |
Обработка ошибок и восстановление
Ошибки Realtime обычно связаны с четырьмя категориями проблем: подключением, аутентификацией, аудио или сеансом:
| Тип | Частые причины | Действия |
|---|---|---|
| Ошибка подключения | Сбой сети, неудачное рукопожатие или неверная конфигурация подключения | Проверьте адрес WSS, сеть и запрос рукопожатия; ограничьте число повторных подключений |
| Ошибка аутентификации | Ключ API недействителен, временный токен истёк или не соответствует адресу API | Обновите учётные данные и проверьте соответствие ключа API адресу API в запросе |
| Ошибка аудио | Права доступа к устройству, неподдерживаемый формат или несовместимый кодек | Проверьте разрешения устройства, частоту дискретизации и кодирование, затем восстановите аудиоканал |
| Ошибка сеанса | Тайм-аут сеанса, ограничение параллельности или несогласованное состояние событий | Сохраните событие ошибки и создайте сеанс заново; при необходимости перейдите на интерфейс без работы в реальном времени |
Стратегии восстановления могут включать автоматическое переподключение, восстановление сеанса, ограниченные повторные попытки и переход к упрощённой функциональности. При ошибке сначала прочитайте событие error, сохраните event_id, error.type, error.code, error.message и сведения о связанном событии, а затем решайте, нужна ли повторная отправка.