Files
ai-podcast/docs/plans/2026-02-05-signalwire-callers-design.md
tcpsyn 356bf145b8 Add show improvement features: crossfade, emotions, returning callers, transcripts, screening
- Music crossfade: smooth 3-second blend between tracks instead of hard stop/start
- Emotional detection: analyze host mood from recent messages so callers adapt tone
- AI caller summaries: generate call summaries with timestamps for show history
- Returning callers: persist regular callers across sessions with call history
- Session export: generate transcripts with speaker labels and chapter markers
- Caller screening: AI pre-screens phone callers to get name and topic while queued

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 02:43:01 -07:00

53 lines
2.0 KiB
Markdown

# SignalWire Phone Call-In Design
## Goal
Replace browser-based WebSocket call-in with real phone calls via SignalWire. Callers dial 208-439-5853 and enter the show queue.
## Architecture
SignalWire handles PSTN connectivity. When a call comes in, SignalWire hits our webhook, we return XML telling it to open a bidirectional WebSocket stream with L16@16kHz audio. The audio flows through our existing pipeline — same queue, channel allocation, transcription, host mic streaming, and TTS streaming.
## Call Flow
1. Caller dials 208-439-5853
2. SignalWire hits `POST /api/signalwire/voice` (via Cloudflare tunnel)
3. We return `<Connect><Stream codec="L16@16000h">` XML
4. SignalWire opens WebSocket to `/api/signalwire/stream`
5. Caller enters queue — host sees phone number on dashboard
6. Host takes call — audio flows bidirectionally
7. Host hangs up — we call SignalWire REST API to end the phone call
## Audio Path
```
Phone → PSTN → SignalWire → WebSocket (base64 L16 JSON) → Our server
Our server → WebSocket (base64 L16 JSON) → SignalWire → PSTN → Phone
```
## SignalWire WebSocket Protocol
Incoming: `{"event": "media", "media": {"payload": "<base64 L16 PCM 16kHz>"}}`
Outgoing: `{"event": "media", "media": {"payload": "<base64 L16 PCM 16kHz>"}}`
Start: `{"event": "start", "start": {"streamSid": "...", "callSid": "..."}}`
Stop: `{"event": "stop"}`
## What Changes
- Remove: browser call-in page, browser WebSocket handler
- Add: SignalWire webhook + WebSocket handler, hangup via REST API
- Modify: CallerService (name→phone, base64 JSON encoding for send), dashboard (show phone number)
- Unchanged: AudioService, queue logic, transcription, TTS streaming, three-way calls
## Config
```
SIGNALWIRE_PROJECT_ID=8eb54732-ade3-4487-8b40-ecd2cd680df7
SIGNALWIRE_SPACE=macneil-media-group-llc.signalwire.com
SIGNALWIRE_TOKEN=PT9c9b61f44ee49914c614fed32aa5c3d7b9372b5199d81dec
SIGNALWIRE_PHONE=+12084395853
```
Webhook URL: `https://radioshow.macneilmediagroup.com/api/signalwire/voice`
No SDK needed — httpx for the one REST call (hangup).