Signatur
Beschreibung
MIDIInput steht für einen einzelnen MIDI-Eingangsport, etwa ein USB-Keyboard, einen Controller mit Drehreglern oder einen virtuellen MIDI-Bus. Die Schnittstelle erbt von MIDIPort und damit auch von EventTarget. Eigenschaften wie id, name, manufacturer, state und connection sowie die Methoden open() und close() sind also verfügbar.
Eine eigene Methode oder einen Konstruktor hat MIDIInput nicht. Instanzen bekommt man ausschließlich über navigator.requestMIDIAccess(). Das zurückgelieferte MIDIAccess-Objekt enthält in inputs eine MIDIInputMap (eine Map-ähnliche Struktur, die von der ID auf den MIDIInput verweist).
Das Wichtigste an der Schnittstelle ist das Ereignis midimessage. Es wird für jede eingehende MIDI-Nachricht ausgelöst und liefert ein MIDIMessageEvent. Dessen Eigenschaft data ist ein Uint8Array mit den Rohbytes: Statusbyte (Nachrichtentyp und Kanal) und Datenbytes (z. B. Notennummer und Anschlagstärke). Man registriert den Handler über addEventListener("midimessage", …) oder die Eigenschaft onmidimessage.
Typische Einsatzfälle sind Web-Synthesizer (zusammen mit der Web Audio API), Lern-Apps für Musikinstrumente, das Steuern von Visualisierungen mit Hardware-Controllern und Diagnose-Werkzeuge, die MIDI-Nachrichten mitschneiden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $onmidimessage | ((event: MIDIMessageEvent) => void) | null | null | Handler-Eigenschaft für das Ereignis midimessage. Wird sie gesetzt, öffnet der Browser den Port automatisch (implizites open()). |
| $event.data | Uint8Array | Rohbytes der MIDI-Nachricht im MIDIMessageEvent. data[0] ist das Statusbyte, danach folgen die Datenbytes. |
|
| $event.timeStamp | DOMHighResTimeStamp | Empfangszeitpunkt in Millisekunden, vergleichbar mit performance.now(). |
Rückgabewert
MIDIAccess.inputs bereitgestellt. Geerbt von MIDIPort sind unter anderem type (immer "input"), state ("connected" oder "disconnected") und connection ("open", "closed" oder "pending").Beispiele
Alle MIDI-Eingänge auflisten
const listInputs = async () => {
if (!navigator.requestMIDIAccess) {
console.warn('Web MIDI wird nicht unterstützt');
return;
}
const access = await navigator.requestMIDIAccess();
for (const input of access.inputs.values()) {
console.log(`${input.name} (${input.manufacturer}) – ${input.state}`);
}
};
listInputs();
Note-On/Note-Off mit addEventListener auswerten
const noteName = (n) =>
['C','C#','D','D#','E','F','F#','G','G#','A','A#','H'][n % 12] + (Math.floor(n / 12) - 1);
const handleMessage = (event) => {
const [status, note, velocity] = event.data;
const command = status & 0xf0;
const channel = (status & 0x0f) + 1;
// Note-On mit Anschlagstärke 0 gilt laut MIDI-Standard als Note-Off
if (command === 0x90 && velocity > 0) {
console.log(`Kanal ${channel}: ${noteName(note)} an (Anschlagstärke ${velocity})`);
} else if (command === 0x80 || (command === 0x90 && velocity === 0)) {
console.log(`Kanal ${channel}: ${noteName(note)} aus`);
}
};
const access = await navigator.requestMIDIAccess();
access.inputs.forEach((input) => {
input.addEventListener('midimessage', handleMessage);
});
Handler per onmidimessage setzen und wieder entfernen
const access = await navigator.requestMIDIAccess();
const [input] = access.inputs.values();
if (input) {
// Controller-Änderungen (CC) mitschneiden, z. B. für Drehregler
input.onmidimessage = ({ data }) => {
if ((data[0] & 0xf0) === 0xb0) {
console.log(`CC ${data[1]} = ${data[2]}`);
}
};
// Nach 10 Sekunden Mitschnitt beenden und Port freigeben
setTimeout(async () => {
input.onmidimessage = null;
await input.close();
console.log('Port geschlossen:', input.connection);
}, 10_000);
}
Anschließen und Trennen von Geräten erkennen
const access = await navigator.requestMIDIAccess();
access.addEventListener('statechange', ({ port }) => {
if (port.type !== 'input') return;
console.log(`${port.name}: ${port.state}`);
if (port.state === 'connected') {
port.onmidimessage = (e) => console.log('Daten:', [...e.data]);
}
});
// Wichtig · Fallstricke
- Browser-Unterstützung: Chromium-Browser unterstützen die Web MIDI API seit Langem, Firefox seit Version 108 (mit Berechtigungsabfrage und Site-Permission-Add-on). Safari unterstützt sie nicht. Vor der Nutzung sollte man immer mit
'requestMIDIAccess' in navigatorprüfen, ob die API vorhanden ist. - Sicherer Kontext und Berechtigung: Die API funktioniert nur über HTTPS (oder
localhost) und fragt den Nutzer um Erlaubnis. In iframes muss die Permissions Policymidierlaubt sein. - SysEx: System-Exclusive-Nachrichten (Statusbyte
0xF0) kommen nur an, wenn der Zugriff mitrequestMIDIAccess({ sysex: true })angefordert wurde. Das löst eine eigene, strengere Berechtigungsabfrage aus, weil SysEx die Firmware eines Geräts verändern kann. - Implizites Öffnen: Wer
onmidimessagesetzt, öffnet den Port automatisch. BeiaddEventListenerpassiert das in manchen Implementierungen nicht zuverlässig. Im Zweifel vorherawait input.open()aufrufen. - Note-Off-Falle: Viele Geräte senden statt Note-Off (
0x80) ein Note-On (0x90) mit Anschlagstärke 0. Beide Fälle sollten ausgewertet werden. - Laufzeit-Status und Active Sensing:
MIDIMessageEvent.dataenthält immer vollständige Nachrichten mit Statusbyte. Echtzeit-Nachrichten wie Clock (0xF8) oder Active Sensing (0xFE) können sehr häufig kommen und sollten früh herausgefiltert werden, damit die Leistung nicht leidet. - Die
MIDIInputMapist eine Momentaufnahme. Geräte, die später angeschlossen werden, erkennt man über das EreignisstatechangeanMIDIAccess.