Files
StarlightRadio/README.md
T

253 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 音乐在线电台
把 `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