EdgeSonic —— 我为什么把音乐库搬到边缘
一个完整的、多用户的 Subsonic 兼容音乐服务,没有服务器,没有常驻进程。聊聊我为什么要做它。
EdgeSonic 以 AGPL-3.0 开源,是我第一个按边缘架构从头设计的多用户完整服务。它想给自托管音乐多一个选择:不用 NAS,也不用服务器,成本、稳定性和维护压力都比它们低不少;想搭配着用也行,把它当前端,后面接你原来的储存。
这个想法其实动笔很早,真正让我下决心做完的,是下面这些事。
一、Navidrome 不够用,家里的 NAS 也靠不住
我最早用的是 Navidrome。它的播放做得很好,但我要的不止播放:标签要能改,专辑要能整理,多个用户要各管各的收藏和歌单。功能对不上,再好用的播放器也只能算半个答案。
另一头,家里的 NAS 也不太省心。我有两台,各有各的毛病:加拿大的家宽时不时抽一下风,中国那台上行带宽又不够。小请求感觉不到,大文件就不行了,比如整张专辑的 WAV,断一下就是整段播放失败,偏偏音乐最吃大文件。要从外面访问,还得做内网穿透或者直接暴露 IP,相当于在家庭网络边界上开个口子,还得自己长期盯着。
真正推我一把的是朋友。我分享给他们之后,好多人都跟我说:你这个怎么这么卡。
问题出在根上:Navidrome 和 music-tag-web 都是单节点设计,节点在地球的某个角落,离得远的人就只能隔着半个世界取音频,调参数救不了。EdgeSonic 的数据层说到底也是单点,但入口铺在全球网络上,再加上比较激进的预载策略(提前缓冲下一首,播完的曲目缓存在本地),实际用起来已经接近全球都能顺畅访问了。
二、买了份闭源,然后越补越累
为了补上标签管理这块,我买了 music-tag-web 转闭源之后的版本。用着用着,我从里面挖出了一个安全漏洞。万幸它只能把普通用户提权成管理员,我也私下、负责任地告诉了开发者。
事情没完。后来我又在网页上找到几个 UI 层面的问题。花了钱,却看不到里面是什么,也没法按自己的需要改,只能在外面打补丁:在 nginx 层注入修复脚本,再把有风险的 API 转发到我自己搭的安全缓解层。说实话,我开始厌倦了。给黑盒修修补补,补得越多,越觉得自己在替别人维护。
所以我给自己立了个规矩:想长期依赖的东西,必须能读,也必须能改。EdgeSonic 选 AGPL 也是这个原因,我希望别人遇到它的时候,别落到我当时的处境里。
三、IRIS 做通之后,我开始想自己做一个
还有个时机的问题。5 月,我在一个私有项目上把 Agent 工作流的设计做通了,那就是 IRIS 的 v0.2。当时它还不是一套完整的 harness,只是一套中等大小的插件:让 Agent 的任务有计划、有记录、有审计,项目的状态自己就能维持住。就是这么一套自维护的体系,已经撑得起高复杂度的网站开发。
从那时起,我开始慢慢想:既然市面上没有一个合理的软件来干这件事,那我可以自己开源一个。而且看得见的是,我多半能在课余和实习之余把它做出来,成本也在我能承受的范围里。
比起把别人走过的路再走一遍,我更想去没人去过的地方看看,再把路标留给后来的人。EdgeSonic 开源,也是这个意思。
四、最贵的成本是补丁
自托管最容易被低估的成本不是硬件,是及时打补丁:系统、容器、反向代理、面板、每个依赖,一环都不能漏,而且永远没有尽头。
Anthropic 发布 Project Glasswing(玻璃之翼计划)的时候,我意识到接下来几年可能会遇到规模最大的一轮批量攻击。公开报道里有两点让我印象很深:一个月里发现的高危、严重漏洞超过一万个;Anthropic 自己也承认,找漏洞比修漏洞容易得多,有些合作方修补的速度,甚至跟不上发现的速度。
放到个人自托管上更扎心。大厂有安全团队专门消化补丁队列,我没有。找洞越来越便宜,修补却得靠有人值守,而个人的值守时间是固定的。我家的服务器站在补丁链的最末端,最后收到通知,也最慢修好。
更何况,就算我知道哪里有洞,我也未必有那个心思去修。
五、所以,把维护交出去
整个设计都围着一个问题转:怎么把需要长期盯着的部分压到最少。结论很朴素:让有能力天天盯补丁的人去盯,我只管自己写的那部分代码。
Workers 跑在 V8 isolate 上,运行时由 Cloudflare 自己控制和更新,V8 的补丁间隙不到 24 小时。主机系统、SSH、常驻端口、内核漏洞,这一整层都不用我操心了。
架构也尽量轻:Worker、D1、R2,加上少量 Durable Object。能出问题的东西本来就少,出了问题也容易看清。
账算下来也还算划算。R2 标准储存 $0.015/GB·月,免费 10 GB,出站流量不要钱;Workers 付费套餐 $5/月,含一千万次请求。
五美元的套餐再加几刀的储存费,也就一个音乐会员的价格,换来不用买硬盘、不交电费、不用半夜爬起来处理“服务挂了”。对我来说,这买卖相当划算。
六、中间踩过的坑
Cloudflare 没有音频转码接口。 我想了两招。
第一招是预转码:用 Opus 这类高压缩、低损失的格式,空间省下来,WAV 原件照样保留。
第二招是按需转码,分两条路。免费套餐上,让浏览器当劳动力:一个 Durable Object 通过休眠 WebSocket 把任务派给空闲的浏览器,播放的时候自动暂停,转完再回写。付费套餐上,用 Container 临时拉起 ffmpeg 转码。
Worker 的连接问题。 音频如果从 Worker 里过,大文件的带宽和连接稳定性都不太理想。所以我加了 302 模式:Worker 只负责签名和跳转,浏览器直接去 R2 拉音频。就我自己的体验,哪怕在中国大陆,加载速度也够用。
NAS 变成可选的储存后端。 WebDAV、S3 兼容储存、另一台 Subsonic 服务器都能接,EdgeSonic 负责索引、用户体系和客户端协议。已经有 NAS 的人可以保留数据,拿它当后端。
七、一个新时代的私有服务,还应该往哪里长
做到能用之后,我开始想:一个音乐服务,还该长出什么。
迁移不该赌上全部数据。 EdgeSonic 能复制、同步其他服务的内容:从 Navidrome 这类 Subsonic 服务拉曲目、用户、歌单和星标,中断了可以续传;反过来,也能把收藏和歌单推回上游。
和朋友互联。 我设计了一套面向未来的节点互联方案:互相信任的 EdgeSonic 实例可以交换各自能提供的曲目,还能跨节点搜索,你和朋友之间能自动聚合彼此可访问的资源。
K 歌模式。 我喜欢唱歌,而很多专辑恰恰只有我的曲库里有,市面上的 K 歌软件找不到。所以它能开临时房间,朋友扫二维码就能在手机上点歌,也支持加载视频。音乐库不只是用来听。
单点登录。 个人的服务越来越多,只靠账号加密码登录不是个好主意。所以浏览器端支持 OIDC 单点登录。
隔离好客户端 subsonic生态决定了客户端还是得走密码账号,不用主密码,也就不会因为某个客户端出了问题,让它摸到 EdgeSonic 的高权限内部接口。
部署也有两条路。 我觉得新时代的私有服务,部署应该分两条路走:
- 第一条,降低前置知识,于是有了 Overture。它仿照微软 OOBE 做的引导式零代码部署工具,在浏览器里一步步走完,不用碰命令行,不用碰代码。
- 第二条,让专业用户省心。仓库里有一份写给 Agent 看的部署指南:该准备什么,该向用户要什么,怎么验证服务确实按用户的要求搭好了。你把仓库丢给自己的 Agent,剩下的它来问你。
协议上它兼容 Subsonic v1.16.1 和 OpenSubsonic 扩展,DSub、Symfonium、Substreamer、Sonixd 直接能用;标签编辑、元数据抓取、文件整理也都自带,这些正是我当初想要的。
试试看
- 在线演示:https://edgesonic.lsy-demo.workers.dev/#/login。
- 部署:用浏览器里的 Overture 向导,不需要本地工具链;也可以让 Agent 按仓库里的指南帮你部署,或者自己用 Wrangler。
- 代码与文档:GitHub →
本文为作者 Siyu Lei 原创内容,转载请注明出处并附上原文链接。(leisiyu.dev)