What streaming codecs do to a master, measured
A pop master delivered at −0.2 dBTP comes back from Spotify's codec at +2.4 dBTP. A jazz master delivered at −1.2 comes back at −0.0, and fits with nothing to spare. Those two numbers are most of what the −1 dBTP line in the delivery specs is buying, and they are easier to show than to argue about. Below: the method, the results for three masters through three codecs, and the script, so you can run it on your own work.
Everyone knows a lossy codec removes something. What is harder to find is a number: how much, on real masters, at the settings the platforms actually serve. So I measured it on three of my own masters, and the interesting result was not the one I went looking for.
What was measured
Three commercial masters, all 44.1 kHz, 24-bit stereo: a dense pop master and a hip-hop master, both delivered at −0.2 dBTP, and a jazz master delivered at −1.2 dBTP. Each was encoded three ways and decoded back to PCM:
- Ogg Vorbis, 96 kbps, which is Spotify's bitrate on the free tier and on mobile data. That is the encode most listeners get.
- AAC-LC, 256 kbps, which is what Apple Music publishes.
- Opus, 128 kbps, the commonly reported figure for YouTube music.
Spotify does not publish which container its apps use, so Ogg Vorbis is the long-reported assumption rather than a documented fact. The bitrate is theirs.
The method, and why the control matters more than the results
The measurement is a null test: subtract the decoded file from the source and look at what is left. Two things have to be right before the subtraction means anything.
Alignment. Encoders delay the signal, and the amount differs by codec. Subtract without correcting for it and you are comparing a file with a shifted copy of itself, which reports enormous damage that the codec never did. The script cross-correlates the two and shifts before subtracting. On this pipeline the offset came out at zero samples for all three, because ffmpeg honors the priming and pre-skip metadata when it decodes. That is a suspicious-looking result, so the script shifts a signal by known amounts and requires the aligner to find them before it measures anything.
Level. A codec can come back a fraction of a decibel off. Uncorrected, that shows up as loss. The script solves for the best-fit gain and reports the correction alongside the residual, so you can see how much of it was level.
Then the control. The same pipeline runs on a lossless round trip: FLAC in, decode, align, subtract. The residual is a perfect null. A method that cannot return identical when the answer is identical is not measuring anything, so that runs first, every time, and prints first.
True peak: the result worth having
This is the number I did not expect to be the headline. True peak is read from ffmpeg's ebur128 rather than from anything in the script, because it is the figure most likely to be argued with and it should not rest on a filter I wrote.
| Master | Delivered | Ogg Vorbis 96k | AAC-LC 256k | Opus 128k |
|---|---|---|---|---|
| Pop | −0.2 dBTP | +2.4 | +1.0 | +1.7 |
| Hip-hop | −0.2 dBTP | +2.3 | +1.1 | +1.5 |
| Jazz | −1.2 dBTP | −0.0 | −0.6 | −0.2 |
The two masters delivered at −0.2 dBTP are handed to the listener at over +2 dBTP by the codec most listeners receive. The one delivered at −1.2 lands at −0.0, which is to say it fits, and only just.
That is what the −1 dBTP in Apple's and Amazon's specs is for, and it is a more useful thing to know than the rule itself. It is also not an instruction. Plenty of released records sit above the line on purpose, from engineers who have looked at the number and decided the density is worth more than the headroom. The measurement tells you the size of the trade. It does not tell you which side of it to be on.
How much came back
Residual is the level of what is left after subtracting, relative to the source. Lower is closer to the original.
| Master | Ogg Vorbis 96k | AAC-LC 256k | Opus 128k |
|---|---|---|---|
| Pop (densest) | −13.3 dB | −22.7 dB | −17.2 dB |
| Hip-hop | −17.4 dB | −26.3 dB | −20.0 dB |
| Jazz (most headroom) | −20.0 dB | −31.9 dB | −22.9 dB |
The ordering is the same in every column, and it is the order of how hard each master was pushed. The denser the material, the more the codec discards. That has a consequence for the way transparency gets talked about: "AAC at 256 is transparent" is a claim about typical music, not about all music, and the material you hand it moves the answer by nearly ten decibels.
Where it goes
Broken into bands, against each band's own energy in the source, the three codecs do visibly different jobs on the pop master:
| 0–1k | 1–6k | 6–12k | 12–18k | 18–22k | |
|---|---|---|---|---|---|
| Ogg Vorbis 96k | −21 dB | −9 dB | −4 dB | −2 dB | gone |
| AAC-LC 256k | −26 dB | −21 dB | −13 dB | −11 dB | −12 dB |
| Opus 128k | −21 dB | −14 dB | −9 dB | −5 dB | gone |
Vorbis and Opus both discard everything above 18 kHz. AAC keeps it, and is the only one of the three that does. If you compare these codecs by looking at spectrograms, that top octave is what you will notice, and it will tell you AAC is the careful one and the other two are crude. The residual figures say something more complicated: AAC is indeed the closest, but it still leaves −22.7 dB against a dense master while appearing untouched from about 12 kHz up. A spectrum shows you what is missing. It does not show you what has moved.
What this changes about sending a master
Not much, if you already deliver with a decibel of headroom. If you deliver at −0.2 because that is where the limiter landed, the measurement says the listener's file will be over zero, on the encode most of them receive, and that whether it matters depends on their decoder and their playback chain rather than on anything you can hear on yours.
The part worth carrying into a session is smaller and more practical: the encode is a different file, and the client is going to hear that one. Approving a lossless master and then releasing a 96 kbps Vorbis of it means the approval was given on audio nobody will play. That gap is small on an acoustic record with headroom and it is not small on a dense one.
Run it on your own work
The whole point of a measurement is that someone else can repeat it. The script is below in full. It needs ffmpeg, numpy and soundfile, it takes a WAV, and it prints the control first. Nothing is uploaded and nothing is written except the numbers.
Two things to watch if you run it. Use real music: a sine tone gives a codec almost nothing to throw away, and noise gives it far too much, so both will mislead you. And read the control line. If the lossless round trip does not come back as a perfect null on your machine, the rest of the output is decoration.
Frequently asked questions
Does a streaming codec raise true peak?
In these measurements, yes, and by more than the margin most masters are delivered with. A pop master at −0.2 dBTP came back from Ogg Vorbis at 96 kbps at +2.4 dBTP, from Opus at 128 kbps at +1.7, and from AAC-LC at 256 kbps at +1.0. The same three codecs moved a jazz master delivered at −1.2 dBTP to −0.0, −0.2 and −0.6.
Why does a null test need the files aligned first?
Encoders delay the signal. Vorbis and AAC prime, Opus has a pre-skip, and subtracting without correcting for that compares a file with a shifted copy of itself, which reports far more damage than the codec did. The script cross-correlates first. It also matches level, because a codec returning a fifth of a decibel low would otherwise look like loss.
How do you know the measurement is not just measuring itself?
The same pipeline is run on a lossless round trip. FLAC in, decode, align, subtract, and the residual is a perfect null on every run. A method that cannot return identical when the answer is identical is not measuring anything, so that control runs before the codecs and the script says so in its output.
Is AAC at 256 kbps transparent?
It was the closest of the three on all three masters, and it was the only one that kept anything above 18 kHz. It still left a residual of −22.7 dB against the densest master. Transparent is a claim about what a listener notices, which is a different question from what survives subtraction, and this page only answers the second.
Why do the three masters give different results?
The denser the master, the more the codec discards. Ogg Vorbis at 96 kbps left −13.3 dB against the pop master, −17.4 against the hip-hop one and −20.0 against the jazz one, which is the order of how hard each was pushed. Any claim that a bitrate is transparent is a claim about typical material rather than about all of it.
Let the client hear the encode, not just the master
Soneam turns a master into a review link, and the client can switch between the lossless file and the encode each platform serves, at that platform's playback level. Approving one and releasing the other is the gap this page measures.