Capo
How it works

Why most audio extensions do nothing on Spotify or Tidal

Elyra Labs team3 min read
The short answer

Protected streaming audio will not give its decoded samples to page scripts. Any extension that works by attaching an analyser to the media element therefore produces silence on Spotify, Tidal, Apple Music, Amazon Music and Deezer. Processing the audio in place, inside the context that negotiated the encryption, is the way around it.

  1. The usual approach taps the media element. Protected media refuses.
  2. Capo instead splices its worklet into the audio graph itself.
  3. The samples never leave the context, so playback keeps working.

If you have tried a pitch or equalizer extension on a paid streaming service, you have probably watched it do nothing at all. The controls move, the audio does not change, and there is rarely any explanation. The reason is the same in every case, and it is not a bug.

What protected playback refuses to do

Streaming services deliver encrypted audio through the browser’s Encrypted Media Extensions. The decryption happens somewhere the page cannot see, and the browser will not hand the decoded samples back to ordinary JavaScript. That is the entire point: if page scripts could read the samples, the protection would be meaningless.

The standard way to process a page’s audio is to attach an analyser or a processing node to the media element. On protected media the browser refuses, and what comes out is silence or nothing at all. Every extension built that way stops at the same wall.

Processing in place instead of extracting

Capo takes a different route. Rather than pulling audio out of the page, it replaces the audio context so that every context — the page’s own included — carries a proxy destination, with the pitch-shifting worklet spliced between that proxy and the real output.

The consequence is the one that matters: the samples never leave the context that negotiated the encryption. Nothing is decrypted by Capo, nothing is copied, and nothing is exposed to any other script. The audio is processed on its way to the speakers and then it is gone.

Which services this covers

ServiceWhere
Spotifyopen.spotify.com, web player only
Apple Musicmusic.apple.com, web player only
Tidaltidal.com and listen.tidal.com
Amazon Musicmusic.amazon.* regional storefronts
Deezerdeezer.com

The desktop applications for these services are native software. No browser extension can reach them, and that limitation is not something a different approach would solve.

Pitch and speed, even on protected players.

Free · nothing uploaded
Add to Chrome — free

What this does not settle

It does not mean every protected player behaves identically. Services change their web clients, and a layout change can break track detection without breaking audio processing. It also does not cover pages that never produce sound in the first place, where there is nothing to process at all.

Questions

Can a browser extension change the pitch of DRM-protected audio?
Not by the usual method. Protected media will not hand its decoded samples to page scripts, so extensions that attach an analyser to the media element produce silence. Processing the audio in place, inside the context that negotiated the encryption, does work.
Why does my equalizer extension do nothing on Spotify?
Almost certainly because it taps the media element, which protected playback refuses. It is a limitation of the approach rather than a fault in that particular extension.
Does Capo decrypt anything?
No. The samples never leave the context that negotiated the encryption. Capo does not decrypt, copy, record or upload anything.
Does this work in the Spotify or Apple Music desktop apps?
No. Those are native applications and no browser extension can reach them. The web players work.
Is processing protected audio the same as downloading it?
No. Capo has no download, export or recording of any kind. It changes playback as it happens.

Keep reading

Put a capo on everything you listen to.

Add to Chrome — it’s freeAlso on Firefox & Edge · v2.7.6 · no account