G.711 est le codec que votre agent vocal entend sur la plupart des appels téléphoniques. Il échantillonne l’audio 8 000 fois par seconde, stocke chaque échantillon sur 8 bits selon l’une de deux courbes logarithmiques, loi μ ou loi A, et envoie le résultat à 64 kbit/s. L’UIT l’a publié pour la première fois en 1972 sous le nom de Recommandation G.711, et c’est toujours le format par défaut du réseau téléphonique public, de la plupart des trunks SIP et des media streams de Twilio.
Si vous construisez quoi que ce soit qui touche à l’audio téléphonique, vous manipulerez des octets G.711 tôt ou tard. Ce guide explique comment fonctionne le codec, comment distinguer la loi μ de la loi A, comment le décoder et l’encoder en quelques lignes, quels bugs transforment un appelant en grésillement, et comment faire entrer et sortir de l’audio 8 kHz des modèles vocaux sans conversions inutiles. Il s’adresse aux ingénieurs qui relient une ligne téléphonique à la reconnaissance vocale, à un LLM et à la synthèse vocale.
G.711 en bref
| Propriété | Valeur |
|---|---|
| Fréquence | 8 000 Hz |
| Bits par échantillon | 8 (logarithmiques, pas linéaires) |
| Débit | 64 kbit/s par sens |
| Bande audio | Environ 300 à 3 400 Hz |
| Variantes | Loi μ (PCMU) et loi A (PCMA) |
| Charge utile RTP | PCMU = 0, PCMA = 8, avec une horloge de 8 000 Hz |
| Paquet de 20 ms | 160 échantillons, 160 octets de charge utile |
| Délai du codec | Un échantillon (0,125 ms), sans anticipation |
| Octets de silence | Loi μ 0xFF, loi A 0xD5 |
Le paquet de 20 ms vient de la RFC 3551, qui fixe 20 ms comme intervalle de paquétisation par défaut pour PCMU et PCMA. La plupart des opérateurs et des PBX l’utilisent, donc 160 octets par paquet est le chiffre que vous verrez dans les captures.
Comment fonctionnent la loi μ et la loi A
Un échantillon linéaire sur 16 bits peut décrire 65 536 niveaux. La voix n’a pas besoin d’autant de marches égales. Elle a besoin de détail fin à faible volume, là où se trouve l’essentiel de l’information d’une voix, et de marches grossières à fort volume, là où l’oreille ne perçoit pas les petites erreurs.
G.711 fait exactement cela. Il place chaque échantillon sur une courbe logarithmique, un procédé appelé compression-extension (on compresse, puis on étend au décodage). Chaque code de 8 bits a trois parties : un bit de signe, trois bits qui choisissent l’un des huit segments, et quatre bits qui choisissent une marche dans le segment. Chaque segment couvre deux fois la plage du précédent, donc la taille de la marche double à mesure que le signal monte.
Les deux variantes placent les marches différemment :
- La loi μ part d’un échantillon linéaire sur 14 bits et sert en Amérique du Nord et au Japon. C’est aussi le seul format qu’envoient et acceptent les Media Streams de Twilio.
- La loi A part d’un échantillon linéaire sur 13 bits et sert en Europe, en Inde et dans la plupart des autres pays. Elle donne un peu plus de résolution aux signaux faibles.
Les deux font tenir une plage dynamique de 13 ou 14 bits sur 8 bits, et c’est pour cela que G.711 sonne comme un appel normal et pas comme un talkie-walkie. Quand un appel passe d’un pays en loi μ à un pays en loi A, le réseau le convertit, et la norme prévoit que la liaison entre les deux transporte la loi A.
Comment savoir laquelle vous avez
En général, les octets seuls ne suffisent pas. Les deux sont une suite de valeurs non signées sur 8 bits, sans en-tête. Regardez plutôt les métadonnées autour :
- SDP.
a=rtpmap:0 PCMU/8000désigne la loi μ.a=rtpmap:8 PCMA/8000désigne la loi A. - Twilio Media Streams. Le message
startindique toujours"encoding": "audio/x-mulaw"et"sampleRate": 8000. La documentation des messages WebSocket de Twilio précise que cela ne change jamais. - Fichiers WAV. L’étiquette de format du bloc
fmtvaut 7 pour la loi μ et 6 pour la loi A.ffprobeaffichepcm_mulawoupcm_alaw. - Silence. Sur une ligne silencieuse, les octets en loi μ restent près de
0xFFet0x7E, et ceux en loi A alternent entre0xD5et0x55. Un tampon rempli de0xFFest très probablement du silence en loi μ, pas un flux corrompu.
Si vous vous trompez, ça s’entend. Quand nous avons encodé un son de 440 Hz en loi μ et l’avons décodé en loi A, la sortie ne gardait qu’environ la moitié de sa corrélation avec l’original à tous les volumes testés, et son niveau variait de la moitié au double selon le niveau d’entrée. Un audio décodé avec la mauvaise loi reste assez intelligible pour vous faire chercher le problème ailleurs, et assez dur pour ruiner la reconnaissance vocale.
Décoder et encoder G.711 en code
Le plus rapide est FFmpeg, qui lit et écrit les deux lois en flux bruts :
# Loi μ brute d'un appel vers un WAV 16 bits que vous pouvez écouter
ffmpeg -f mulaw -ar 8000 -ac 1 -i call.ulaw call.wav
# N'importe quel fichier audio vers de la loi μ brute à 8 kHz, prête pour Twilio
ffmpeg -i prompt.wav -ar 8000 -ac 1 -f mulaw prompt.ulaw
# Loi A : changez le nom du format
ffmpeg -f alaw -ar 8000 -ac 1 -i call.alaw call.wav
En Python, la bibliothèque standard le faisait avec audioop, mais audioop a été retiré dans Python 3.13. Le paquet audioop-lts le rétablit. Si vous préférez vous en passer, la loi μ tient en quelques lignes de 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)
Nous avons vérifié les deux fonctions contre audioop sur toutes les valeurs d’entrée 16 bits et les 256 codes en loi μ : elles concordent exactement. Les encodeurs ne s’accordent pas toujours entre eux aux limites de segment (FFmpeg et audioop diffèrent sur 512 des 65 536 entrées), et ce n’est pas grave : l’écart est d’une marche sur la courbe et ne s’entend pas.
Les bugs qui transforment un appelant en grésillement
La plupart des problèmes G.711 viennent d’un écart entre ce que sont les octets et ce que le code croit qu’ils sont.
- La mauvaise loi. Loi μ décodée en loi A, ou l’inverse. L’audio est fort, granuleux et à moitié intelligible. Vérifiez le SDP ou le message
startdu flux, pas vos suppositions sur l’opérateur. - Traiter G.711 comme du PCM linéaire 8 bits. Une bibliothèque qui voit des échantillons 8 bits et les suppose linéaires joue du bruit avec la voix enfouie dessous. Décodez en PCM linéaire 16 bits avant de rééchantillonner, de mixer ou de lancer une détection d’activité vocale.
- Un en-tête de fichier dans le flux. Twilio précise que le
media.payloadsortant ne doit pas contenir d’octets d’en-tête de fichier audio. Envoyez l’en-tête de 44 octets d’un WAV et vous aurez un clic ou une rafale de bruit au début de chaque message. Retirez-le, ou demandez une sortie brute au modèle vocal. - Une fréquence mal étiquetée. De l’audio 8 kHz étiqueté 16 kHz joue deux fois trop vite et une octave trop haut. L’inverse ressemble à une bande ralentie. Les deux se décodent sans erreur, et c’est pourquoi ces bugs passent la revue de code.
- Rééchantillonner plusieurs fois. Un pipeline qui prend de la loi μ à 8 kHz, la passe à 16 kHz pour un service, à 24 kHz pour un autre, puis la ramène en loi μ à 8 kHz ajoute de la latence et des artefacts de filtrage à chaque étape. Choisissez les formats pour que chaque chemin audio ne convertisse qu’une fois, ou pas du tout.
- Suréchantillonner pour « améliorer » la qualité. Passer de l’audio 8 kHz à 16 kHz ne récupère rien au-dessus de 4 kHz. Les nouveaux échantillons sont interpolés. Cela peut aider un modèle qui n’accepte que du 16 kHz, mais le « f » de l’appelant ne ressemblera pas moins à un « s ».
Ce que 8 kHz change pour les agents vocaux
La bande de 300 à 3 400 Hz est la partie de la voix dont la plupart des gens ont besoin pour comprendre les mots, et c’est pour cela que le téléphone fonctionne. Il lui manque aussi une bonne partie de ce qui sépare « f » de « s » et « m » de « n ». Un modèle de transcription testé uniquement sur de l’audio navigateur propre à 16 kHz peut faire nettement moins bien sur les mêmes mots au téléphone. Le guide sur le trunk SIP aborde la question côté opérateur.
Trois habitudes aident :
- Évaluez sur de l’audio téléphonique. Enregistrez des appels de test via votre opérateur réel, ou au minimum faites passer votre jeu de test par un aller-retour en loi μ à 8 kHz, avant de comparer des modèles. Le guide du WER explique comment lire les résultats sans vous tromper.
- Faites confirmer les informations importantes. Répétez les noms, les e-mails et les numéros de compte, et proposez le clavier pour les longues suites de chiffres. Les touches DTMF ne dépendent pas de la bonne transmission d’une consonne.
- Envoyez la voix dans le format attendu par la ligne. Une synthèse générée à 44,1 kHz puis réduite en loi μ à 8 kHz coûte une conversion à chaque morceau. Si le modèle peut produire directement de la loi μ à 8 kHz, demandez-le.
Certains appels transportent de l’audio large bande. G.722 (« voix HD ») échantillonne à 16 kHz, et les appels WebRTC utilisent en général Opus. Mais dès qu’un appel passe par le réseau téléphonique public, prévoyez du G.711.
G.711 avec Cartesia
Les modèles vocaux de Cartesia acceptent et produisent du G.711 nativement, donc un pipeline téléphonique n’a pas besoin de sa propre étape de codec.
Synthèse vocale. Sonic renvoie de la loi μ ou de la loi A brute à 8 kHz quand vous le demandez. Définissez le format de sortie sur n’importe quelle requête TTS :
{
"container": "raw",
"encoding": "pcm_mulaw",
"sample_rate": 8000
}
Utilisez pcm_alaw pour les lignes en loi A. La documentation des formats de sortie liste tous les encodages et toutes les fréquences. Les morceaux bruts du WebSocket TTS arrivent encodés en base64, la forme même que Twilio attend dans media.payload ; le guide d’intégration Twilio les transmet donc sans les décoder.
Transcription. Ink accepte la loi μ et la loi A via l’API de streaming, y compris l’endpoint avec détection des tours de parole conçu pour les agents vocaux. Déclarez le format à la connexion :
wss://api.cartesia.ai/stt/turns/websocket?model=ink-2&encoding=pcm_mulaw&sample_rate=8000&cartesia_version=2026-08-14
Le serveur décode vos octets exactement selon ce que vous déclarez, et il peut ne pas renvoyer d’erreur si la déclaration est fausse. La documentation sur l’entrée audio montre comment enregistrer un flux et le vérifier avec ffplay, ce qui repère une mauvaise loi ou une mauvaise fréquence en quelques secondes.
Managed Agents. Managed Agents répond aux appels sur des numéros Cartesia, Twilio ou votre propre trunk SIP et gère l’audio de l’appel pour vous. Si vous reliez plutôt votre propre téléphonie à un agent, le WebSocket des agents accepte directement une entrée mulaw_8000. Les appels d’agent coûtent 0,06 $ par minute, et vous pouvez en créer un dans le playground et l’appeler depuis votre téléphone.
Si vous avez seulement quelques enregistrements à convertir, FFmpeg le fait déjà bien, et vous n’avez besoin d’aucune API vocale.