从零实现的音乐聚合搜索与下载工具,支持 11 个平台并发搜索、在线试听、歌词查看、歌曲下载,前端可管理音乐源开关与 Cookie 配置。
- 11 个音乐源并发搜索:网易云、QQ音乐、酷狗、酷我、咪咕、Bilibili、5sing、Jamendo、JOOX、千千音乐、汽水音乐
- 搜索结果自动去重合并
- 在线试听播放
- 歌词查看
- 歌曲下载(后端代理,无 CORS 问题)
- 前端源管理:开关启用/禁用音乐源、为每个源单独配置 Cookie
- 源配置持久化(JSON 文件)
- 单二进制部署,前端嵌入后端
| 层 | 技术 |
|---|---|
| 后端 | Go 1.22 + Gin |
| 音乐源库 | music-lib |
| 前端 | HTML + Alpine.js + 原生 CSS |
| 部署 | Docker / 单二进制 |
music-dl/
├── cmd/server/ # 程序入口
├── internal/
│ ├── config/ # 配置管理
│ ├── handler/ # HTTP 处理器
│ ├── middleware/ # 中间件(日志、恢复、CORS)
│ ├── model/ # 数据模型 + music-lib 类型转换
│ ├── server/ # Gin 引擎和路由
│ ├── service/ # 搜索聚合服务(并发 + 超时 + 去重)
│ └── source/ # 音乐源管理
│ ├── provider.go # Provider 接口定义
│ └── manager.go # Manager:源配置 + Cookie + 持久化
├── web/ # 前端(go:embed 嵌入)
│ ├── index.html
│ ├── app.js
│ ├── style.css
│ └── embed.go
├── Dockerfile
├── docker-compose.yml
├── Makefile
└── go.mod
docker-compose up -dmake build
./bin/music-dlmake deps
make run| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/sources |
获取所有音乐源 |
| GET | /api/sources/config |
获取源配置(含开关、Cookie 状态) |
| PUT | /api/sources/config |
更新单个源配置(开关/Cookie) |
| PUT | /api/sources/config/batch |
批量更新源配置 |
| GET | /api/sources/:name/cookie |
获取源 Cookie 状态 |
| GET | /api/search?keyword=xxx&sources=netease,qq |
搜索歌曲 |
| GET | /api/song/:source/:id |
获取播放链接 |
| GET | /api/lyrics/:source/:id |
获取歌词 |
| GET | /api/download?source=xxx&id=xxx&name=xxx |
下载歌曲(代理) |
| GET | /health |
健康检查 |
点击页面右上角齿轮图标打开设置面板:
- 开关切换:启用/禁用任意音乐源,配置自动持久化到
data/sources.json - Cookie 配置:为每个源单独设置 Cookie(用于解锁高音质或 VIP 歌曲)
- 源筛选:搜索时可选择只从特定源搜索
创建 config.yaml(可选,不创建则使用默认值):
server:
port: "8080"
mode: "release"
search:
timeoutSec: 8
maxConcurrent: 5
sourceConfigPath: "./data/sources.json"项目通过 music-lib 库提供音乐源。如需添加新源:
- 在
internal/source/manager.go的allSources列表中添加源元信息 - 在
createProvider函数中添加对应的case分支 - 在
defaultEnabled中设置默认启用状态
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Download proxy may need larger timeout
location /api/download {
proxy_pass http://127.0.0.1:8080;
proxy_read_timeout 300s;
proxy_buffering off;
}
}MIT