Sage Betko

One Long Number

What twenty milliseconds of a phone call looks like from the inside.

When you speak into a call, your voice leaves the microphone as a pressure recording and leaves the machine as something else: about fifty packets per second, each covering twenty milliseconds, most only a few dozen bytes long. On nearly every call in the world those packets are built by the same piece of software: Opus, the codec inside WebRTC, the machinery under Discord and WhatsApp and most of what we casually call “a call.” It is one of the most-executed perceptual models ever written. Here is what its packets contain.

A packet is not a miniature recording, and it is not a small spectrogram. Exactly one byte of it has fields you can read: the first.

the first byte — the only one with fields

0 0 0 0 1 0 0 0 configuration stereo frames 00001 = config 1 SILK speech model · 10–60 ms Hybrid both at once CELT transform coder · 2.5–20 ms 0 31
The table-of-contents byte of an actual 6 kb/s packet from the heatmap below. Five bits pick one of thirty-two configurations — which coder is in use, over what audio bandwidth, for how long — one bit says mono or stereo, and two describe how frames are packed. It is the only part of the packet with fields at fixed positions.

Those five configuration bits choose between two different models of sound. SILK, descended from Skype’s speech codec, models sound as a voice: a pitched buzz from the larynx, shaped by the resonances of a throat and mouth. Modeling the speaker rather than the waveform is what makes SILK cheap on speech: a vocal tract is a few dozen slowly-changing numbers, while the waveform it produces is sixteen thousand samples a second. It is also why SILK alone can’t handle music: a cymbal crash has no pitch to track and no vocal tract shaping it, and a model built from one buzzing source and one filter has no setting of its parameters that produces one.

CELT, which came from Xiph.Org (the nonprofit behind Vorbis and FLAC), assumes nothing about what made the sound: it codes the spectrum itself, band by band, which costs more bits for speech but can represent anything — cymbals included. Between the two sits a hybrid mode that splits the signal at eight kilohertz and runs SILK below, CELT above. The encoder picks whichever representation fits each twenty-millisecond frame, and switches as the signal changes.

After that first byte there are no more fields. The rest of the packet is, in a precise sense, a single number.

everything after the first byte is one number

first decision 0 1 the likely option · 0.7 bits the rare one · 1.4 bits second decision — inside the chosen slice 0 1 this one · 1.7 bits a few hundred decisions later 0 1 ← the interval that survives The packet's remaining bytes are the binary digits of one number inside that sliver — no fields, no offsets; every decision affects every byte that follows it.
Range coding, the machine that writes the rest of the packet. Every quantized decision narrows an interval on the number line — cheaply when the outcome was probable, expensively when it wasn't; the cost in bits is exactly −log₂ of the probability. Predict well and the interval barely narrows: that is compression, and it is why a well-predicted stream has almost nothing left to see.

The decisions doing that narrowing are the interesting part. In a SILK frame, the encoder writes down: how loud you are, as four gains covering five milliseconds each; the shape of your vocal tract, as sixteen numbers; your pitch, as a lag and a measure of how exactly the buzz repeats. Whatever those models fail to account for goes in last, as the excitation, the residual left over once the gains, the filter, and the pitch predictor have each subtracted what they can. The excitation takes most of the bits, and it has to: everything predictable about the signal has already been absorbed into the model parameters, so what remains is close to patternless, and patternless data is the one thing entropy coding cannot compress.

The sixteen vocal-tract numbers are worth a closer look:

SILK's model of a voice

a pitched buzz the vocal tract, as a filter speech the envelope, redrawn every 20 ms 0 8 kHz sixteen line-spectral frequencies — the whole filter, as sixteen numbers pairs pinch where the envelope peaks
SILK carries the vocal-tract filter as sixteen frequencies. Where two of them crowd together, the envelope has a sharp peak; where they spread apart, it is flat. What travels in the packet, in effect, is the shape of a mouth, re-measured fifty times a second.

