ClawOps Docs

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 IP34.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

스트림 메타데이터. mediaFormatencodingaudio/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 오디오 즉시 중단)