Stream
WebSocket 기반 실시간 양방향 오디오 스트리밍 프로토콜. G.711 μ-law 오디오 사양, 메시지 형식, 사용 패턴.
개요
VoiceML의 <Connect><Stream> 동사를 사용하면 실시간 양방향 오디오 스트림을 WebSocket으로 연결할 수 있습니다.
AI 에이전트, 실시간 음성 분석, 보이스봇 등에 사용됩니다.
VoiceML 연결 예제
<Response>
<Connect>
<Stream url="wss://your-server.com/stream" track="inbound">
<Parameter name="userId" value="123"/>
</Stream>
</Connect>
</Response>네트워크
Stream 연결은 ClawOps 플랫폼에서 고객의 WebSocket 서버로 발신됩니다. 방화벽 화이트리스트가 필요한 경우 아래 IP를 허용해 주세요.
| 항목 | 값 |
|---|---|
| Source IP | 34.47.65.45/32 |
| 리전 | GCP asia-northeast3 (서울) |
| 프로토콜 | WebSocket (TCP 443) |
고정 IP이며, 변경 시 사전 공지합니다.
오디오 사양
오디오 포맷은 G.711 μ-law입니다. PCM16이 아닙니다. 인코딩/디코딩 시 반드시 μ-law 코덱을 사용하세요.
| 항목 | 값 |
|---|---|
| 인코딩 | G.711 μ-law |
| 샘플레이트 | 8000 Hz |
| 채널 | 1 (mono) |
| 프레임 크기 | 160 bytes (20ms) |
| 전송 형식 | base64 in JSON |
플랫폼 보장 사항
수신 오디오: Asterisk jitter buffer가 네트워크 jitter를 흡수하여 균일한 20ms 간격으로 전달합니다.
송신 오디오: 아무 타이밍으로 보내도 플랫폼이 20ms 간격으로 정규화하여 재생합니다.
SDK에서 pacing이나 jitter buffer를 구현할 필요가 없습니다.
3초간 무음이 지속되면 자동으로 페이싱이 중단됩니다.
서버 → 클라이언트 메시지
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" }
}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" }사용 패턴
기본 오디오 송수신
클라이언트 서버
| |
|<-- 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 오디오 즉시 중단)