The problem
Teamfight Tactics Set 10 shipped a modular soundtrack: each band's song split into stems that the game layers depending on your board. Outside the game, you can't play with them. I wanted a mixer that plays those stems in perfect sync, lets me arrange them, and in time follows my live board the way the game does.
What I built
A Windows desktop app on ow-electron, Overwolf's build of Electron, with a React and TypeScript interface. The mixer plays any combination of the 60 stems; stems checked mid-song join in time. A second window, the track builder, arranges stems on a timeline: each clip opens its stem for a stretch of the song, snaps to the beat grid, and saves as you go. The app also connects to Overwolf's Game Events Provider and shows the match state and board live. Separately, a set of Python tools transcribes the stems and maps chords, phrases and the clean places to cut, bar by bar.
Technical challenges
- Sample-accurate sync. Every stem plays against one frame counter in an AudioWorklet. Decoders run up to two seconds ahead and post chunks tagged with the exact frame they must play at.
- Starting anywhere. To start a stem mid-song I index its Ogg Vorbis packets myself, reading block sizes from the codec's setup header the way FFmpeg does, and check the total against every page's granule position.
- Two tempos. Early stems run at 140 BPM and loop on 3:29, late ones at 90 BPM on 2:53, so loops and grids are defined per phase.
- Clean fades. Gains ramp over 6 ms whenever a stem joins, leaves or recovers, so nothing clicks.
Outcome
The manual mixer and the track builder work, and the live board shows up in game. Following the board automatically is the next step.