# Starlight专属电台 · 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