통화 처리 방식
Stream
WebSocket 기반 실시간 양방향 오디오 스트리밍 프로토콜. G.711 μ-law 오디오 사양, 메시지 형식, 사용 패턴.
개요
VoiceML의 <Connect><Stream> 동사를 사용하면 실시간 양방향 오디오 스트림을 WebSocket으로 연결할 수 있습니다.
AI 에이전트, 실시간 음성 분석, 보이스봇 등에 사용됩니다.
운영 환경 실통화로 검증된 범위는 url (wss://), inbound 트랙, WebSocket 이벤트 connected / start / media / stop /
mark / clear / dtmf(양방향), μ-law 8k 양방향 오디오, <Connect action> 입니다.
동사별 검증 상태는 VoiceML 문서를 참고하세요.
VoiceML 연결 예제
<Response>
<Connect>
<Stream url="wss://your-server.com/stream" track="inbound">
<Parameter name="userId" value="123"/>
</Stream>
</Connect>
</Response>현재 구현은 inbound 트랙(발신자 → 한국AI통신) 오디오만 전달합니다. outbound / both 등의 다른 값은
지원되지 않습니다. AI 응답 등 송신측 오디오는 별도 트랙으로 받지 않으며, 클라이언트가 보낸 오디오를
한국AI통신이 그대로 발신측에 재생합니다.
네트워크
Stream 연결은 한국AI통신 플랫폼에서 고객의 WebSocket 서버로 발신됩니다. 방화벽 화이트리스트가 필요한 경우 네트워크 (IP 허용목록) 에서 허용할 IP를 확인해 주세요.
인증 — Stream WebSocket 자체에는 X-Signature 등의 한국AI통신 측 인증 서명이 적용되지 않습니다.
통화/계정 식별이 필요하면 VoiceML <Stream> 안의 <Parameter> 로 자체 토큰을 넘기거나,
start 메시지의 streamId / callId / accountId 와 미리 알고 있는 통화 정보를 대조해 검증하세요.
공개 엔드포인트는 위 Source IP 화이트리스트와 함께 사용하는 것을 권장합니다.
오디오 사양
오디오 포맷은 G.711 μ-law입니다. PCM16이 아닙니다. 인코딩/디코딩 시 반드시 μ-law 코덱을 사용하세요.
| 항목 | 값 |
|---|---|
| 인코딩 | G.711 μ-law |
| 샘플레이트 | 8000 Hz |
| 채널 | 1 (mono) |
| 프레임 크기 | 160 bytes (20ms) |
| 전송 형식 | base64 in JSON |
플랫폼 보장 사항
수신 오디오: 받은 20ms 프레임을 그대로 media 메시지로 전달합니다.
송신 오디오: 크기·타이밍과 관계없이 보낸 순서대로 20ms 간격으로 재생합니다.
서버 → 클라이언트 메시지
connected
WebSocket 연결 성공.
{
"event": "connected",
"protocol": "Call",
"version": "1.0.0"
}start
스트림 메타데이터. mediaFormat의 encoding이 audio/x-mulaw인 것을 확인하세요.
{
"event": "start",
"sequenceNumber": "1",
"start": {
"streamId": "MZ...",
"callId": "CA...",
"accountId": "AC...",
"tracks": ["inbound"],
"mediaFormat": {
"encoding": "audio/x-mulaw",
"sampleRate": 8000,
"channels": 1
},
"customParameters": { "userId": "123" }
}
}media
수신 오디오 (전화 → 클라이언트). 메시지 하나에 20ms 프레임 하나가 담깁니다.
{
"event": "media",
"sequenceNumber": "3",
"media": {
"track": "inbound",
"chunk": "1",
"timestamp": "5",
"payload": "<base64 G.711 μ-law>"
}
}mark
클라이언트가 보낸 mark의 재생 완료 알림. 해당 mark 이전의 모든 오디오가 재생 완료되었음을 의미합니다.
{
"event": "mark",
"sequenceNumber": "4",
"mark": { "name": "greeting_end" }
}dtmf
발신자가 통화 중 키패드를 누르면 전송됩니다. IVR/메뉴 선택, 본인 인증 코드 입력 등을 처리할 때 사용합니다.
{
"event": "dtmf",
"sequenceNumber": "5",
"dtmf": { "digit": "1", "track": "inbound_track" }
}| 필드 | 설명 |
|---|---|
digit | 입력된 키 (0-9, *, #) |
track | 입력 트랙 식별자 (inbound_track) |
stop
스트림 종료.
{
"event": "stop",
"sequenceNumber": "5",
"stop": { "accountId": "AC...", "callId": "CA..." }
}클라이언트 → 서버 메시지
media
송신 오디오 (클라이언트 → 전화). G.711 μ-law base64로 인코딩하여 전송합니다. 아무 타이밍으로 전송 가능 — 플랫폼이 20ms 간격으로 pacing 처리합니다.
{
"event": "media",
"media": { "payload": "<base64 G.711 μ-law>" }
}mark
오디오 재생 지점에 마커를 삽입합니다. media 전송 후 mark를 보내면, 해당 지점까지 오디오가 재생 완료될 때 서버가 동일한 mark를 돌려보냅니다.
{
"event": "mark",
"mark": { "name": "custom-identifier" }
}clear
송신 오디오 버퍼를 즉시 비웁니다 (barge-in). 대기 중인 mark가 있으면 모두 발화한 후 큐를 비웁니다.
{ "event": "clear" }dtmf
클라이언트가 발신자에게 DTMF 신호를 전송합니다. ARS 메뉴 탐색, 내선번호 입력 등 발신자 측 으로 키 톤을 보낼 때 사용합니다.
{
"event": "dtmf",
"dtmf": { "digit": "1" }
}| 필드 | 설명 |
|---|---|
digit | 보낼 키 (0-9, *, #) |
사용 패턴
기본 오디오 송수신
클라이언트 서버
| |
|<-- connected ----------------|
|<-- start --------------------|
|<-- media (수신 오디오) -------| (20ms 프레임)
|--- media (송신 오디오) ------>| (아무 타이밍 OK)
|<-- media --------------------|
| ... |
|<-- stop ---------------------|Mark 기반 재생 추적
클라이언트 서버
| |
|--- media (TTS 청크 1) ------>|
|--- media (TTS 청크 2) ------>|
|--- mark("greeting") -------->| (greeting 끝 지점에 마커)
|--- media (TTS 청크 3) ------>|
|--- mark("question") -------->|
| ... |
|<-- mark("greeting") ---------| (greeting까지 재생 완료)
| ... |
|<-- mark("question") ---------| (question까지 재생 완료)Barge-in (clear)
클라이언트 서버
| |
|--- media (TTS 응답) -------->|
|--- media (TTS 응답) -------->|
|--- mark("response") -------->|
|--- media (TTS 응답) -------->|
| | (사용자가 말하기 시작)
|--- clear ------------------->| (버퍼 비움 요청)
|<-- mark("response") ---------| (대기 중이던 mark 발화)
| | (남은 TTS 오디오 즉시 중단)