CELT’s inventory matches its model. It transforms each frame to the frequency domain and splits the spectrum into twenty-one bands whose widths follow the Bark scale, an empirical map of the ear’s frequency resolution: fine at the bottom of the range, increasingly coarse toward the top. Matching the ear’s resolution means the codec never spends bits on distinctions no listener could hear. The first thing coded in every CELT frame, before any detail, is one coarse energy per band.

CELT's model of sound

0 1k 4k 8k 20k narrow where hearing is sharp… …wide where it isn't one coarse energy per band, every packet — a 21-pixel spectrogram column
CELT's twenty-one bands at 48 kHz, drawn to scale on a linear axis. The spacing tracks the ear's critical bands: two hundred hertz wide at the bottom, over four kilohertz wide at the top. Each band's energy is coded first, coarsely, before anything else — then the fine shape within each band, with a bit budget derived from that energy.

None of this structure is supposed to be visible in the bytes. The range coder’s job is to spend bits only on what could not be predicted, and its output, run perfectly, is statistically indistinguishable from random noise. Any visible pattern would be a prediction the model failed to make. This is why compressed data looks encrypted before any encryption has touched it. The vocal tract, the band energies, the pitch track: all of it is in the packet, but at no fixed offset, dissolved into the digits of one long number.

Even the one property the entropy coder cannot hide — how many bytes each packet needed — says more than it should: researchers have recovered spoken phrases from encrypted calls from packet sizes alone, and there is an RFC politely warning about it.

Whether the noise promise actually holds is easy to check: take one second of speech (a single word), encode it at three bitrates, and draw every byte as a pixel.

Three stacked charts of raw Opus packet bytes for the same one-second word at 6, 24, and 48 kb/s, drawn as glowing amber cells on a dark plate. Each packet is a column of byte-valued pixels, first byte at the bottom, and the column heights trace packet sizes. The 6 kb/s panel is short with visible repeating structure; under the 24 kb/s panel, brackets mark a run of hybrid packets followed by SILK packets; the 48 kb/s panel is a tall field of uniform speckle.
Raw packet bytes, parsed straight from the stream, with no decoding anywhere. Each packet is one column, first byte at the bottom, time running left to right; all three panels share the same vertical scale, and brighter cells are higher byte values. The brackets under the middle panel mark where the encoder switched between hybrid and SILK packets mid-word as the sound changed.

At 48 kb/s the promise is nearly kept: the panel is uniform speckle, and the only structure left is its outline. At 6 kb/s it isn’t. Horizontal bands run through the stack at the same byte offsets, packet after packet; the first bytes form a flat, unvarying line along the base; and the skyline itself, which shows how many bytes each packet needed, rises and falls with the word. The closer an encoder runs to the entropy limit, the less structure it should leave visible; at six kilobits, it is plainly leaving some.

But the visible leftovers are a curiosity, not the point. Whether or not anything shows in the bytes, everything cataloged above is inside every packet. A codec is a compiled theory of its signal: decades of speech science and psychoacoustics reduced to running code. A stream of packets is that theory applied, twenty milliseconds at a time: a vocal-tract shape, a spectrum drawn on the ear’s own bands, a pitch track. An Opus stream is not a compressed waveform; it is a description of one.

That reframes the phone call we began with. While you speak, the encoder on your side fits a fresh model of your voice every twenty milliseconds and writes it into the stream. The decoder on the other side uses the model to reconstruct sound, then discards it. And when a machine needs to analyze that audio, it decodes back to a waveform and computes a spectrogram, rebuilding from scratch a description that was in the packets all along.

I have wondered since 2022 whether the description could be read directly: whether a model could work from what the codec wrote instead of decoding it and starting over. The idea has precedent in other media: image networks have been trained on JPEG’s DCT coefficients rather than pixels, and action recognizers have worked from the motion vectors in compressed video rather than from decoded frames. For audio it remains nearly untouched, though there are places it would matter: anywhere sound is analyzed at scale, on a battery, or under a latency budget.

This August I started finding out. The results belong in a paper before they belong here, so that is the order they’ll arrive in.