이벤트·세션 제어¶
클라이언트 제어 이벤트는 WebRTC 데이터채널 oai-events의 JSON 메시지로 오갑니다. 오디오는
데이터채널의 base64 payload가 아니라 RTP 트랙을 사용합니다. Gateway는 데이터채널이 열리기 전에
발생한 서버 이벤트를 제한된 큐에 보관한 뒤 open 시 순서대로 전송합니다.
클라이언트 → Gateway → /sohri¶
| 클라이언트 이벤트 | 백엔드 동작 |
|---|---|
session.update |
언어·EPD·DM 파라미터 또는 conversation engine을 검증·전달하고 session.updated 회신 |
conversation.item.create |
input_text를 text{message}로 전달 |
response.create |
최초 선인사 또는 현재 자동 DM lifecycle과 연결; OpenAI 엔진이면 realtime_event로 전달 |
response.cancel / cancel_response |
백엔드에 cancel_response, 로컬 playout 취소 |
output_audio_buffer.clear |
대기 playout 무효화 후 output_audio_buffer.cleared 회신 |
input_audio_buffer.* |
무해하게 폐기; 실제 입력은 RTP→PCM 경로 |
지원하지 않는 타입과 내용 없는 입력은 연결을 끊지 않고 무해하게 폐기할 수 있습니다. 단, JSON
구문 오류·파라미터 충돌·범위 오류는 데이터채널 error로 알려 줍니다.
/sohri → Gateway → 클라이언트¶
백엔드는 표준 봉투 {type,data,timestamp}, 클래스명 봉투, top-level raw event를 혼용합니다.
Gateway가 이를 정규화한 뒤 다음 핵심 이벤트를 변환합니다.
/sohri 이벤트 |
데이터채널 이벤트 |
|---|---|
connection_established |
session.created |
speech_candidate[_cancelled] |
sohri.speech_candidate[_cancelled] |
speech_started 계열 |
input_audio_buffer.speech_started |
stop_recording 계열 |
input_audio_buffer.speech_stopped |
stt_result |
conversation.item.input_audio_transcription.completed |
dm_processing |
response.created |
dialog_response |
transcript delta/done과 response.done lifecycle |
dialog_text |
첫 가청 TTS 시점의 sohri.dialog_text |
dm_scenario_updated |
적용값을 담은 session.updated |
conversation_session_updated |
엔진 ACK를 담은 session.updated |
realtime_event{event} |
내장 provider 이벤트를 원형 전달 |
| 분석·대화 완료 | sohri.analysis.*, sohri.dialog_complete |
| 오류 계열 | OpenAI 형태의 error |
전체 필드와 커스텀 이벤트는 엔드포인트·이벤트 참조를 확인하세요.
session.update와 엔진 선택¶
권장 확장 위치는 session.sohri입니다.
{
"type": "session.update",
"session": {
"sohri": {
"conversationEngine": "openai_realtime",
"instructions": "간결하게 답하세요.",
"externalUser": {"id": "user-42"}
}
}
}
현재 통합 브랜치의 엔진 상태 전이는 다음과 같습니다.
- 미지정 엔진은
sohri입니다. openai_realtime선택 시 Gateway가conversation_session_update를 WSS로 보냅니다.- 백엔드의
conversation_session_updatedACK 뒤에만 runtime을 활성화합니다. - 초기 ACK 대기 중
session.update는 최신 snapshot으로 병합되고response.create는 마지막 하나만 보류됩니다. - 최초 설정 실패·timeout·ACK 불일치는 오류 후 세션 종료입니다. ready 이후 재설정 실패는 마지막 승인 snapshot으로 복구해 통화를 유지합니다.
- 세션이 시작된 뒤 엔진을 다른 값으로 바꿀 수 없습니다.
instructions는 session.sohri.instructions 또는 top-level sohri.instructions에서만 받으며
12,000 UTF-16 code unit 이하입니다. OpenAI 표준 session.instructions나 URL 쿼리는 이 값의
입력 경로가 아닙니다. openai_realtime은 DM scenario, botFirst, SOHRI TTS 선택 파라미터와
동시에 사용할 수 없습니다.
SOHRI 응답 lifecycle¶
Gateway는 backend 이벤트에 응답 ID를 부여해 response.created, transcript, TTS stream,
response.done을 상관시킵니다. 사용자 텍스트 후에는 socket-backend가 자동으로 DM 응답을
시작하므로 추가 response.create가 새 선인사를 만들지 않습니다. response.cancel은 활성
응답과 현재 playout을 함께 취소하며 terminal 이벤트가 오지 않을 때를 위한 제한된 fallback이
있습니다.
dm_scenario_update의 scenarioGraph는 DataChannel message 상한과 backend WSS 64 KB 계약을
넘지 않아야 합니다. 병합 결과가 상한을 넘으면 상태를 적용하거나 WSS로 보내지 않고
scenario_graph_too_large 오류를 돌려줍니다.
OpenAI 엔진 패스스루¶
OpenAI 엔진에서도 Gateway가 공급자에 직접 연결하지 않습니다. socket-backend가 provider WebSocket을 소유하고 다음을 중계합니다.
- JSON:
realtime_event{event}↔oai-events - 오디오:
tts_stream_start와 raw PCM ↔ 공통 Opus playout - 중단:
realtime_playback_interrupt→ 로컬 재생 취소 →realtime_playback_truncated{itemId,audioEndMs}
audioEndMs는 가청 샘플만 센 값이 아니라 무음을 포함해 실제 트랙에 기록한 재생 timeline입니다.