Technology Sep 05, 2026 · 6 min read

How we made a MIDI controller run our browser radio studio

A live radio screen is fine until the host has to do three things at once. The mouse becomes the wrong tool the moment you need to open a mic, pull music down, and hit a jingle without looking away. That is when we decided our browser studio had to understand cheap MIDI controllers. What...

DE
DEV Community
by Mike
How we made a MIDI controller run our browser radio studio

A live radio screen is fine until the host has to do three things at once. The mouse becomes the wrong tool the moment you need to open a mic, pull music down, and hit a jingle without looking away.

That is when we decided our browser studio had to understand cheap MIDI controllers.

What I wanted from the hardware

The Broadcast Studio at Tunio already ran in the browser. It had a mixer, pad grid, mic channels, guest links, a master section, recording, and a Go Live button. When nobody was live, the stream played the scheduled rotation. When the host stopped, the rotation came back.

That worked with a mouse.

But live radio has a body memory to it. A fader should be under a finger. A jingle should be on a pad. Mute and cue should be buttons you can find without thinking.

I did not want people to install a studio app, route audio through OBS, or buy a sound card just to get that feeling. The constraint was simple and annoying: keep the studio in the browser, but make it feel less like a web page.

Web MIDI gave us the door. In Chrome and Edge, the browser can see USB-MIDI devices. A user plugs in a controller, opens the studio, and the device can send notes, knobs, faders, and button presses straight into the page.

Internet radio setup: a laptop running Tunio's Broadcast Studio, a MIDI controller and headphones

That sounded easy at first. It was not.

The hard part was not receiving MIDI

Reading MIDI messages is the small part. The harder question was: what should a message mean?

Different controllers describe the same human action in different ways. A pad may send a note. A button may send a control change. A fader sends a stream of values. Some controls send one value on press and another on release.

I did not want a settings screen where the user had to know any of that. Most radio hosts do not care about note numbers or CC values. They want to click “bind”, touch a control, and move on.

So we built MIDI Learn around the action, not around the protocol.

The user picks a thing in the studio: a jingle pad, a channel level, Go Live, Mute, CUE, start or stop. Then they touch the hardware control. We watch what comes in for a short moment.

If it behaves like one press, it becomes a button binding. If it sweeps through a range, it becomes a fader or knob binding. The studio decides the type from the movement instead of making the user choose it.

That small decision removed a lot of friction. It also made the code more careful. We had to wait long enough to tell a click from a sweep, but not so long that binding felt slow. Too eager, and a fader can look like a button. Too cautious, and the UI feels like it is ignoring you.

I still do not love that edge. The interface hides complexity, but the complexity does not disappear. It just moves into our timing rules.

Matching the controller instead of forcing our layout

The next problem was shape.

Controllers are not standard in the way a keyboard is standard. One person has 8 pads. Another has 16. One has a 4×4 grid. Another has pads in a row. Some have faders next to pads. Some only have knobs.

Our rule became: the screen should copy the hardware where it matters.

So the studio settings let the user set the number of pads and how many pads sit in a row. If the controller is 4×4, the on-screen pad grid can be 4×4. If it is 8 across, the screen can match that too.

This sounds cosmetic. It is not. When someone presses the top-left hardware pad, they expect the top-left on-screen jingle to fire. If the shapes do not match, the host has to translate under pressure. That is exactly what hardware is meant to avoid.

Studio settings: hotkeys and MIDI bindings, pad grid size, mixer channel matrix

Mixer channels had a different issue. A jingle pad is stable. A guest channel is not.

If “Guest 1” is bound to a fader, what happens when that guest leaves and another person joins? We decided the binding should attach to the slot, not the human. The first guest seat stays on that fader. Whoever is in that seat gets controlled by it.

That is less personal, but more useful. The operator keeps the same hand position. The show can change without breaking the controller map.

We used the same idea for channel actions. Air, Mute, CUE, and level can each be placed on different hardware controls. Some controllers have a neat strip per channel. Many do not. We could not assume a perfect mixer surface.

The controller also had to answer back

Listening to hardware was only half of it.

A real console tells you state. A button lights when a channel is on. A mute key stays lit. You do not have to stare at the screen to know what is happening.

So we made the studio send MIDI back to the controller where the device supports it. When a channel goes on air or gets muted, the matching hardware button can light up.

This made the system feel much more like an instrument. It also created another source of truth problem.

The broadcast state can change from the mouse, a hotkey, the MIDI controller, or the studio itself. The lights cannot just reflect the last MIDI action. They have to reflect the actual state of the broadcast.

That pushed us to treat MIDI output as a view of studio state, not as a side effect of button presses. When state changes, update the screen and the controller. That is a cleaner model, and I wish we had started there in every part of the studio.

There are still limits I do not like. Safari does not support Web MIDI, so this is not a universal browser feature. Controllers also vary a lot. “Plug in and learn” works because we avoid asking users to understand MIDI, but MIDI is still old, loose, and full of device quirks.

The part I am happiest with is that the browser stopped feeling like the weak link. A laptop, a web page, and a small controller can run a live show with pads, faders, cue, mute, guests, and automatic return to the scheduled stream after Stop.

If you have built browser control for physical hardware, how did you handle device differences without turning the settings screen into a MIDI manual?

DE
Source

This article was originally published by DEV Community and written by Mike.

Read original article on DEV Community
Back to Discover

Reading List