websocket配合web midi api可构建低延迟网页midi系统,关键在于音符同步、防堆积与时序补偿:需https授权获取设备、json封装带时间戳消息、web audio精确触发音符,并通过去重、服务端合并及ntp校准实现跨客户端时钟对齐。

WebSocket 可以实现在浏览器中低延迟传输 MIDI 数据,配合 Web MIDI API,就能构建跨平台的实时网页 MIDI 演奏系统——关键不在于“能不能连”,而在于“怎么同步音符、避免堆积、处理时序”。
1. 前提:启用 Web MIDI 并获取输入设备
Web MIDI API 默认禁用,需用户主动授权(Chrome / Edge / Safari 支持,Firefox 仍受限)。页面加载后需调用 navigator.requestMIDIAccess() 获取接口,并监听 midimessage 事件捕获按键/控制器数据:
- 确保页面使用 HTTPS 或 localhost(MIDI API 强制安全上下文)
- 监听 onconnect 和 ondisconnect 动态更新可用设备列表
- 对每个输入端口调用 open() 后绑定 onmidimessage,原始数据是 Uint8Array,前三位通常是 [status, data1, data2](如 [144, 60, 100] 表示按下中央C,力度100)
2. WebSocket 连接与消息结构设计
不建议直接转发原始 MIDI 字节数组。应封装为轻量 JSON,包含必要时序和上下文信息:
- 字段示例:{ "type": "noteon", "note": 60, "vel": 95, "ts": 1723456789123 }(客户端时间戳)
- 服务端不做业务逻辑,仅广播;若需多房间,可在消息中加 room 字段,用 Map 维护连接与房间映射
- 客户端收到后,用 performance.now() 计算本地延迟,动态补偿播放时机(尤其对长连接抖动)
3. 浏览器端实时发声:AudioContext + Web Audio API
避免使用 new Audio() 加载音色文件——延迟高、不可控。推荐用 Web Audio 构建合成器或采样播放器:
- 用 OscillatorNode + GainNode 实现简单方波/锯齿波合成(适合实验)
- 更实用的是预加载 .mp3/.wav 钢琴采样,用 AudioBufferSourceNode 触发,通过 playbackRate 变调(如 C4=261.63Hz → C5=523.25Hz,rate=2)
- 注意:每个音符必须创建独立 source node,且调用 start() 时传入精确时间(如 context.currentTime + latencyCompensation),否则音符会“堆叠”或错拍
4. 关键优化点:防抖、节流与时钟对齐
MIDI 键盘可能高频发送重复 noteon/noteoff,网络可能乱序,音频引擎有调度延迟:
- 客户端对同一音符做“去重”:记录 lastNoteOn[60] 时间,10ms 内重复忽略
- 服务端可对高频消息做微秒级合并(如 5ms 窗口内同 note 的 on/off 合并为最终状态)
- 所有客户端定期(如每 5 秒)向服务端请求一次 NTP-style 时间差,校准本地 performance.now() 与服务端逻辑时钟,用于预测远端音符触发时刻
不需要自建 MIDI 服务器,用 Node.js + ws 库即可承载百人级实时演奏;难点不在连接,而在让每个音符在对方耳朵里“准时落键”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











