baseline: 音乐在线电台 v1(重构前基线)

This commit is contained in:
dev committed 2026-09-24 19:46:35 +08:00
commit fa6eeb25b9
11 files changed
+5483

No files matched your search

+252
View File
@@ -0,0 +1,252 @@
# 音乐在线电台
把 `audio/` 目录里的歌曲用 FFmpeg 切成 HLS 切片,拼成一条永不停播的直播流,并提供 Web 控制面板管理播放列表、从网易云导入音源。前后端一体的 Node.js 应用,无数据库依赖。
## 功能特性
- 🎵 音频文件自动转码切片(HLS),拼成 24 小时不间断的直播流
- 📋 拖拽排序的播放列表(支持添加、移除、清空、切歌)
- 🔥 热度统计 + 缓存自动清理(上限 1GB,按热度淘汰)
- ☁️ 网易云音源导入:输入歌曲 ID,一键下载入库并显示封面/歌名/作者
- 🖼️ 资源卡片展示:封面图高斯模糊背景 + 时长/大小信息(hover 显示)
- 🔒 可选 API 鉴权(Bearer Token)
## 环境要求
| 依赖 | 版本要求 |
|------|----------|
| Node.js | >= 14.14 |
| npm | 随 Node 附带 |
| FFmpeg | 任意较新版本(需包含 `ffmpeg` 与 `ffprobe`,且在系统 PATH 中) |
> ⚠️ FFmpeg 是硬性依赖。缺少它程序能启动但无法转码切片,直播流不会有内容。安装后请在终端运行 `ffmpeg -version` 与 `ffprobe -version` 确认可用。
## 安装
### 1. 安装 Node.js
**Windows**
- 前往 <https://nodejs.org> 下载 LTS 版本安装包(`.msi`),一路下一步即可。
- 安装完成后重新打开终端,运行 `node -v` 应显示版本号(≥ v14.14)。
**Linux(Debian/Ubuntu 示例)**
```bash
# 使用 NodeSource 源安装新版 Node
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
node -v
```
> 其它发行版请参考 Node.js 官方安装文档,或使用包管理器安装 `nodejs` / `npm`。
### 2. 安装 FFmpeg
**Windows(推荐)**
方式一:用 winget(Windows 11 自带):
```powershell
winget install Gyan.FFmpeg
```
方式二:手动下载
1. 打开 <https://www.gyan.dev/ffmpeg/builds/>,下载 `release essentials` 的 zip 包。
2. 解压到固定目录(如 `C:\ffmpeg`)。
3. 把解压后 **`bin` 子目录**的完整路径(如 `C:\ffmpeg\bin`)加入系统环境变量 `Path`:
- `Win` 键 → 搜索「编辑系统环境变量」→ 「环境变量」→ 双击「Path」→ 新建 → 粘贴路径 → 确定。
4. **重新打开终端**,运行 `ffmpeg -version` 验证。
方式三:用 Chocolatey / Scoop:
```powershell
choco install ffmpeg # 或
scoop install ffmpeg
```
**Linux**
```bash
# Debian / Ubuntu
sudo apt update && sudo apt install -y ffmpeg
# CentOS / RHEL / Fedora
sudo dnf install -y ffmpeg # 部分发行版需先启用 EPEL 或 RPM Fusion 源
# Arch
sudo pacman -S ffmpeg
```
验证安装:
```bash
ffmpeg -version
ffprobe -version
```
### 3. 安装项目依赖
在项目根目录(`demo/`)下:
```bash
npm install
```
## 启动
```bash
npm start
```
启动成功后控制台会输出:
```
[INFO] 资源: N 个文件
[CACHE] 启动扫描: ...
[LIVE] 已启动 | 切片 5s | 窗口 15 段 ≈75s | ...
[HTTP] 面板: http://127.0.0.1:3000
[HTTP] 直播: http://127.0.0.1:3000/hls/index.m3u8
```
- **控制面板**:浏览器打开 <http://127.0.0.1:3000>
- **直播流地址**:<http://127.0.0.1:3000/hls/index.m3u8>(可用 VLC、PotPlayer、ffplay 等播放器打开)
停止服务:在终端按 `Ctrl + C`。
> 💡 Windows 下如果端口被旧进程占用导致启动失败(`EADDRINUSE`),见下文「常见问题」。
## 使用指南
### 添加音频
把音频文件(支持 `.mp3` / `.m4a` / `.flac` / `.wav`)直接放进 `audio/` 目录。程序用 chokidar 监听目录,**无需重启**,新文件会自动扫描并开始转码切片。
> 文件名建议用「作者 - 歌名.mp3」格式,程序会据此自动解析出作者与歌名,用于面板展示。
### 网易云音源导入
1. 在控制面板左侧「资源列表」顶部输入框填入网易云歌曲 ID。
2. 点「查询」,预览区会显示封面、歌名、作者。
3. 点「下载」,音频会自动保存到 `audio/` 并入库切片,封面/歌名/作者写入元数据。
**网易云歌曲 ID 在哪找?** 打开网易云网页版某首歌的页面,地址栏 `https://music.163.com/song?id=33894312` 中 `id=` 后面的数字即为歌曲 ID。
> ⚠️ 版权限制:只有免费、可播的歌曲能下载。VIP / 灰色无版权歌曲会被拦截并提示「无版权或需 VIP」,这是网易云服务端的限制,无法绕过。
### 管理播放列表
控制面板右侧「播放列表」支持:
- ➕ 点资源卡片右侧的加号把歌曲加入播放列表
- 🖱️ 拖拽排序(SortableJS)
- ❌ 移除单曲
- 🗑️ 清空列表(清空后自动随机补一首,保证直播不断流)
- 歌曲播完自动从列表移除,列表空了自动随机补一首
播放列表与热度会持久化到磁盘,重启后保留。
## 目录结构与数据文件
```
demo/
├── index.js # 主程序(后端 + HLS 直播 + HTTP API)
├── package.json # 依赖与启动脚本
├── public/ # 前端控制面板(静态文件,含 favicon)
│ ├── index.html
│ └── favicon.png
├── audio/ # 【你的音频】放这里,程序自动监听
└── (以下为运行时自动生成,可随时删除,重启自动重建)
├── hls/ # 直播流滑动窗口 index.m3u8
├── hls_cache/ # 每首歌的 HLS 切片缓存(上限 1GB,自动清理)
├── heat.json # 歌曲热度(缓存清理优先级)
├── playlist.json # 播放列表(持久化)
└── metadata.json # 歌曲元数据(歌名/作者/封面图/时长)
```
## 环境变量
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `AUTH_TOKEN` | (空) | 设置后,所有 `/api/*` 接口需携带请求头 `Authorization: Bearer <token>` |
| `USE_DISCONTINUITY` | `false` | 设为 `true` 时在歌曲切换处插入 `#EXT-X-DISCONTINUITY` 标签(兼容性更好则保持关闭) |
| `PORT` | `3000` | HTTP 服务端口 |
| `HLS_TIME` | `5` | 单个 HLS 切片时长(秒),同时决定直播 tick 间隔 |
| `SLIDE_WINDOW` | `15` | 直播滑动窗口段数(≈ 窗口秒数 = HLS_TIME × 该值) |
| `MAX_CACHE_MB` | `1000` | HLS 缓存上限(MB),超出按热度淘汰 |
| `FFMPEG_CONCURRENCY` | `3` | FFmpeg 转码并发数 |
| `MAX_RETRIES` | `3` | 单文件转码失败重试上限 |
| `FFMPEG_TIMEOUT_MS` | `300000` | 单次 FFmpeg 转码超时(毫秒) |
设置方式(三平台):
**Windows PowerShell**
```powershell
$env:AUTH_TOKEN="your_token"; npm start
```
**Windows CMD**
```cmd
set AUTH_TOKEN=your_token && npm start
```
**Linux / macOS**
```bash
AUTH_TOKEN=your_token npm start
```
## 常见问题
### 端口 3000 被占用
**Windows**
```powershell
# 找到占用 3000 端口的 PID
netstat -ano | findstr :3000
# 结束该进程(把 <PID> 换成上一条命令查到的数字)
taskkill /PID <PID> /F
```
**Linux**
```bash
# 查看占用进程
sudo lsof -i :3000
# 或
sudo ss -tlnp | grep 3000
# 结束进程(把 <PID> 换成实际值)
kill <PID>
```
### 启动成功但直播流没声音 / 一直缓冲
1. 确认 `audio/` 目录里确有音频文件。
2. 确认 FFmpeg 已正确安装并在 PATH 中:`ffmpeg -version`。
3. 看启动日志里 `[PRESEG]` 是否报错——若某首歌转码失败会打印 `[PRESEG] 失败`,可检查该文件是否损坏。
4. 首次启动需对所有歌曲转码,耗时随歌曲数量与长度增加,请耐心等待日志出现 `[PRESEG] 完成`。
### 网易云下载报「无版权或需 VIP」
正常现象,见上文「网易云音源导入」的版权说明。换一首免费歌曲即可。
### 局域网内其它设备访问不到
- 确认目标设备能 ping 通本机 IP。
- **Windows**:需在防火墙中放行 Node.js(或放行 3000 端口)。首次启动时若弹出防火墙授权,点「允许」;否则在「Windows 安全中心 → 防火墙 → 允许应用通过防火墙」中手动添加 node.exe。
- **Linux**:若有 `ufw` / `firewalld` 需放行端口:
```bash
sudo ufw allow 3000 # ufw
sudo firewall-cmd --add-port=3000/tcp --permanent && sudo firewall-cmd --reload # firewalld
```
然后用本机局域网 IP 访问:`http://<本机IP>:3000`。
## 技术栈
Node.js · Express · Chokidar · FFmpeg(HLS 切片)· SortableJS · Bootstrap Icons