Thanks — this is clear and helpful. I’ll answer both parts: whether to pass 48 kHz vs 24 kHz to Deepgram, and a detailed approach to capture raw RTP or publish a preserved-rate stream so you can retain 8 kHz / 48 kHz audio.
Part 1 — Deepgram: 48 kHz vs 24 kHz
• What matters most: matching the audio sample rate you send to Deepgram to the sample rate of the audio actually being processed by your pipeline. If the audio arriving at Deepgram is 24 kHz (because LiveKit Agents resampled to 24 kHz), telling Deepgram the audio is 48 kHz can hurt recognition and processing quality. Conversely, if the audio reaching Deepgram truly is 48 kHz, you should send 48 kHz.
• Recommendation:
◦ Verify the actual sample rate of the audio you send to Deepgram. If your Agent logs show 24 kHz and that same stream is what you forward to Deepgram, switch to 24 kHz when calling Deepgram.
◦ If you can preserve the original 48 kHz upstream and forward that, keep Deepgram at 48 kHz.
◦ If your incoming sources vary (8 kHz telephony and 48 kHz Opus), normalize what Deepgram receives: for telephony voice, 8 kHz or 16 kHz is typical; for wideband speech (48 kHz source downsampled to 24 kHz by Agents), use 24 kHz.
• Practical test: run an A/B test — send identical segments labeled as 48 kHz vs 24 kHz (matching the actual stream) and compare recognition accuracy and latency. If Agents are resampling to 24 kHz, you’ll likely see improved results by passing 24 kHz.
Part 2 — How to capture raw RTP or publish a preserved-rate stream (detailed approach) Goal: keep an unmodified copy of the incoming SIP audio (8 kHz or 48 kHz) so you can:
• Send true-native-rate audio to ASR/analytics, or
• Keep original-quality recordings separate from the Agent-processed stream.
High-level options (choose one based on architecture and constraints)
• Option A — Capture raw RTP at the SIP gateway (recommended if you control SIP ingress).
• Option B — Duplicate the RTP stream before it enters Agent processing and publish the duplicate into the LiveKit room without Agent resampling.
• Option C — Record or store raw audio at the SIP side (file or RTP dump) for later processing.
Detailed steps for each option
1) Option A — Capture raw RTP at the SIP gateway 1.1 Setup
• On the server that terminates the SIP call (your SIP gateway or the Twilio Media Stream endpoint), enable raw audio capture. This can be:
◦ An RTP dump (pcap) of the RTP stream, or
◦ A raw PCM/WAV write-out from the media processing layer (before any conversion).
1.2 Implementation notes
• For G.711 (PCMA/PCMU at 8 kHz), capture the decoded PCM rather than relying on downstream resampling.
• For Opus (48 kHz), capture decoded PCM at 48 kHz.
1.3 Forwarding to ASR
• Stream the captured PCM to Deepgram (or another ASR) with the sample rate matching the captured PCM (8 kHz for G.711, 48 kHz for Opus).
• If you need a real-time stream, implement a small producer that reads captured audio frames and forwards them via your Deepgram streaming client, ensuring the sample_rate in Deepgram metadata matches the frames.
2) Option B — Duplicate/passthrough stream into LiveKit without Agent processing 2.1 Goal
• Publish a second track into the same LiveKit room that preserves the original sample rate, while letting Agents keep their normalized track for VAD/STT.
2.2 Approach
• Create a separate RTP-to-WebRTC bridge or media forwarder that:
◦ Receives RTP from Twilio.
◦ Decodes or repacketizes as needed but preserves the native PCM sampling rate.
◦ Publishes that media as a new participant/track into LiveKit (using the Python SDK or a WebRTC publisher) with explicit encoding parameters that preserve sample rate where possible.
2.3 Implementation sketch
• On the ingest server:
◦ Terminate Twilio SIP RTP.
◦ Decode to PCM (preserve 8 kHz or 48 kHz).
◦ Use a WebRTC client library (or LiveKit publisher) to create a publisher connection and publish an audio track built from the PCM capture.
◦ Ensure your publisher does not apply any resampling or processing; publish raw PCM frames matching their native rate.
• Downstream consumers (recorders, analytics) subscribe to that preserved track instead of, or in addition to, the normalized Agent track.
3) Option C — Record/store raw audio at ingest for offline processing 3.1 Implementation
• Write the decoded PCM into files named/segmented by call ID and timestamp.
• Store with metadata (call SID, codec, original sample rate).
• For ASR, either:
◦ Batch-send the file with its correct sample rate to Deepgram, or
◦ Stream it as if live by reading back frames to Deepgram’s streaming API.
3.2 When to use
• Use when real-time ASR is not required or you only need perfect-quality transcriptions for post-call analysis.
Practical considerations and tips
• Metadata: Always tag preserved files/streams with call SID, codec, and original sample rate.
• Sync: If you publish both normalized Agent tracks and preserved tracks, ensure subscribers know which track to use for STT vs. playback.
• Bandwidth: Publishing two live tracks increases bandwidth/CPU; consider only publishing preserved stream when needed.
• Format conversion: If you decode Opus to PCM at 48 kHz, avoid re-encoding to a lower sample rate before forwarding to your ASR unless required.
• Deepgram config: When streaming to Deepgram, set the sample_rate parameter to the sample rate of the frames you send. If you send PCM frames at 24 kHz, use 24000; if 48 kHz, use 48000; if 8 kHz, use 8000.
Example flow (recommended if you control ingest)
1. Twilio SIP -> your SIP termination server.
2. On termination server:
◦ Duplicate stream: one copy -> LiveKit Agent (normal pipeline), second copy -> PCM capture & publisher.
1. Publisher -> LiveKit room as participant "preserved-{callSid}" with preserved sample rate track.
2. Deepgram -> consume preserved track (streaming API) with matching sample_rate, or process recorded preserved files offline.
Next steps I can help with
• Give you a concrete code example in Python showing how to publish PCM frames into LiveKit as a second audio track (I can provide a sample using the LiveKit Python SDK and a small PCM frame producer).
• Help craft the Deepgram streaming metadata payload you should use for 8k/24k/48k frames.
• Walk through a specific RTP-capture setup for Twilio (if you tell me whether you terminate SIP on your infrastructure or rely fully on Twilio).
Which of the next steps would you like: a Python publisher code sample for preserving/publishing PCM into LiveKit, or the Deepgram metadata snippet for streaming the exact sample rates you’ll send?