{"_id":"@do-re-mi-fa-so/airmidi","name":"@do-re-mi-fa-so/airmidi","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@do-re-mi-fa-so/airmidi","version":"0.1.0","publishConfig":{"access":"public"},"description":"BLE-MIDI over Web Bluetooth — connect to BLE MIDI devices directly from the browser.","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"sideEffects":false,"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","build:docs":"node scripts/build-docs.mjs","prepublishOnly":"npm run typecheck && npm test && npm run build"},"keywords":["midi","ble-midi","bluetooth","web-bluetooth","web-midi"],"author":{"name":"c3v6a2vy"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/do-re-mi-fa-so/airmidi.git"},"homepage":"https://github.com/do-re-mi-fa-so/airmidi#readme","bugs":{"url":"https://github.com/do-re-mi-fa-so/airmidi/issues"},"engines":{"node":">=18"},"devDependencies":{"@types/web-bluetooth":"^0.0.20","tsup":"^8.3.5","typescript":"^5.6.3","vitest":"^2.1.4"},"gitHead":"cbf9ee655e33a67ad795c643ad1154077f6e340a","_id":"@do-re-mi-fa-so/airmidi@0.1.0","_nodeVersion":"23.2.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-U5Zix9mnmLd7YrT2oFJnaqvk3/u2uZv0TXzIl9veLKqpH4wILH36bwnw+PoAVjmwnlSEMMmfJmAPpPruvHe9EQ==","shasum":"829157c3a9df0f7e307374cd92cab5e1c7a046ac","tarball":"https://registry.npmjs.org/@do-re-mi-fa-so/airmidi/-/airmidi-0.1.0.tgz","fileCount":9,"unpackedSize":76427,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCiHfFeOt6yNKe5gF5fDRfq0Ylk2krN7DZwGfLZ+/UYLQIga8UG+/pwBqx0Oa442Un2y3q3m4gr1kceCnatHSLf5dA="}]},"_npmUser":{"name":"c3v6a2vy","email":"c3v6a2vy@protonmail.com"},"directories":{},"maintainers":[{"name":"c3v6a2vy","email":"c3v6a2vy@protonmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/airmidi_0.1.0_1786178954766_0.259719442216769"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-08T08:49:14.570Z","0.1.0":"2026-08-08T08:49:14.900Z","modified":"2026-08-08T08:49:15.072Z"},"maintainers":[{"name":"c3v6a2vy","email":"c3v6a2vy@protonmail.com"}],"description":"BLE-MIDI over Web Bluetooth — connect to BLE MIDI devices directly from the browser.","homepage":"https://github.com/do-re-mi-fa-so/airmidi#readme","keywords":["midi","ble-midi","bluetooth","web-bluetooth","web-midi"],"repository":{"type":"git","url":"git+https://github.com/do-re-mi-fa-so/airmidi.git"},"author":{"name":"c3v6a2vy"},"bugs":{"url":"https://github.com/do-re-mi-fa-so/airmidi/issues"},"license":"MIT","readme":"# airmidi\n\nConnect to BLE-MIDI peripherals directly from the browser via the [Web Bluetooth API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API) — no OS-level MIDI pairing required. The connection is bi-directional over a single GATT characteristic: send messages to the peripheral and receive messages from it (notes played on the device itself, or by anything else routed to it) on the same `connection`.\n\nThis is a different approach from wrapping [`navigator.requestMIDIAccess()`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/requestMIDIAccess) (what [`webmidi`](https://webmidijs.org/) does): it talks to the [BLE-MIDI GATT service](https://midi.org/specifications/midi-transports-specifications/bluetooth-le-midi) directly, so it works anywhere Web Bluetooth is supported, even on platforms where the Web MIDI API doesn't surface BLE devices.\n\n**[Live demo →](https://do-re-mi-fa-so.github.io/airmidi/)** — connect to a real device and play a virtual keyboard that sends and receives: notes you click are sent to the device, and notes played on the device light the same keys back up. Also try the parser/encoder without any hardware.\n\n## Browser support\n\nRequires [Web Bluetooth](https://caniuse.com/web-bluetooth) — Chrome, Edge, Opera, and Android WebView. Not supported in Safari or Firefox.\n\n## Install\n\n```sh\nnpm install airmidi\n```\n\n## Usage\n\n```ts\nimport { connectBleMidi } from \"airmidi\";\n\n// Opens the browser's Bluetooth device picker, scoped to BLE-MIDI devices,\n// and connects to the MIDI I/O characteristic.\nconst connection = await connectBleMidi();\n\n// Receive — fires for messages coming from the peripheral (notes played on\n// the device itself, or by anything else routed to it).\nconnection.addEventListener(\"midimessage\", (event) => {\n  const { data, timestamp } = event.detail;\n  console.log(\"received\", Array.from(data), \"at\", timestamp);\n});\n\nconnection.addEventListener(\"disconnected\", () => {\n  console.log(`${connection.deviceName} disconnected`);\n});\n\n// Send — same connection, same characteristic, the other direction.\n// Note On (channel 0, note 60, velocity 100).\nawait connection.send({ data: [0x90, 0x3c, 0x64] });\n\nconnection.disconnect();\n```\n\n### Lower-level pieces\n\n`requestBleMidiDevice()` and `BleMidiConnection.connect()` are exposed separately if you want to manage device selection and connection independently:\n\n```ts\nimport { requestBleMidiDevice, BleMidiConnection } from \"airmidi\";\n\nconst device = await requestBleMidiDevice();\nconst connection = await BleMidiConnection.connect(device);\n```\n\n`BleMidiParser` and `encodeBleMidiPackets` implement the raw BLE-MIDI packet framing (header/timestamp bytes, running status, SysEx chunking) and have no Web Bluetooth dependency, so they can be reused outside the browser (e.g. against a `noble`-based GATT connection in Node) or tested in isolation.\n\n## Development\n\n```sh\nnpm install\nnpm test        # vitest\nnpm run build   # tsup -> dist/\nnpm run typecheck\n```\n\n`docs/` is the source for the GitHub Pages demo (served from `/docs` on `main`). It vendors a copy of the built library — after changing `src/`, regenerate it with:\n\n```sh\nnpm run build:docs   # builds the library, then copies dist/index.js to docs/airmidi.js\n```\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_rev":"1-a4ba242fe388162623ba27652bf38b70"}