Back

试着加了一个 MIDI 播放器

起因

用了 Swup.js 和 Alpine.js 。想做一个简单的音乐播放器来着。以前搞 Hexo Next 的时候,就搞过全站音乐,pjax 支持下,换页音乐不断。

正好电脑上有很多 MIDI 文件,MIDI 文件很小。一个音乐几 KB。用来做博客的背景音乐刚好合适。不过缺点也很明显,MIDI 文件相当于谱子,不是音频文件,不支持人声,播放效果依赖音源库。

MIDI 是一种很老的技术了,不过现在一些领域还是在用。文件体积可以做到非常小——一首几分钟的曲子通常只有几十 KB,甚至几 KB。因为它存储的不是音频波形,而是音符、力度、音色这些演奏指令。缺点就是播放效果依赖音源库,同样的 MIDI 文件在不同设备上听起来可能不太一样。
实际数据大概是 30MB 125h

实现

MIDI 播放器放哪是个小问题。带有音乐播放器的博客一般放在左下角。我这直接模仿手机电脑搞了一个控制中心,放里面了。

使用了 MIDIjs - https://www.midijs.net/ 这是一个纯 JavaScript 的 MIDI 播放器,不需要任何插件,浏览器原生就能跑。

MIDI.js 有好几个同名的库,我也没弄明白哪个是哪个,能用就行。音源也不知道哪来的。好像是这个 https://github.com/babelsberg/babelsberg-js/blob/master/midijs/ 里的。

写起来不麻烦。很快写了个 shortcode 验证一下。

shortcode

这个 Hugo shortcode {{< midi >}},用在文章里可以直接嵌入一个曲目列表供读者点播。样式是简单的链接列表,点击曲目名称就开始播放。

这个 shortcode 的核心 Alpine.js 组件和控制中心大同小异。播放界面比较简洁(简陋),显示当前曲目、当前时间和总时长。

这个 shortcode 会自动加载 MIDIjs,MIDIjs 会先加载一个 3.5MB 的 midijs/lib/pat/arachno-127.pat ,加载完成后就可以播放那些只使用钢琴的 .mid 文件了。然后有其他乐器再加载其他的 .pat 文件。

控制中心版

控制中心里的实现大概是这样:

  • 在控制中心面板的 music 区域绑了一个 @mousemove="initMusic()",鼠标移过去才开始加载,避免不必要的请求。
  • 曲目列表存在 /midi/midi.txt 里,按行分隔。播放时从列表里随机选一首。如果开启了循环模式,当前曲目播完后会重新播放同一首,否则自动随机切下一首。

这个版本读取的 txt 做音乐列表。随时可以加新的,往 /content/midi/ 目录下丢个 .mid 文件,在 midi.txt 里加一行就行。

写完发现几个小问题,源码 5kb 有点大。一个 404 页面总共才 不到 10kb。所以我搞成了单独的 HTML ,js fetch 加载。所以初次进入博客的时候会闪一下。

然后就是由于放的位置比较靠后,元素聚焦顺序靠后,键盘导航体验不是很好。比较反直觉。再就是比较经典的遮蔽罩滚动问题。不过没再优化。

搞成一个 HTML 文件,放在对应位置,然后 js 加载一下 /control-center/index.html里的 js 就行了。

最后

有兴趣的可以点开控制中心试试。

基于 MIDI 的音乐播放
https://www.ftls.xyz/posts/2026-05-24-midi-music/
Author 恐咖兵糖
Published at
Copyright CC BY-NC-SA 4.0