
HY
折腾进行时
Hello, I'm HY.








我的书签页里有个「自建服务」分组,评论、图床、图片工具、监控、统计都在里面。这次往里加的是个音乐站。
地址先放这儿:
图的是入口统一:浏览器打开就能听,手机上加到桌面就是个 PWA,不用每台设备都装一遍客户端。
而且这个站是对外开放的 —— 不是自用测试,也不是搭着玩,谁想听直接打开就行,不用打招呼。
项目叫 Folia,AGPL-3.0。卖点不是曲库,是全屏歌词——歌词动画在这个项目里是主角,不是附属的滚动条。

它有几个东西挺戳我:
| 能力 | 说明 |
|---|---|
| 全屏歌词动画 | 十几种模式(浮名、流光、心象、云阶、群唱、镜台、时计……),可调参数,自适应窗口尺寸 |
| 多音源 | 网易云、酷狗、QQ 音乐、Navidrome、本地音乐库 |
| 本地歌库 | 导入本地音频,只上传索引不上传文件;自动匹配在线歌词和封面 |
| AI 主题 | 按歌曲情绪和歌词内容生成沉浸式背景 |
| 多端 | Electron 桌面端有现成安装包;Web 版能当 PWA 装 |
我走的是 Web 版。界面就是一个封面网格,登录之后能直接看到自己网易云那边的歌单,卡片展开是播放和加入队列:

点开一首,网格中间会浮出播放面板,歌词在封面下方跟着走,再点一下就是上面那张全屏歌词:

这是整件事里最容易被忽略的一点。官方文档写得很直白:Web 版至少要有两样东西——一个放前端的地方,和一个可用的网易云 API 地址。
桌面端内置了前后端所以开箱能用,Web 版没有,你得自己准备。所以这次实际上是两段部署。
fork NeteaseCloudMusicApiEnhanced/api-enhanced,丢 Vercel 导入就行,Framework Preset 认成 Express 是对的。
环境变量只需要一条:
1ENABLE_GENERAL_UNBLOCK=false注意这是网易云 API 项目的变量,不是 Folia 前端的。官方文档特意点了这一句,两个项目的环境变量不是一套。
部署完 Vercel 会先给一个 <项目名>-<后缀>.vercel.app 的默认域名,能用,但地址又长又不好看,所以我在这个项目上另外绑了自己的域名:
1https://wyyapi.9ll.ukfork chthollyphile/folia-major 到自己的账号,然后 Cloudflare 后台:Workers 和 Pages → 创建应用 → Continue with GitHub → 选仓库。
仓库自带 wrangler.jsonc,所以不用像有些纯静态项目那样自己补配置:
1{2 "name": "folia-major",3 "main": "./worker/index.ts",4 "compatibility_date": "2026-04-02",5 "assets": {6 "directory": "./dist",7 "binding": "ASSETS",8 "not_found_handling": "single-page-application",9 "run_worker_first": ["/api/*"]10 }11}Cloudflare 自己就把构建命令识别成了 npm run build,部署命令 npx wrangler deploy,不用改。
1VITE_NETEASE_API_BASE=https://wyyapi.9ll.uk这个坑我差点踩进去。
Folia 仓库里有个 runtime-config.js,看名字像是”运行时才读配置”,那种思路下环境变量填在 Worker 的运行时变量里就够了。但我把它抓下来看了一眼,内容是这样的:
1// 当前文件:非 Docker Web 部署的空运行时配置,具体值继续由 Vite 环境变量提供。2window.__FOLIA_RUNTIME_CONFIG__ = window.__FOLIA_RUNTIME_CONFIG__ || {};空壳。真正的值还是 import.meta.env.VITE_* 那一套,走 Vite 构建期注入。
也就是说 VITE_NETEASE_API_BASE 必须填在 Cloudflare 的构建变量(Settings → 构建 → 变量和机密)里。Cloudflare 自己的文档也写得很清楚:构建变量只在构建期可见,运行时读不到;反过来,运行时变量构建期也读不到。
这个填错位子不会报错,构建照样成功,只是产物里的 API 地址是空的,页面能打开但搜不到歌。排查起来挺费劲。
怎么验证填对了:打开线上页面,看它实际请求的是不是你自己那个 API 域名。我这边在 music.9ll.uk 上抓到的请求是 https://wyyapi.9ll.uk/...,这才算真的通了。
Worker 建好之后在「域」标签页里加 music.9ll.uk。因为 9ll.uk 本来就在同一个 Cloudflare 账号里,DNS 记录是自动建的,证书也一起下来了,没等多久。
第一,不登录只能试听 30 秒。 Folia 的在线播放要登录网易云才完整,未登录状态下部分歌曲只能试听 30s,歌单、收藏、电台这些也看不到。
第二,AI 主题现在是用不了的。 它要另外一组 key:
1VITE_AI_PROVIDER=google # 或者 openai2GEMINI_API_KEY=你的_key我这次没配,所以 AI 主题那个入口点了没用。想用的话把这几个变量加进构建变量再重新部署一次就行。
第三,QQ 音乐和酷狗这两条线有额外门槛。
VITE_QQ_API_BASE。我这两个都没接,现在能用的是网易云在线 + 本地音乐库。
第四,构建令牌那条告警可以先放着。 Cloudflare 的构建设置里有一条「提取 GitHub 用户或组织详细信息时出错」。这次构建是正常的,先记一笔,真出问题再回头查。
代码都是原作者的,AGPL-3.0,我做的是 fork 一份、拆成前后端两段部署、再挂到自己域名下。许可证和署名都在仓库里留着。
部署过程这次同样是丢给 AI agent 用浏览器点完的,流程和前面那篇把浏览器交给 AI 之后一样,就不重复了。区别是这次多了「网易云 API 得自己先搭」这一段,比纯静态项目麻烦一档。
地址再放一次:https://music.9ll.uk/
这个站是开放给大家用的,谁都能来听 —— 不是自用测试实例,也不是搭完摆着看的。
配套的网易云 API 单独挂了个域名:https://wyyapi.9ll.uk/
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!
部分内容可能已过时
分享你的想法,与大家交流讨论