123 lines
4.8 KiB
Markdown
123 lines
4.8 KiB
Markdown
# 音乐在线电台 · v2
|
||
|
||
把 `audio/` 目录里的歌曲用 FFmpeg 切成 HLS 切片,拼成**多路**永不停播的直播流,并提供 Web 控制面板管理播放列表、导入音源(网易云 / 本地上传)。前后端一体的 Node.js 应用。
|
||
|
||
## v2 相比 v1 的变化
|
||
|
||
- **数据库**:JSON(playlist/heat/metadata)→ **SQLite**(better-sqlite3,WAL 模式),支持多路流隔离
|
||
- **鉴权**:可选 Bearer Token → **Cookie 会话登录**(面板 + API 全保护,HLS 流不锁)
|
||
- **多路流**:单流 → **多路独立直播流**,各自播放列表,`/hls/{streamId}/index.m3u8`
|
||
- **导入**:仅网易云下载 → 增加**本地上传导入**(自动匹配作者/封面)
|
||
- **删除**:无 → **级联删除**(音频 + 切片缓存 + DB + 播放列表引用)
|
||
- **本地化**:CDN 依赖 + 封面图 → **全部本地**(`public/vendor/`、`public/covers/`),系统字体
|
||
- **模块化**:1233 行单文件 → `src/` 分模块
|
||
|
||
## 环境要求
|
||
|
||
| 依赖 | 版本 |
|
||
|------|------|
|
||
| Node.js | >= 18 |
|
||
| FFmpeg | 含 `ffmpeg` 与 `ffprobe`,在 PATH 中 |
|
||
|
||
## 安装与启动
|
||
|
||
```bash
|
||
npm install
|
||
npm start
|
||
```
|
||
|
||
首次启动若未设密码,控制台会打印随机登录密码:
|
||
|
||
```
|
||
[AUTH] 未设置 PANEL_PASSWORD,已生成随机登录密码: xxxxxx
|
||
```
|
||
|
||
建议固定密码:
|
||
|
||
```bash
|
||
# Windows PowerShell
|
||
$env:PANEL_PASSWORD="你的密码"; npm start
|
||
# Windows CMD
|
||
set PANEL_PASSWORD=你的密码 && npm start
|
||
# Linux / macOS
|
||
PANEL_PASSWORD=你的密码 npm start
|
||
```
|
||
|
||
访问 `http://127.0.0.1:3000`,用密码登录。
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
demo/
|
||
├── index.js # 入口,委托 src/server.js
|
||
├── src/
|
||
│ ├── server.js # 主程序:装配路由、启动服务
|
||
│ ├── config.js # 配置(环境变量)
|
||
│ ├── logger.js # 日志(分级 + 落盘 + 面板可查)
|
||
│ ├── db.js # SQLite 初始化 + schema
|
||
│ ├── store.js # 数据访问层(全部 SQL 收敛于此)
|
||
│ ├── util.js # 工具函数
|
||
│ ├── media.js # ffprobe / FFmpeg 切片 / 并发队列
|
||
│ ├── metadata.js # 网易云 API / 封面本地化 / 元数据补全
|
||
│ ├── livestream.js # LiveStream 类 + 多路流管理 + 缓存
|
||
│ ├── scanner.js # audio/ 目录监听与同步
|
||
│ ├── auth.js # 会话鉴权
|
||
│ ├── sse.js # SSE 推送
|
||
│ └── routes/ # API 路由(auth / music / resources / streams / system)
|
||
├── public/ # 前端(index.html / login.html / css / js / vendor / covers)
|
||
├── scripts/fetch_vendor.py # 一次性下载前端 CDN 资源到本地
|
||
├── audio/ # 音频文件
|
||
├── data.db # SQLite 数据库(自动生成)
|
||
└── hls/ hls_cache/ # 直播流与切片缓存(自动生成)
|
||
```
|
||
|
||
## API 一览
|
||
|
||
所有 `/api/*`(除 `/api/auth/*`)需登录。
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | `/api/auth/login` | 登录(body: `{password}`) |
|
||
| POST | `/api/auth/logout` | 登出 |
|
||
| GET | `/api/resources` | 资源列表 |
|
||
| GET | `/api/music/search?keyword=` | 网易云搜索 |
|
||
| POST | `/api/music/detail` | 网易云详情 |
|
||
| POST | `/api/music/download` | 网易云下载入库 |
|
||
| POST | `/api/music/import` | 本地上传导入(multipart) |
|
||
| POST | `/api/music/delete` | 删除音频(级联) |
|
||
| POST | `/api/music/delete-batch` | 批量删除 |
|
||
| POST | `/api/music/enrich` | 重新匹配元数据 |
|
||
| GET | `/api/streams` | 流列表 |
|
||
| POST | `/api/streams` | 创建流 |
|
||
| DELETE | `/api/streams/:id` | 删除流 |
|
||
| POST | `/api/streams/:id/start\|stop` | 启停流 |
|
||
| GET | `/api/streams/:id/playlist` | 播放列表 |
|
||
| POST | `/api/streams/:id/playlist/add\|remove\|reorder\|clear\|next\|prev\|jump` | 播放列表操作 |
|
||
| GET | `/api/system/cache` | 缓存信息 |
|
||
| POST | `/api/system/cache/cleanup` | 手动清理缓存 |
|
||
| GET | `/api/system/logs?tail=` | 查看日志 |
|
||
| GET | `/api/events` | SSE 实时推送 |
|
||
|
||
## 直播流地址
|
||
|
||
- 默认流:`http://127.0.0.1:3000/hls/main/index.m3u8`
|
||
- 其它流:`http://127.0.0.1:3000/hls/{streamId}/index.m3u8`
|
||
|
||
可用 VLC、PotPlayer、ffplay 打开。
|
||
|
||
## 环境变量
|
||
|
||
| 变量 | 默认 | 说明 |
|
||
|------|------|------|
|
||
| `PANEL_PASSWORD` | 随机 | 面板登录密码 |
|
||
| `PORT` | 3000 | 端口 |
|
||
| `HLS_TIME` | 5 | 切片时长(秒) |
|
||
| `SLIDE_WINDOW` | 15 | 滑动窗口段数 |
|
||
| `MAX_CACHE_MB` | 1000 | 缓存上限 |
|
||
| `FFMPEG_CONCURRENCY` | 3 | 转码并发 |
|
||
| `SESSION_TTL_HOURS` | 72 | 登录有效期(小时) |
|
||
| `LOG_LEVEL` | info | 日志级别 |
|
||
|
||
## 技术栈
|
||
|
||
Node.js · Express · better-sqlite3 · Multer · Chokidar · FFmpeg(HLS)· SortableJS · Bootstrap Icons |