<midi-player>
and <midi-visualizer>
HTML elements powered by @magenta/music (Magenta.js), fully stylable and scriptable.
- Simple demo
- Advanced demo
- Website [source] with MIDI file upload
Notable websites that use html-midi-player include abcnotation.com, Musical Nexus and demo websites for music generation models: piano infilling, stochastic positional encoding.
If you use html-midi-player on your website, please consider linking back to the repository.
-
Add the necessary scripts to your page:
<script src="https://cdn.jsdelivr.net/combine/npm/tone@14.7.58,npm/@magenta/music@1.23.1/es6/core.js,npm/focus-visible@5,npm/html-midi-player@1.5.0"></script>
-
Add a player and a visualizer:
<midi-player src="https://magenta.github.io/magenta-js/music/demos/melody.mid" sound-font visualizer="#myVisualizer"> </midi-player> <midi-visualizer type="piano-roll" id="myVisualizer"></midi-visualizer>
That's it!
Besides jsDelivr, the bundle is also available from cdnjs.
You can also add the package to your project from NPM, e.g. npm install --save html-midi-player or yarn add html-midi-player. Then you can either:
import 'html-midi-player'in your JavaScript code (as an ES Module), or- add the
node_modules/html-midi-player/dist/midi-player.min.jsbundle directly to your page, along with the dependencies (node_modules/tone/build/Tone.js,node_modules/@magenta/music/es6/core.js; note that these need to go beforehtml-midi-player).
In both cases, you should also add the focus-visible polyfill to enable outlines on keyboard focus.
The basic features of html-midi-player are explained below. Wherever both HTML and JavaScript examples are given, they are equivalent. In the JavaScript examples, player and visualizer refer to the corresponding custom element objects, which can be obtained using standard DOM methods like document.getElementById('#myPlayer') or document.querySelectorAll('midi-player'), for example.
See also the API reference for both elements:
midi-player,
midi-visualizer.
Both midi-player and midi-visualizer support two different ways of specifying the input file:
- By setting the
srcattribute to a MIDI file URL, e.g.:<midi-player src="twinkle-twinkle.mid"></midi-player>
player.src = "twinkle-twinkle.mid";
- By assigning a Magenta
NoteSequenceto thenoteSequenceproperty, e.g.:To obtain aplayer.noteSequence = TWINKLE_TWINKLE;
NoteSequence, you can use Magenta functions likeurlToNoteSequence()(see FAQ).
By default, the player will use a simple oscillator synth. To use a SoundFont, add the sound-font attribute:
<midi-player sound-font></midi-player> <!-- default SoundFont (same as below) -->
<midi-player sound-font="https://storage.googleapis.com/magentadata/js/soundfonts/sgm_plus"></midi-player>player.soundFont = null; // no SoundFont
player.soundFont = ''; // default SoundFont (same as below)
player.soundFont = 'https://storage.googleapis.com/magentadata/js/soundfonts/sgm_plus';See the Magenta.js docs for a list of available SoundFonts.
To make the player loop, use the loop attribute:
<midi-player loop></midi-player>player.loop = true;The visualizer type is specified via the type attribute. Three visualizer types are supported: piano-roll, waterfall and staff.
Each visualizer type has a set of settings that can be specified using the config attribute (only from JavaScript), e.g.:
visualizer.config = {
noteHeight: 4,
pixelsPerTimeStep: 60,
minPitch: 30
};The settings are documented in the Magenta.js docs.
A player supports binding one or more visualizers to it using the visualizer attribute (a selector) or the addVisualizer method:
<midi-player visualizer="#myVisualizer, #myOtherVisualizer"></midi-player>player.addVisualizer(document.getElementById('myVisualizer'));
player.addVisualizer(document.getElementById('myOtherVisualizer'));The visualizer only gets updated while the player is playing, which allows a single visualizer to be bound to multiple players.
The player supports listening to different kinds of events using the player.addEventListener() method. See the API reference for the available event types.
Here are some frequently asked questions about html-midi-player. Make sure to also check discussions and issues to see if your question is answered there.
The player supports "SoundFonts" in a special format designed by Magenta. If you want to use a .sf2 file, it will not work out of the box, but it is possible to convert it with some effort. See this discussion thread and especially this answer, which proposes a conversion script.
The Magenta.js core and core/sequences modules define functions for loading and manipulating NoteSequences. To load a MIDI file as a NoteSequence, use the urlToNoteSequence() function. Other useful functions are clone(), trim() and concatenate().
If you are using the provided bundle as suggested above, then the core module will be available simply as core, so you will be able to call e.g. core.urlToNoteSequence() or core.sequences.clone() from your code.
This library is a relatively thin wrapper around Magenta.js, which provides all of the MIDI loading, synthesis and visualization functionality. This means it inherits most of its limitations. If you found an issue, try to check if Magenta.js is also affected, e.g. using this or this demo (click Load MIDI File to upload your own file). If the issue is still there, then this is most likely a Magenta.js issue and cannot be fixed here (although a workaround may be possible). Otherwise, feel free to open an issue (or even better, a pull request) here, but please check for existing issues and discussions first.
- Only one player can play at a time. Starting a player will stop any other player which is currently playing. (#1) This can actually be a benefit in many cases.
- Playback position only gets updated on note onsets. This may cause the player to appear stuck.