DEV Community

Cover image for I solved an annoying issue by building my own real-time audio Chrome extension
B.G
B.G

Posted on

I solved an annoying issue by building my own real-time audio Chrome extension

Hey guys,

this is my first ever post in DEV Community and I think even posting at all. Ok, except few photos on Instagram. As many of you I'm somewhere on my learning journey in web development. My latest project is a Chrome real-time audio extension - equalizer. And this post is about some interesting bugs and what actually learned along the way.

What made me think about building a browser extension at first place? Pretty standard situation. I'm using small 4'' speakers powered by some cheap 90s amp. Really basic set-up responsible for the main part of the issue. The other part is the audio source – my browser. Lot of creators, I'm watching, have pretty hard time mixing voice over music, sounds, etc. I'm not saying it's easy, some times it's just impossible to listen.
So it was obvious there should be some great equalizer extension out there. And there are maybe, but most popular and free haven't solved my problem. I can't really imagine what's possible or not regarding audio in the browser, soo...
I find the topic interesting enough to get engaged and create a simple, but effective extension.

It's called FreqWave EQ a Chrome extension that provides an 8-band equalizer and voice-enhancement modes for improving playback audio (videos, podcasts, movies) in the browser. It uses React, TypeScript, Vite, TailwindCSS and the Web Audio API. You can try it out from the store.

Lesson one: your ears will catch bugs that tests won't

The first serious bug in the project was that audio through the extension was quieter than the same audio bypassed. Only slightly. Not something you'd notice in code review, or a unit test, or even a first listen. But if you A/B the extension on and off with the same podcast, the "on" state was noticeably softer.
The cause was almost embarrassing. The Master Volume knob's default position mapped to gain = 0.089 instead of gain = 1.0. Pre-Amp's default mapped to gain = 0.331. Multiplied together, the audio was being attenuated a lot at what the UI was calling "0 dB, default." The lesson isn't "test your gain math" — that's obvious in retrospect. The lesson is that some categories of bugs only reveal themselves when you actually use the thing in the way the user will. If I'd been writing code and running tests, I might have shipped this. I found it because I was listening. For audio software, subjective listening is the test suite.
If you build anything sensory — audio, visual, haptic — the last debug pass has to be with your actual senses. No amount of green checkmarks replaces that.

Lesson two: don't accept the first diagnosis of a hard bug

Late in the project, I discovered that when the extension was active on a tab, the tab couldn't enter fullscreen. YouTube's fullscreen button did nothing. This would have been a launch-killing bug — video watching is the number one use case for browser audio enhancement.
The initial diagnosis from the AI assistant I got was: "This is a Chrome platform restriction. chrome.tabCapture prevents fullscreen on captured tabs. There's no clean fix; you can only tear down capture on fullscreen enter and rebuild on exit — which means no audio processing during fullscreen video."
The reason I didn't accept it was that I remembered I had researched a competing extensions and still have few of them installed. So it was a quick check and of course fullscreen was working without any restrictions. Also, the Chrome documentation for tabCapture includes a fullscreen property in the captured tab's state — that property wouldn't exist if the platform prevented fullscreen on captured tabs.
The real bug turned out to be in how the offscreen document was consuming the MediaStream. I found a reference implementation in a repo on GitHub — a working extension using the exact same architectural pattern, MIT licensed. Once I compared the two implementations, the fix was small.
The lesson: when a diagnosis says "this can't be fixed," look for a working example that proves otherwise. Working code and real product are stronger evidence than any analysis. Especially in browser extension land, where the platform quirks are numerous and the documentation is sometimes confusing.

Lesson three: from the label to the real feature

The extension has a "Voice Enhancer" section (its main feature) with four modes: Off, Dialogue, Leveler, and Clarity. I labeled the section "DSP Algorithmic Presets" in the UI, without thinking too much and left it as a "reminder" for later.
At one point I stopped and looked at the actual code behind those modes. As originally implemented Dialogue, Clarity, Leveler were just fixed EQ curves — preset positions of the 8 band sliders. There was no DSP happening. It was the time to figure out how to implement it in the easiest and effective way. I decided to take one of the modes and develop it further by adding a DynamicsCompressorNode to the audio graph and wired the Leveler mode to activate it with proper parameters. Now Leveler is a real "leveler" — it evens out quiet dialogue and loud peaks.
This is not a bug, but important decision how to make the extension useful.

The technical shape of the extension

For anyone building something similar: FreqWave EQ is a Manifest V3 Chrome extension. The architecture has three execution contexts communicating via chrome.runtime messages — a React popup for the UI, a service worker as coordinator, and an offscreen document hosting the Web Audio graph. The audio engine runs in the offscreen document because MV3 service workers can't use the Web Audio API. All state persists via chrome.storage.sync, so settings survive Chrome restart. Screen capture is sticky to the tab it started on.

You can reach out for more details, questions, requests or just a chat.

What's next

Per-site EQ profiles are the next real feature — the extension will remember and auto-load your curve based on the site you're on, so Spotify gets your Spotify profile and podcasts get your podcast profile without needing to switch manually. Edge Add-ons submission has been just reviewed and approved too. I hope to gather a real user feedback which can shape further the upcoming release.

Final thoughts

It is my first time publishing something to an official marketplace, where other people can use it. It feels pretty nice. The other great factor is that the tools is simple and convenient to use. I'm noticing improvements in the audio quality exactly where I need them. It's making me curious how far it can get and how precise and narrow the control could be.

What about you? Do you have some similar experience to share? Do you use any extensions for audio control in the browser?
You can share what's on your mind in the comments – any feedback is also welcome.

The source code is on GitHub if you're curious about the architecture or want to see how something like this actually gets structured.

Thanks for reading!

Top comments (0)