baseline: 音乐在线电台 v1(重构前基线)
This commit is contained in:
commit
fa6eeb25b9
11 files changed
+5483
No files matched your search
@@ -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
|
||||
Reference in new issue
Block a user