# Media Gateway ## Purpose The Media Gateway connects the Go AI Operator to Asterisk audio through `chan_websocket` media channels. ## Why chan_websocket Asterisk 20.16.0 on this server has `chan_websocket` and `res_http_websocket` loaded, and HTTP status exposes `/media/...` as Media over Websocket. This avoids RTP socket handling for the MVP media path. ## Asterisk 20.16.0 Compatibility - Plain-text media control messages are used by default. - JSON control parsing is implemented for future compatibility. - No dependency on `transport_data=f(json)`. - Codec for TZ-04 is `slin16`. - Media WebSocket subprotocol is `media`. ## Runtime Flow ```text Caller calls 7199@from-softphones -> Stasis(ai-operator,test) -> Go ARI Call Manager receives StasisStart -> Answer caller -> Create mixing bridge -> Add caller channel -> Create externalMedia WebSocket channel -> Get MEDIA_WEBSOCKET_CONNECTION_ID -> Go connects to ws://127.0.0.1:8088/media/{connection_id} -> Add media channel to bridge -> Pump caller slin16 audio to VoiceProvider -> Pump VoiceProvider assistant audio deltas back to Asterisk -> Cleanup ``` Production Kazakhtelecom routes remain unchanged. AudioSocket `7100` remains the rollback route. ## CLI Usage Media self-test without real call: ```sh ./bin/ai-operator media-self-test --env /etc/ai-operator/ai-operator.env --duration 3s ``` Controlled test route media mode: ```sh ./bin/ai-operator run --env /etc/ai-operator/ai-operator.env --ari-events --call-control --media --voice-provider openai_realtime --media-test-mode stats --test-call-hangup-after 180s ``` ## Media Test Modes - `stats`: collect media stats and do not synthesize test audio. Real VoiceProvider audio is still forwarded to the caller. - `silence`: send short slin16 silence. - `tone`: send a short low-volume sine tone for controlled testing only. - `echo`: reserved for controlled testing, not a default mode. ## Safety - Production route is disabled. - No audio recording by default. - Raw audio frames are not saved to disk by default. - OpenAI is not called. - Cleanup is designed to be idempotent. ## Troubleshooting - No `MEDIA_START`: verify externalMedia channel creation and `/media/{connection_id}` URL. - Missing `MEDIA_WEBSOCKET_CONNECTION_ID`: retry variable fetch; channel may not be fully initialized yet. - WebSocket 404/401: verify ARI/HTTP localhost binding and credentials. - XOFF stuck: outbound audio pauses until `MEDIA_XON` or context timeout. - Leaked bridge/channel: run `core show channels` and `bridge show all`, then clean up aiop-prefixed resources. ## Voice Provider Integration Media Gateway audio is forwarded to a VoiceProvider in test route mode. Caller audio is resampled from Asterisk `slin16` 16 kHz PCM16 to provider 24 kHz PCM16. Assistant audio deltas are resampled back to 16 kHz PCM16 and sent to Asterisk over the media WebSocket. Default provider is `fake`; OpenAI requires explicit `--voice-provider openai_realtime` and an API key. ## TZ-06 Dialogue Safety Media Gateway remains transport-only. It does not decide business state. Dialogue state and tool permissions are handled by the Dialogue Orchestrator.