# Codec Guide

> Pick a voice codec — Opus, PCM16, or G.711 µ-law/A-law — and let the bridge transcode. When to use which, and the passthrough fast paths.

You pick **one codec per attach**, and the bridge does the rest. The carrier
can negotiate any format on the wire: µ-law from a North American trunk, A-law
from a European one, Opus from a browser. The bridge transcodes that format to
the codec that your code asked for. It transcodes your replies back. You never
run media tooling in your own process. You never have to match the carrier's
format to read the audio.

This page is the decision guide. It covers the four codecs that FirstByte
Voice exposes, and when each is the right choice. It also covers the two cases
where you skip transcoding entirely for a zero-cost passthrough.

## The four codecs

Every SDK exposes the same `AudioCodec` type. Set it when you attach an audio
bridge or bind an agent:

| Codec        | Wire format          | Rate    | When to use it                                                    |
| ------------ | -------------------- | ------- | ----------------------------------------------------------------- |
| `opus`       | Opus (48 kHz mono)   | 48 kHz  | **Default.** Browser/app legs; best quality-per-bit.              |
| `pcm16`      | Raw 16-bit PCM LE    | 8 kHz¹  | Use it to feed a realtime AI model that wants uncompressed input. |
| `g711_ulaw`  | G.711 PCMU (PT 0)    | 8 kHz   | PSTN-direct, no transcode. µ-law — North America and Japan.       |
| `g711_alaw`  | G.711 PCMA (PT 8)    | 8 kHz   | PSTN-direct, no transcode. A-law — most of the rest of the world. |

