The Web MIDI API[0] used by the author has a built-in precise scheduler, that has higher precision and works better than the unreliable setTimeout approach used by OP when coupled with the Performance API[1].
Pass a timestamp as the second argument to midiOutput.send(data, timestamp), calculated with performance.now. Something like midiOutput.send(data, performance.now() + offset)