G.711 è il codec che il tuo agente vocale sente nella maggior parte delle telefonate. Campiona l’audio 8.000 volte al secondo, salva ogni campione in 8 bit con una di due curve logaritmiche, μ-law o A-law, e invia il risultato a 64 kbit/s. L’ITU lo ha pubblicato per la prima volta come Raccomandazione G.711 nel 1972, ed è ancora il formato predefinito sulla rete telefonica pubblica, sulla maggior parte dei trunk SIP e nei media stream di Twilio.
Se costruisci qualcosa che tocca l’audio telefonico, prima o poi avrai a che fare con byte G.711. Questa guida spiega come funziona il codec, come distinguere μ-law da A-law, come decodificarlo e codificarlo in poche righe di codice, quali bug trasformano chi chiama in un fruscio e come far entrare e uscire audio a 8 kHz dai modelli vocali senza conversioni inutili. È scritta per gli ingegneri che collegano una linea telefonica a riconoscimento vocale, un LLM e sintesi vocale.
G.711 in sintesi
| Proprietà | Valore |
|---|---|
| Frequenza | 8.000 Hz |
| Bit per campione | 8 (logaritmici, non lineari) |
| Bit rate | 64 kbit/s per direzione |
| Banda audio | Circa da 300 a 3.400 Hz |
| Varianti | μ-law (PCMU) e A-law (PCMA) |
| Payload RTP | PCMU = 0, PCMA = 8, entrambi con clock a 8.000 Hz |
| Pacchetto da 20 ms | 160 campioni, 160 byte di payload |
| Ritardo del codec | Un campione (0,125 ms), senza look-ahead |
| Byte di silenzio | μ-law 0xFF, A-law 0xD5 |
Il pacchetto da 20 ms viene dalla RFC 3551, che fissa 20 ms come intervallo di pacchettizzazione predefinito per PCMU e PCMA. La maggior parte di operatori e PBX lo usa, quindi 160 byte per pacchetto è il numero che vedrai nelle catture.
Come funzionano μ-law e A-law
Un campione lineare a 16 bit può descrivere 65.536 livelli. La voce non ha bisogno di così tanti gradini uguali. Ha bisogno di dettaglio fine a basso volume, dove sta quasi tutta l’informazione di una voce, e di gradini grossi ad alto volume, dove l’orecchio non nota piccoli errori.
G.711 fa esattamente questo. Porta ogni campione su una curva logaritmica, un processo chiamato compansione (comprimere, poi espandere in decodifica). Ogni codice a 8 bit ha tre parti: un bit di segno, tre bit che scelgono uno degli otto segmenti e quattro bit che scelgono un gradino dentro il segmento. Ogni segmento copre il doppio dell’intervallo di quello sotto, quindi la dimensione del gradino raddoppia man mano che il segnale cresce.
Le due varianti distribuiscono i gradini in modo diverso:
- La μ-law parte da un campione lineare a 14 bit e si usa in Nord America e in Giappone. È anche l’unico formato che i Media Streams di Twilio inviano e accettano.
- La A-law parte da un campione lineare a 13 bit e si usa in Europa, in India e nella maggior parte degli altri paesi. Dà un po’ più di risoluzione ai segnali deboli.
Entrambe fanno stare una gamma dinamica di 13 o 14 bit in 8 bit, ed è per questo che G.711 suona come una normale telefonata e non come un walkie-talkie. Quando una chiamata passa da un paese μ-law a uno A-law, la rete la converte, e lo standard prevede che il collegamento tra i due usi la A-law.
Come capire quale hai
Di solito i byte da soli non bastano. Entrambe sono una sequenza di valori senza segno a 8 bit, senza intestazione. Guarda invece i metadati intorno:
- SDP.
a=rtpmap:0 PCMU/8000è μ-law.a=rtpmap:8 PCMA/8000è A-law. - Twilio Media Streams. Il messaggio
startdice sempre"encoding": "audio/x-mulaw"e"sampleRate": 8000. La documentazione dei messaggi WebSocket di Twilio chiarisce che questo non cambia mai. - File WAV. Il tag di formato del blocco
fmtvale 7 per la μ-law e 6 per la A-law.ffprobemostrapcm_mulawopcm_alaw. - Silenzio. Su una linea in silenzio, i byte μ-law restano vicino a
0xFFe0x7E, mentre quelli A-law alternano tra0xD5e0x55. Un buffer pieno di0xFFè quasi certamente silenzio μ-law, non un flusso corrotto.
Se sbagli, si sente. Quando abbiamo codificato un tono a 440 Hz in μ-law e l’abbiamo decodificato in A-law, l’uscita conservava solo circa metà della correlazione con l’originale a ogni volume provato, e il volume oscillava tra la metà e il doppio a seconda del livello di ingresso. L’audio con la legge sbagliata è abbastanza comprensibile da farti cercare il problema altrove, e abbastanza aspro da rovinare il riconoscimento vocale.
Decodificare e codificare G.711 nel codice
La strada più rapida è FFmpeg, che legge e scrive entrambe le leggi come flussi grezzi:
# μ-law grezza da una chiamata a un WAV a 16 bit che puoi ascoltare
ffmpeg -f mulaw -ar 8000 -ac 1 -i call.ulaw call.wav
# Qualsiasi file audio in μ-law grezza a 8 kHz, pronta per Twilio
ffmpeg -i prompt.wav -ar 8000 -ac 1 -f mulaw prompt.ulaw
# A-law: cambia il nome del formato
ffmpeg -f alaw -ar 8000 -ac 1 -i call.alaw call.wav
In Python, la libreria standard lo faceva con audioop, ma audioop è stato rimosso in Python 3.13. Il pacchetto audioop-lts lo ripristina. Se preferisci non dipenderne, la μ-law sta in poche righe di NumPy:
import numpy as np
def linear_to_mulaw(pcm: np.ndarray) -> bytes:
"""16-bit signed PCM samples -> G.711 mu-law bytes."""
x = pcm.astype(np.int32) >> 2 # 14-bit magnitude range
mask = np.where(x < 0, 0x7F, 0xFF)
x = np.minimum(np.abs(x), 8158) + 33 # clip, then add the bias
segment = np.floor(np.log2(x)).astype(np.int32) - 5
code = (segment << 4) | ((x >> (segment + 1)) & 0x0F)
return (code ^ mask).astype(np.uint8).tobytes()
def mulaw_to_linear(data: bytes) -> np.ndarray:
"""G.711 mu-law bytes -> 16-bit signed PCM samples."""
u = ~np.frombuffer(data, dtype=np.uint8).astype(np.int32) & 0xFF
segment, mantissa = (u >> 4) & 0x07, u & 0x0F
magnitude = (((mantissa << 3) + 0x84) << segment) - 0x84
return np.where(u & 0x80, -magnitude, magnitude).astype(np.int16)
Abbiamo verificato entrambe le funzioni contro audioop su tutti i valori di ingresso a 16 bit e su tutti i 256 codici μ-law, e coincidono esattamente. Gli encoder non sempre concordano tra loro ai confini dei segmenti (FFmpeg e audioop differiscono su 512 dei 65.536 ingressi), e va bene così: la differenza è di un gradino sulla curva e non si sente.
I bug che trasformano chi chiama in un fruscio
La maggior parte dei problemi con G.711 nasce da una differenza tra ciò che i byte sono e ciò che il codice pensa che siano.
- La legge sbagliata. μ-law decodificata come A-law, o il contrario. L’audio è forte, ruvido e comprensibile a metà. Controlla l’SDP o il messaggio
startdel flusso, non le tue ipotesi sull’operatore. - Trattare G.711 come PCM lineare a 8 bit. Una libreria che vede campioni a 8 bit e li considera lineari riproduce rumore con la voce sepolta sotto. Decodifica in PCM lineare a 16 bit prima di ricampionare, mixare o eseguire il rilevamento dell’attività vocale.
- Un’intestazione di file nel flusso. Twilio specifica che il
media.payloadin uscita non deve contenere byte di intestazione di file audio. Invia l’intestazione da 44 byte di un WAV e avrai un clic o una raffica di rumore all’inizio di ogni messaggio. Toglila, oppure chiedi al modello vocale un’uscita grezza. - Una frequenza etichettata male. Audio a 8 kHz etichettato come 16 kHz suona al doppio della velocità e un’ottava più acuto. Il contrario sembra un nastro rallentato. Entrambi si decodificano senza errori, ed è per questo che questi bug superano la code review.
- Ricampionare più di una volta. Una pipeline che prende μ-law a 8 kHz, la porta a 16 kHz per un servizio, a 24 kHz per un altro e poi di nuovo a μ-law a 8 kHz aggiunge latenza e artefatti di filtraggio a ogni passaggio. Scegli i formati in modo che ogni percorso audio converta una volta sola, o mai.
- Sovracampionare per “migliorare” la qualità. Portare audio a 8 kHz a 16 kHz non recupera nulla sopra i 4 kHz. I nuovi campioni sono interpolati. Può servire a un modello che accetta solo 16 kHz, ma la “f” di chi chiama non somiglierà meno a una “s”.
Cosa significa 8 kHz per gli agenti vocali
La banda da 300 a 3.400 Hz è la parte della voce che serve alla maggior parte delle persone per capire le parole, ed è per questo che le telefonate funzionano. Le manca però buona parte di ciò che distingue “f” da “s” e “m” da “n”. Un modello di trascrizione provato solo su audio pulito da browser a 16 kHz può andare parecchio peggio sulle stesse parole al telefono. La guida ai trunk SIP affronta il tema dal lato dell’operatore.
Tre abitudini aiutano:
- Valuta su audio telefonico. Registra chiamate di prova attraverso il tuo operatore reale, o almeno fai passare il tuo set di test da un andata e ritorno in μ-law a 8 kHz, prima di confrontare i modelli. La guida al WER spiega come leggere i risultati senza ingannarti.
- Fai confermare i dati importanti. Ripeti nomi, email e numeri di conto, e offri la tastiera per le lunghe sequenze di cifre. I toni DTMF non dipendono dal fatto che il codec trasmetta bene una consonante.
- Invia la voce nel formato che la linea vuole. Una sintesi generata a 44,1 kHz e poi ridotta a μ-law a 8 kHz costa una conversione per ogni frammento. Se il modello può produrre μ-law a 8 kHz direttamente, chiediglielo.
Alcune chiamate trasportano audio a banda larga. G.722 (“voce HD”) campiona a 16 kHz, e le chiamate WebRTC di solito usano Opus. Ma appena una chiamata tocca la rete telefonica pubblica, metti in conto G.711.
G.711 con Cartesia
I modelli vocali di Cartesia accettano e producono G.711 in modo nativo, quindi una pipeline telefonica non ha bisogno di un proprio passaggio di codec.
Sintesi vocale. Sonic restituisce μ-law o A-law grezza a 8 kHz quando lo chiedi. Imposta il formato di uscita su qualsiasi richiesta TTS:
{
"container": "raw",
"encoding": "pcm_mulaw",
"sample_rate": 8000
}
Usa pcm_alaw per le linee A-law. La documentazione dei formati di uscita elenca tutte le codifiche e le frequenze. I frammenti grezzi del WebSocket TTS arrivano in base64, la stessa forma che Twilio si aspetta in media.payload, quindi la guida all’integrazione con Twilio li inoltra senza decodificarli.
Trascrizione. Ink accetta μ-law e A-law tramite l’API di streaming, incluso l’endpoint con rilevamento dei turni pensato per gli agenti vocali. Dichiara il formato quando ti connetti:
wss://api.cartesia.ai/stt/turns/websocket?model=ink-2&encoding=pcm_mulaw&sample_rate=8000&cartesia_version=2026-08-14
Il server decodifica i tuoi byte esattamente secondo ciò che dichiari, e potrebbe non restituire un errore se la dichiarazione è sbagliata. La documentazione sull’input audio mostra come salvare un flusso e controllarlo con ffplay, che scopre in pochi secondi una legge o una frequenza sbagliata.
Managed Agents. Managed Agents risponde alle chiamate su numeri Cartesia, Twilio o sul tuo trunk SIP e gestisce l’audio della chiamata per te. Se invece colleghi la tua telefonia a un agente, il WebSocket degli agenti accetta direttamente input mulaw_8000. Le chiamate degli agenti costano 0,06 $ al minuto, e puoi crearne uno nel playground e chiamarlo dal tuo telefono.
Se devi solo convertire qualche registrazione, FFmpeg lo fa già bene e non ti serve nessuna API vocale.