# 音乐在线电台 把 `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** - 前往 下载 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. 打开 ,下载 `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 ``` - **控制面板**:浏览器打开 - **直播流地址**:(可用 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 ` | | `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 # 结束该进程(把 换成上一条命令查到的数字) taskkill /PID /F ``` **Linux** ```bash # 查看占用进程 sudo lsof -i :3000 # 或 sudo ss -tlnp | grep 3000 # 结束进程(把 换成实际值) kill ``` ### 启动成功但直播流没声音 / 一直缓冲 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