feat(whatsapp-call): add server-side WebRTC media server for call persistence
Implements a Pion Go B2BUA media server sidecar that sits between Meta's WhatsApp Cloud API and the agent's browser, enabling call persistence across page reloads, server-side recording, multi-participant support, audio injection, and AI integration readiness. Go Media Server (enterprise/media-server/): - Pion WebRTC v4 B2BUA with Peer A (Meta) and Peer B (Agent) connections - Real-time OGG/Opus recording with crash recovery - Audio bridge with multi-peer fan-out and AudioConsumer plugin interface - Audio injection from OGG files with loop support for hold music - Session manager with graceful shutdown and orphaned recording recovery - HTTP API with Bearer token auth, health checks, and metrics Rails Integration: - Whatsapp::MediaServerClient HTTP client for Go sidecar communication - Dual-mode CallService: legacy browser-direct and server-relay paths - Media server callback controller for agent disconnect/recording/terminate - CallRecordingFetchJob: downloads OGG from Go server to ActiveStorage/S3 - CallCleanupJob: sweeps stale ringing and in-progress calls - New endpoints: active, agent_answer, reconnect, join, play_audio - DB migration: media_session_id column with indexes Frontend: - Dual-mode composable auto-detecting legacy vs server-relay - handleAgentOffer() for receiving SDP from media server - useCallReconnection composable for page reload recovery - Removed terminateCallOnUnload in server-relay mode - Simplified outbound call flow in ConversationHeader - New ActionCable event: whatsapp_call.agent_offer Documentation: - Server-side WebRTC architecture spec (1505 lines) - Implementation plan with 119 trackable checklist items - Feature spec, PR breakdown, and relay architecture docs
This commit is contained in:
@@ -110,6 +110,32 @@ services:
|
||||
- 1025:1025
|
||||
- 8025:8025
|
||||
|
||||
media-server:
|
||||
image: chatwoot/media-server:latest
|
||||
build:
|
||||
context: ./enterprise/media-server
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- '4000:4000'
|
||||
- '10000-10100:10000-10100/udp'
|
||||
environment:
|
||||
- AUTH_TOKEN=${MEDIA_SERVER_AUTH_TOKEN:-}
|
||||
- RAILS_CALLBACK_URL=http://rails:3000
|
||||
- RECORDINGS_DIR=/recordings
|
||||
- LOG_LEVEL=info
|
||||
- UDP_PORT_MIN=10000
|
||||
- UDP_PORT_MAX=10100
|
||||
- PUBLIC_IP=${MEDIA_SERVER_PUBLIC_IP:-}
|
||||
- STUN_SERVERS=stun:stun.l.google.com:19302
|
||||
volumes:
|
||||
- media_recordings:/recordings
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ['CMD', 'wget', '--spider', '-q', 'http://localhost:4000/health']
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
volumes:
|
||||
postgres:
|
||||
redis:
|
||||
@@ -117,3 +143,4 @@ volumes:
|
||||
node_modules:
|
||||
cache:
|
||||
bundle:
|
||||
media_recordings:
|
||||
|
||||
Reference in New Issue
Block a user