Loading Cookbooks...
Loading Cookbooks...
Wire an incoming Twilio phone call to OrbitalsAI's streaming API so that every word spoken on the call is transcribed and printed to your console in real time: no recording, no post-processing, and no waiting.
Twilio can stream raw audio from any phone call to a WebSocket endpoint the moment the call connects. This guide wires that stream to OrbitalsAI's streaming API so that every word spoken on a call appears in your console as it happens: no recording, no post-processing, no waiting for the call to end. By the end you'll have a working phone number you can call and watch transcribe itself in real time. The multilingual guide builds directly on top of this one, so it's worth getting this running before moving on.
There are three moving parts, and understanding how they connect will save you debugging time later.
The format mismatch in the middle is the part that catches people: Twilio encodes phone audio in 8 kHz mu-law (the PSTN standard), but OrbitalsAI expects 16 kHz PCM16. The conversion happens in two steps (mu-law decode, then resample) using Python's built-in audioop module. No FFmpeg, no external dependencies.
Every endpoint configuration in these recipes uses local credentials. Replace placeholders (like YOUR_API_KEY) with your actual API key retrieved from the OrbitalsAI Dashboard.
There are three moving parts, and understanding how they connect will save you debugging time later.
The format mismatch in the middle is the part that catches people: Twilio encodes phone audio in 8 kHz mu-law (the PSTN standard), but OrbitalsAI expects 16 kHz PCM16. The conversion happens in two steps (mu-law decode, then resample) using Python's built-in audioop module. No FFmpeg, no external dependencies.
Create a .env file in your project root:
Add .env to your .gitignore. Commit an env.example copy with blank values so teammates know what to fill in.
Then install dependencies:
This file owns everything between receiving a Twilio audio frame and sending it to OrbitalsAI: conversion, buffering, and the streaming session lifecycle.
Two endpoints:
- POST /: Twilio calls this when a call arrives. Respond with TwiML that tells Twilio to stream audio to the WebSocket.
- WebSocket /realtime: Twilio streams audio frames here as JSON messages.
You should see:
INFO: Uvicorn running on http://0.0.0.0:5000
In a second terminal, expose your local port 5000 using ngrok:
Copy the https:// URL, you need it in the next step. On the free ngrok tier, this URL changes every time you restart ngrok. If you're doing anything beyond a quick local test, a static ngrok URL or a proper deployment will save you the constant re-configuration.
1. Open the Twilio Console (console.twilio.com)
2. Go to Phone Numbers → Manage → Active numbers
3. Click your number
4. Under Voice & Fax → A call comes in, set:
- Webhook: your ngrok URL, e.g., https://a1b2-203-0-113-42.ngrok-free.app/
- HTTP method: HTTP POST
5. Save
When you initiate a connection and make a phone call, your server console or browser display will output values formatted as follows:
Transcribe in African languages. Pass language="hausa", language="yoruba", or language="igbo" to StreamingConfig. Nothing else changes. The multilingual guide builds on this to let the caller choose their language at dial time. This is the same pattern used by MTN and Airtel IVRs.
Store transcripts instead of printing them. Replace the print() calls in TwilioOrbitalsHandlers with writes to a database, keyed by the call SID (available as data["start"]["callSid"] in the start event).
Handle multiple simultaneous calls. You already do. Each WebSocket connection creates its own TwilioOrbitalsTranscriber instance, so concurrent calls are isolated by default.
Deploy beyond ngrok. Twilio requires a valid TLS certificate on the WebSocket URL. Railway, Render, and a VPS behind nginx are all straightforward options.