실시간 상호작용
Realtime WebSocket으로 실시간 텍스트, 오디오 및 함수 호출을 처리합니다.
OpenAI Realtime은 지속 연결과 양방향 이벤트로 실시간 텍스트, 오디오 및 함수 호출을 처리합니다. 클라이언트는 세션, 오디오 버퍼, 대화 항목 및 응답 제어 이벤트를 보내고 서버는 세션 상태, 전사, 텍스트, 오디오, 함수 인수 및 오류 이벤트를 지속적으로 반환합니다.
이 페이지는 WebSocket을 기본 연결 방식으로 사용합니다. 연결할 때 MODEL_ID를 현재 계정에 표시되며 Realtime을 지원하는 모델 ID로 바꿉니다.
대표적인 사용 사례는 실시간 음성 대화, 회의 실시간 전사 및 음성 어시스턴트, 실시간 번역, 음성 전사, 실시간 코드 상호작용 및 서버 측 실시간 연동입니다. 연결은 텍스트와 오디오를 동시에 전달하며 이벤트를 통해 VAD, 함수 호출 및 상태 업데이트를 처리합니다.
wss://api.agtcloud.cn/v1/realtime?model=MODEL_ID인증 및 연결
WebSocket 인증
서버 애플리케이션은 Bearer API 키로 WSS 연결을 설정하고 핸드셰이크 요청에 Realtime Beta Header를 포함합니다.
| 항목 | 값 |
|---|---|
| 연결 주소 | wss://api.agtcloud.cn/v1/realtime?model=MODEL_ID |
| Authorization | Bearer your-api-key |
| OpenAI-Beta | realtime=v1 |
장기 API 키는 신뢰할 수 있는 서버에서만 사용하고 브라우저, 모바일 패키지 또는 공개 저장소에 넣지 않습니다. 모든 연결에 HTTPS/WSS를 사용해야 합니다.
임시 토큰
클라이언트가 연결할 때 신뢰할 수 있는 서버에서 유효 기간이 1분이며 단일 연결에만 사용할 수 있는 임시 토큰을 먼저 생성할 수 있습니다.
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를 생성하여 Realtime 엔드포인트로 제출하고 SDP Answer를 받은 다음 oai-events 데이터 채널로 JSON 이벤트를 교환합니다.
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 구성에는 임계값, 음성 시작 전 패딩 및 무음 지속 시간이 포함됩니다.
- 대화는 세션, 대화 항목, 내용 부분 및 응답 이벤트가 함께 진행합니다.
구체적인 이벤트 필드는 아래 이벤트 브라우저에서 확인합니다. 공통 매개변수와 값 범위는 “공통 유형”에 모아 두었습니다.
이벤트 Reference
이벤트를 선택하여 필드 정의 및 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 | 아니요 | 단일 응답의 최대 Token 수 | "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 |
WebRTC 구성 매개변수 표3개 필드
| 필드 | 유형 | 필수 | 설명 | 선택 가능한 값 또는 예시 |
|---|---|---|---|---|
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 및 관련 이벤트 정보를 저장한 다음 재전송 여부를 결정합니다.