npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-midi-api

v0.1.0

Published

A native Web MIDI API polyfill for React Native (iOS, Android & Web) — talk to USB & BLE MIDI hardware with the standard requestMIDIAccess surface. Drop-in replacement for @motiz88/react-native-midi.

Downloads

843

Readme

react-native-midi-api

npm version License: MIT CI

A native Web MIDI API polyfill for React Native — talk to USB & BLE MIDI hardware from iOS, Android, and Web with the standard requestMIDIAccess surface. MIDI 1.0 + SysEx.

Built as a modern, maintained drop-in replacement for the abandoned @motiz88/react-native-midi: same public API, correctness improvements (stable port maps, standard MIDIMessageEvent), and no third-party native MIDI pod.

Platform support

| Platform | Transport | Minimum version | Status | | --- | --- | --- | --- | | Web | navigator.requestMIDIAccess (browser Web MIDI passthrough) | Any Web-MIDI-capable browser | ✅ | | iOS | CoreMIDI — USB-MIDI | iOS 14+ | ✅ | | Android | android.media.midi — USB-MIDI | API 24+ (Android 7) | ✅ | | BLE-MIDI | Bluetooth LE MIDI | — | 🔜 planned — PRs welcome! |

BLE-MIDI note: The consuming app can do BLE MIDI separately today via react-native-ble-manager. Native BLE-MIDI transport integrated directly into this library is planned. See the tracking issue Odisei-Music/Odisei-Play#1143 — contributions welcome.

Install

npx expo install react-native-midi-api
# or
npm install react-native-midi-api

This is an Expo module. In a managed Expo or Expo-prebuild app it autolinks with no extra steps. In a bare React Native app, follow installing Expo modules once, then npx pod-install for iOS.

Peer dependencies: expo, react, react-native — these must be present in the consuming app (never auto-installed).

Usage

import { requestMIDIAccess } from "react-native-midi-api";
import type { MIDIMessageEvent, MIDIConnectionEvent } from "react-native-midi-api";

// Request access (sysex: false by default).
const midi = await requestMIDIAccess({ sysex: false });

// Enumerate connected inputs and attach listeners.
for (const input of midi.inputs.values()) {
  console.log("Input:", input.name, input.manufacturer);
  input.onmidimessage = (event: MIDIMessageEvent) => {
    const [status, data1, data2] = event.data; // Uint8Array
    console.log("MIDI in:", status.toString(16), data1, data2);
  };
}

// Enumerate connected outputs and send a Note On
// (channel 1, note 64, velocity 127).
const output = [...midi.outputs.values()][0];
output?.send([0x90, 0x40, 0x7f]);

// Schedule a Note Off 500 ms from now.
output?.send([0x80, 0x40, 0x00], performance.now() + 500);

// React to devices connecting / disconnecting (hotplug).
midi.onstatechange = (event: MIDIConnectionEvent) => {
  const port = event.port;
  console.log(port?.name, "→", port?.state, port?.connection);
};

The surface mirrors the W3C Web MIDI API — refer to the MDN docs for full semantics.

Requesting SysEx access

System Exclusive (0xF0 … 0xF7) messages require explicit opt-in:

// Enable SysEx in both directions.
const midi = await requestMIDIAccess({ sysex: true });

// Send a SysEx message.
output?.send([0xf0, 0x41, 0x10, 0x00, 0x00, 0x00, 0x28, 0x12, 0xf7]);

// Inbound SysEx arrives through onmidimessage as normal.
input.onmidimessage = (e: MIDIMessageEvent) => {
  if (e.data[0] === 0xf0) console.log("SysEx:", e.data);
};

Without { sysex: true }, calling send() with a 0xF0 start byte throws InvalidAccessError, and incoming SysEx bytes are filtered out silently. This gating applies in both directions — outbound and inbound.

API

Full API reference (all exports, type signatures, and TSDoc annotations) is available at midi.odiseimusic.com (coming soon — the site builds from source on every merge to main).

Quick reference

| Export | Kind | Notes | | --- | --- | --- | | requestMIDIAccess(options?) | function | { sysex?, software? } → Promise<MIDIAccess>. On Web, resolves the browser's native access. | | MIDIAccess | interface | inputs / outputs (stable ReadonlyMaps), sysexEnabled, onstatechange, statechange event. | | MIDIPort | interface | id, manufacturer, name, type, version, state, connection, open(), close(), onstatechange. | | MIDIInput | interface | Extends MIDIPort; onmidimessage + standard midimessage event. | | MIDIOutput | interface | Extends MIDIPort; send(data, timestamp?), clear(). | | MIDIInputMap / MIDIOutputMap | type | ReadonlyMap<string, MIDIInput | MIDIOutput>. | | MIDIMessageEvent | class | Standard event; .data: Uint8Array, .receivedTime. | | MIDIConnectionEvent | class | Standard event; .port: MIDIPort | null. | | MIDIOptions | interface | { sysex?: boolean; software?: boolean }. | | InvalidAccessError / InvalidStateError | class | Thrown for disallowed SysEx / disconnected-port sends. | | validateMidiMessage / getChannelMessageLength | function | Low-level helpers for parsing raw MIDI bytes. |

Platform notes

  • Web: Requires a Web-MIDI-capable browser (Chrome / Edge). Safari does not support Web MIDI natively — a MIDI polyfill extension may be needed.
  • iOS: Requires iOS 14+. CoreMIDI is the underlying transport. USB-MIDI devices are plug-and-play. No external native pod is required.
  • Android: Requires API level 24+ (Android 7 Nougat). Uses the android.media.midi system API. USB-MIDI devices are plug-and-play.

Contributing

Bug reports and pull requests are welcome on GitHub. Please follow the Conventional Commits style used in this repo.

BLE-MIDI is explicitly unimplemented and contributions for it are especially welcome. Please open an issue to discuss the approach before sending a large PR, so we can align on the transport design.

Acknowledgments

  • @motiz88/react-native-midi (MIT, © 2022 Moti Zilberman) — the reference Web MIDI surface and Expo module structure this package is modeled on. SimpleEventTargetImpl and validateMidiMessage are direct adaptations (the latter ultimately deriving from Chromium's BSD-licensed Web MIDI implementation). The Android MIDI framing logic (MidiConstants.kt, MidiFramer.kt, MidiMessageReassembler.kt) is adapted from the same upstream project's Android port, which itself derives from AOSP's MidiFramer.java / MidiConstants.java. See NOTICE.
  • react-native-audio-api MIDI draft by Software Mansion (MIT, © 2024 Software Mansion) — architectural reference for the modern CoreMIDI integration approach. See NOTICE.

License

MIT © 2026 Odisei Music S.L.