如何实现node-easymidi与FL Studio同时读取MIDI键盘输入?
解决Windows下FL Studio与Node.js共享MIDI输入设备的问题
嘿,这个问题我之前也踩过坑!本质是Windows下MIDI设备的独占访问冲突——你用的node-easymidi底层依赖的WinMM API默认会独占式打开MIDI输入设备,而FL Studio运行时已经把你的CASIO USB-MIDI键盘占住了,导致Node应用启动时抛出「no MIDI input devices currently available」的错误。下面给你几个靠谱的解决思路:
方法1:调整FL Studio的MIDI设备访问权限(最简单)
不用改代码,直接在FL Studio里设置共享:
- 打开FL Studio,点击顶部菜单栏的「Options」→「MIDI Settings」
- 在输入设备列表里找到你的「CASIO USB-MIDI 0」,把它的Access Mode(访问模式)改成「Share」(共享)或者「Multiplex」(多路复用)(不同FL Studio版本叫法可能略有差异)
- 保存设置后重启FL Studio,这样它就不会独占设备,Node应用就能同时连接了
方法2:改用node-midi的WinRT后端(支持共享访问)
node-easymidi是node-midi的简化封装,它默认用了独占式的WinMM后端。直接使用node-midi并指定支持共享的WinRT后端就能解决问题,示例代码如下:
const midi = require('midi'); // 初始化WinRT后端的MIDI输入(支持多应用共享设备) const input = new midi.Input(midi.Backend.WINRT); // 列出所有可用MIDI输入设备 const portCount = input.getPortCount(); console.log('可用MIDI输入设备:'); for (let i = 0; i < portCount; i++) { console.log(`[${i}] ${input.getPortName(i)}`); } // 打开目标设备(替换成你CASIO设备对应的索引) input.openPort(0); // 监听MIDI消息,解析noteon/noteoff事件 input.on('message', (deltaTime, message) => { const status = message[0]; const note = message[1]; const velocity = message[2]; // 识别noteon(状态码144且力度>0) if (status === 144 && velocity > 0) { console.log(`noteon: { note: ${note}, velocity: ${velocity} }`); } // 识别noteoff(状态码128 或 144但力度=0) else if (status === 128 || (status === 144 && velocity === 0)) { console.log(`noteoff: { note: ${note} }`); } }); // 程序退出时关闭设备(避免资源泄漏) process.on('SIGINT', () => { input.closePort(); process.exit(); });
注意:确保你的node-midi是v0.9.0及以上版本,这样才支持WinRT后端。如果版本不够,先执行npm install midi@latest升级。
方法3:用虚拟MIDI端口中转(兜底方案)
如果上面两种方法都不适用,可以借助虚拟MIDI工具实现设备共享:
- 下载安装loopMIDI这类虚拟MIDI端口工具
- 打开工具创建一个虚拟端口(比如命名为「Virtual MIDI Hub」)
- 使用MIDI中转工具(比如MIDI-OX),把物理CASIO键盘的输入转发到这个虚拟端口
- 让FL Studio和Node应用分别连接这个虚拟端口,两者就能同时接收MIDI输入了
为什么会出现这个问题?
Windows传统的WinMM MIDI API设计是独占式的,同一时间只能有一个应用访问设备;而微软新推出的Windows MIDI Services(WinRT)支持多应用共享MIDI设备,这也是方法2能解决问题的核心原因。node-easymidi目前没有提供切换后端的接口,所以直接用node-midi更灵活。
内容的提问来源于stack exchange,提问作者ー PupSoZeyDe ー
相关产品推荐
相关产品推荐

