Repository navigation
Home
Lux 是面向 NAS 的个人媒体服务端:用 Rust 提供高效、可诊断的媒体索引、元数据管理与播放服务,用 React + TypeScript 提供同源 Web 客户端,并通过 Emby 兼容 API 连接 VidHub、SenPlayer、Infuse、Harbor 等第三方客户端。
Lux 的重点不是订阅聚合,而是把本地媒体库管理、扫描、元数据和播放链路做得轻量、可控、可诊断,改善大媒体库下的加载和维护体验。
当前仓库版本标记:0.4.9。兼容性和部署状态会持续变化,本文以仓库当前实现为准;具体行为请以项目文档和真实客户端测试记录为准。
- 电影、电视剧和混合媒体库;一个媒体库可以配置多个根路径。
- 文件事件增量扫描,以及可暂停、恢复、取消和重试的后台任务。
- 本地 NFO 与图片优先;支持候选匹配、元数据锁定、图片管理和原子写回。
- 本地媒体直放、鉴权、Range 请求、外挂字幕、多媒体源和多版本选择。
- .strm 外部播放地址支持:播放路径将地址交给有权限的客户端,不主动探测、代理远程媒体字节。
- Lux Web:初始化、登录、首页、媒体库浏览、搜索、筛选、详情、继续观看、收藏、账户和管理控制台。
- Emby 兼容层:连接、认证、媒体库浏览、搜索、详情、播放信息、进度、收藏、字幕,以及弹幕相关扩展接口持续完善。
- Emby 客户端服务端 HLS fallback:本地媒体在客户端明确请求且条件满足时,可按播放能力协商 Remux、音频转码、硬件转码或软件转码;.strm 不进入 Lux 服务端转码路径。
- 用户、会话、媒体库 ACL、下载权限、审计事件和结构化日志。
- SQLite 或外部 PostgreSQL;默认使用
/config/lux.db中的 SQLite。 - 独立进程插件运行时,支持 TMDb、媒体探测、IP 归属地、通知等插件能力。
需要 Docker Engine 和 Docker Compose v2:
services:
lux:
image: pdzhou/lux:latest
container_name: lux
environment:
LUX_SCAN_CONCURRENCY: 8
LUX_PROBE_CONCURRENCY: 8
LUX_FFMPEG_CONCURRENCY: 2
ports:
- "8097:8097"
volumes:
- ./config:/config:rw
- ./media:/media:rw
restart: unless-stopped启动后访问 http://localhost:8097/,按引导选择数据库并创建第一个管理员。
目录用途:
| 宿主机目录 | 容器目录 | 用途 |
|---|---|---|
./config |
/config |
数据库、插件、配置和日志,必须持久化 |
./media |
/media |
媒体库;NFO 和图片写回需要读写权限 |
首次初始化建议只在局域网完成。初始化后,再通过 HTTPS 反向代理或 Tailscale 提供访问;不要把未初始化的 setup 页面直接暴露到公网。
如果媒体位于 NAS 的其他目录,请先修改挂载关系,再把容器内可见的路径(例如 /media/Movies)添加为媒体库根路径。
-
SQLite:默认内置数据库,不需要额外容器,数据文件为
/config/lux.db。 - PostgreSQL:连接 Lux 容器之外运行的 PostgreSQL,可使用仓库 Compose 的可选 profile,也可以连接已有实例。
数据库后端只能在创建第一个管理员之前选择。已初始化实例不支持在线切换,也不会自动执行 SQLite 到 PostgreSQL 的数据迁移。
官方 Docker Compose 默认使用:
-
LUX_SCAN_CONCURRENCY=8:文件扫描工作项上限; -
LUX_PROBE_CONCURRENCY=8:媒体技术信息探测上限; -
LUX_FFMPEG_CONCURRENCY=2:缩略图和 FFmpeg 阶段上限。
这三个阶段独立限流;扫描并发不是 Tokio OS 线程总数。修改 Compose 环境变量后需要重新创建容器,单纯重启旧容器不会更新环境变量。NAS 上应结合 CPU、内存、存储延迟、数据库写锁和前台 p95 逐步调整。
- 打开 Web 首页,选择 SQLite 或 PostgreSQL。
- 创建第一个管理员账号。
- 在管理控制台创建媒体库,选择电影、电视剧或混合类型。
- 添加容器内可访问的媒体库根路径。
- 启动扫描,等待媒体进入索引。
- 按需安装并配置刮削器;低置信度条目可在管理台继续处理。
- 配置 HTTPS 反向代理后,再把服务提供给外部客户端。
扫描只负责文件系统调和、媒体探测和本地 NFO/图片索引,不会因为一次普通扫描就自动发起在线刮削。元数据匹配、图片策略和通知任务由独立流程处理。
Lux 优先使用 Direct Play。客户端需要具备对应容器、视频、音频和字幕能力;Lux 负责鉴权、Range 请求、媒体源选择和播放状态回传。
对于明确请求服务端转码的 Emby 客户端,Lux 可以根据 PlaybackInfo、设备 profile、媒体流信息和码率限制协商本地媒体的 HLS fallback。转码会话使用短期签名地址,并在播放停止、超时或失败时清理资源。
Lux 不代理 .strm 指向的远程媒体字节。播放时返回受保护的直连/重定向路径,由客户端直接访问远程地址;远程地址中如果本来包含 token,Lux 不负责替客户端隐藏它。.strm 不进入 Lux 服务端 HLS 转码路径。
Lux Web 的浏览、详情、状态与管理流程持续完善;播放能力取决于浏览器、硬件解码能力和媒体编码。对稳定播放、复杂字幕或特定编码,建议使用已验证的第三方客户端,并参考兼容性矩阵中的具体证据。
兼容性不是“某个接口返回 200”就算完成。以下是当前仓库记录过的真实客户端验证摘要,版本、平台和未覆盖项以兼容性矩阵为准:
| 客户端 | 已记录的验证摘要 |
|---|---|
| VidHub | macOS 与 Android 均有添加/登录、媒体库浏览、详情和至少一条播放链路记录;部分状态回传已验证 |
| SenPlayer | macOS 添加、登录、首页、电影列表和 .strm 直连播放已验证 |
| Infuse | macOS 添加服务器、登录链路已验证,完整浏览与播放矩阵仍需补充 |
| Harbor | macOS 添加、登录、媒体库浏览已验证;播放/状态需按场景继续验证 |
| Yamby | Android 真机媒体库、详情、H.264 直放、继续播放、进度和收藏有记录 |
| CapyPlayer | Android 真机添加隔离测试服务器、登录、Exo 直放和进度回传有记录 |
| Hills | Android 真机媒体库、详情和 MPV 直放有记录 |
| 网易爆米花 | Android 远程 Lux 连接下有稳定播放和进度回传记录,但不同资源仍可能有差异 |
| Lux Web | Chrome smoke 已覆盖登录、浏览、详情、Direct、服务器 HLS、状态与管理流程的部分路径 |
如果遇到客户端问题,请提供客户端版本、平台/设备、脱敏后的请求路径、状态码、关键响应字段和复现媒体类型;不要上传 token、Cookie、完整签名 URL 或私人媒体信息。
Lux 当前采用单 Rust 进程的模块化单体架构:
第三方客户端 / Lux Web
│
HTTP API
│
Handler:解析、校验、DTO 映射
│
Application Service:业务规则与任务编排
│
Storage:SQLite / PostgreSQL
│
Bounded Workers:扫描、探测、图片/FFmpeg、元数据与通知
- Rust 服务端负责凭据、完整播放 URL、缓存、媒体路径安全和播放会话。
- React + TypeScript 负责 Web 界面与用户交互,不把服务端凭据直接暴露给不受信任的 URL。
- Emby 路由/DTO 与 Lux 自有 API、领域模型保持分离。
- 扫描、ffprobe、FFmpeg 和在线刮削均在后台有界执行,不在用户请求中扫描整库或调用 TMDb。
- 插件以独立进程运行,通过插件 SDK 与宿主通信。
详细的产品规格、架构边界和实施任务见LUX-DEVELOPMENT.md。
Lux 是本地媒体管理器和播放服务,不是订阅聚合器。当前明确不在首要范围内的能力包括:
- 完整 Emby API 仿真;只覆盖目标客户端实际需要的兼容接口;
- 音乐库、照片库、直播电视、DVR、DLNA;
- 内置备份/恢复、SQLite 与 PostgreSQL 之间的在线迁移;
- 多节点高可用和公共注册;
- 让 Lux 代理或隐藏远程 .strm 媒体地址。
欢迎通过 Issues 反馈问题或提出建议。提交播放、兼容性或扫描问题时,请尽量附上可复现步骤和脱敏诊断信息;源码、日志、数据库和媒体文件中不要包含密码、token、Cookie、完整外部 URL 或私人数据。
Lux 的 Rust package metadata 使用 MIT 许可证;仓库中的字体资源另有对应的 SIL Open Font License 1.1 许可说明,详见仓库中的许可证文件。