<sub>¹ `pcm16` frames are 8 kHz mono on the call bus by default; set `sampleRate`
to resample. See [Audio shape](#audio-shape-samplerate-channels-framems).</sub>

  
```ts
import { Voice } from "clutchcall_connect/voice";

const voice = new Voice({ apiKey: process.env.CLUTCHCALL_API_KEY! });

// Attach the server side of a call, asking for PCM16 to feed a model.
const bridge = await voice.audioBridge.attach(sid, { codec: "pcm16" });
bridge.onUplink((tsUs, pcm) => model.push(pcm));   // caller audio, decoded for you
```
  
  
```python
from clutchcall.voice import Voice

voice = Voice(api_key=os.environ["CLUTCHCALL_API_KEY"])

bridge = await voice.audio_bridge.attach(sid, codec="pcm16")
bridge.on_uplink(lambda ts_us, pcm: model.push(pcm))
```
  
  
```rust
// enum Codec { Opus, Pcm16, G711ULaw, G711ALaw }
let bridge = voice.audio_bridge()
    .attach(&sid, Codec::Pcm16)
    .await?;
```
  

Voice is **audio-only**. There are no video codecs on this path. If you do not
set a codec, you get `opus`.

## Choosing a codec

Work from the consumer of the audio, not from the carrier. The carrier leg is
the bridge's problem, not yours:

  1. **Talking to a browser or app? Use opus.**
Browser softphones capture and encode Opus natively. The encoder comes
    straight from the browser's audio pipeline. Keep the leg on `opus`
    end-to-end. There is then no re-encode, and you get the best quality for
    the bitrate. This is why `opus` is the default.
  2. **Feeding a realtime AI model? Use pcm16.**
Most speech-to-speech and ASR models want uncompressed PCM on their input.
    Ask for `pcm16`. The bridge hands your code decoded 16-bit samples with no
    codec in the middle. This is the same raw format that the agent runtime
    uses internally.
  3. **Bridging straight to a PSTN trunk? Match the trunk's G.711.**
You can relay a call leg to a SIP/PSTN trunk without a need to inspect or
    transform the audio. In that case, ask for the trunk's own G.711 variant:
    `g711_ulaw` for North America and Japan, `g711_alaw` for the rest of the
    world. The frames pass through untouched (see
    [passthrough](#passthrough-fast-paths-zero-transcode)).

> **NOTE:**
> **µ-law vs A-law is a regional wire convention, not a quality choice.** North
> American and Japanese carriers use µ-law (PCMU, payload type 0). Nearly everyone
> else uses A-law (PCMA, payload type 8). Both are 8 kHz 8-bit companded G.711
> with effectively identical fidelity. Pick the one that your carrier negotiates.
> If you get it wrong, you hear distortion. When two G.711 legs of different
> flavours meet, the bridge transcodes between the two anyway.

## Transcoding at the bridge

Carrier legs almost always arrive as **G.711 at 8 kHz** (PCMU or PCMA). Browser
legs arrive as **Opus at 48 kHz**. The bridge sits between the wire and your
code. It converts in both directions: it decodes to the runtime's internal PCM
representation, and it re-encodes to the format that each side needs:

```
 CALLER LEG                         BRIDGE                      YOUR CODE
 ┌──────────────┐                                             ┌──────────────┐
 │ PSTN G.711   │ ──decode──▶  8 kHz PCM16 (agent bus)  ──────▶│ codec: pcm16 │
 │ µ-law/A-law  │ ◀─encode──   ◀────── your reply PCM ─────────│  (or opus)   │
 └──────────────┘                                             └──────────────┘
 ┌──────────────┐                                             
 │ Browser Opus │ ──decode/resample 48↔8 kHz──▶  PCM16  ──────▶ same bus
 └──────────────┘                                             
```

Two consequences are worth knowing:

- **The runtime bus is 8 kHz PCM16 end-to-end.** A 20 ms tick is 160 samples at
  8 kHz. That is the fidelity ceiling for anything routed through the agent
  path. This is telephone-band audio — exactly what PSTN delivers, and what
  speech models are trained on.
- **Opus keeps a 48 kHz RTP clock even though the audio is narrowband.** The
  Opus rtpmap stays `opus/48000/2`. Each 20 ms frame advances the timestamp by
  960, per the codec's spec. The encoder's internal rate is driven to
  narrowband to match the bus. You do not manage any of this — it is the fix
  that makes browser Opus play back clean. But it is why you see `48000` in an
  SDP, even for an 8 kHz call.

## Passthrough fast paths (zero transcode)

Transcoding is cheap, but the fastest audio is audio that you never touch. Two
paths skip the codec entirely:

  1. **G.711 in, same G.711 trunk out.**
Bridge a PSTN leg to another PSTN/SIP trunk of the **same** G.711 flavour,
    and ask for that flavour. The bridge then relays the frames verbatim: no
    decode, no re-encode. This is the norm for straight call-forwarding and
    carrier hand-off.
  2. **External µ-law WebSocket audio to a µ-law trunk.**
Are you migrating from a Twilio Media Streams–style source? Its 8 kHz µ-law
    WebSocket frames map straight onto a PCMU SIP trunk with **zero
    transcode**. The payloads are already in the trunk's format. See
    [Migrate from Twilio](/modalities/voice/migration/from-twilio) for the
    wiring.

> **WARNING:**
> Passthrough only holds when **both** ends agree on the codec. If you ask for
> `pcm16` or `opus` on a G.711 leg, you opt into a transcode. That is fine and
> often what you want — you cannot feed a model raw companded G.711 — but it is
> not free. If two G.711 legs disagree (one µ-law, one A-law), the bridge
> transcodes between them automatically instead of sending garbled audio.

## Audio shape: sampleRate, channels, frameMs

The codec choice sets the *format*. Three more knobs set the *shape*. All have
sensible defaults, so you usually set only `codec`:

- **`codec`** (`"opus" | "pcm16" | "g711_ulaw" | "g711_alaw"`, default `opus`) — The wire format for this leg, per the table above.
- **`sampleRate`** (`number`, default `48000`) — Samples per second. `opus` runs at 48000. G.711 is fixed at 8000. For   `pcm16`, set this to the rate that your model wants (e.g. `16000` or   `24000`). The bridge resamples for you. The stateful resampler avoids the   "chipmunk" artefacts of a naive double-resample.
- **`channels`** (`number`, default `1`) — Voice is mono. Recordings mix the two legs into stereo downstream (caller   left, agent right). That is a recording concern, not a codec concern.
- **`frameMs`** (`number`, default `20`) — Milliseconds of audio per frame/object. 20 ms is the RTP and Opus standard   (160 samples at 8 kHz, 960 at 48 kHz). Every pacer and jitter buffer on the   path assumes it. Change it only if a downstream consumer demands it.

## Related

  - **[Sessions, calls, tracks & streams](/modalities/voice/concepts/sessions-calls-tracks-streams)** — Where the codec's capability tag (`voice/opus`, `voice/pcm16`) fits the track model.
  - **[SIP trunking](/modalities/voice/transport-telephony/sip-trunking)** — How carrier legs negotiate G.711 on the wire before the bridge sees them.
  - **[Browser audio capture](/modalities/voice/transport-web/browser-audio-capture)** — The Opus path: the browser's own encoder onto QUIC/MoQT.
  - **[Migrate from Twilio](/modalities/voice/migration/from-twilio)** — The µ-law WebSocket → PCMU trunk passthrough on-ramp.
