本文主要介绍一类自托管媒体库(以 Octans 为演进样本)在全局架构上的稳定原则:它要同时做「本地资产治理」与「可持续运行的播放服务」,因此必须在物理文件事实、逻辑实体、后台任务与多端客户端之间划清边界。文中对照早期白皮书思路与当前架构总览,历史口号若与现行决策冲突,以现行系列文为准

系统到底要解决什么

如果只做「文件信息展示」,架构可以很薄。媒体库一旦同时承担:

  • 像 tinyMediaManager 一类的整理 / 刮削 / NFO / 命名 / 清理
  • 像 Emby 一类的常驻服务、任务调度、播放入口、多端访问

就不能围着单个页面或单个引擎设计。至少要同时处理:

内容
物理事实磁盘上的真实文件与变更
逻辑实体电影 / 剧集 / 人物 / 合集
异步任务扫描、刮削、重命名、删除、导出
播放域会话、Planner、DirectPlay / HLS
客户端Web 管理与各端原生播放体验

当前最核心的架构原则

物理优先,逻辑后组装

永远先承认磁盘上的真实文件,再推导逻辑身份。

结果:

  • 扫描阶段不假设已拿到完整元数据身份
  • 许多动作入口可以基于文件 ID / 路径事实,而不是要求前端先拼完美实体图

查询与动作分离

  • 查询域:浏览、详情、筛选、分页
  • 动作域:扫描、刮削、重命名、删除、NFO 导出

前端能清楚区分「我在看状态」还是「我在下命令」。

重任务异步化

扫描 / 刮削 / 重命名 / 删除 / NFO 不是轻量同步 HTTP。主路径通常是:

API 接收命令
  → 后台队列 / SystemTask
  → 异步执行
  → 进度与状态回传(如 SignalR)

交互保持响应,重 I/O 不绑死在请求生命周期上。

限界上下文解耦

扫描不负责重命名,刮削不负责删除,删除不反向变成扫描,NFO 不是「补元数据」的万能出口。边界保守,但长期可回归、可文档化。

早期白皮书里仍然成立的产品直觉

早期全局选型讨论里,有几条方向与现行实践仍然对齐:

  1. DirectPlay 优先:能不转码就不转码;音视频字幕尽量分离处理,按需最小转码。
  2. 服务端决策,客户端执行:复杂策略(刮削、匹配、转码决策)收敛在后端 API / Planner,而不是各端复制。
  3. 多端不是一套 UI 跑天下:Web 擅长管理与兼容播放;桌面 / 移动 / TV 需要原生播放能力与各自交互模型。
  4. 转码可共享:HLS window / 切片缓存思路,避免「同一片源每人一个 FFmpeg 进程」的浪费(具体缓存选型见转码缓存文)。

已被后续决策 supersede 的历史表述

早期文稿中出现过「跨平台 UI 框架 + 原生播放器嵌壳」等工程猜测,以及偏口号的「一套 UI 复用到桌面」。后续公开决策已更细:

主题现行口径(系列文)
Web UI 基座自有 ui + headless + 数据网格内核
Windows 壳当前产品主线 WebView2 Host;WinUI 3 为长期候选
Android单 App + 双 Interaction Shell;Compose for TV
跨端Web 做基线,原生各自 UI + native 播放
服务端 FFmpeg自维护 full runtime,与客户端 LGPL libmpv 分离

阅读早期白皮书时,应把「哲学」与「具体技术栈名单」分开;栈名单以 2026 现行决策为准

推荐阅读地图(从总览到专题)

全局原则(本文)
  ├─ 扫描 / 刮削 / 重命名 / 删除
  ├─ NFO 与轨识别 / 动态范围
  ├─ 播放架构 → Planner → 矩阵 → 排障
  ├─ FFmpeg / 硬解 / 缓存存储
  ├─ Docker / PG 部署
  └─ 各端 UI 与播放内核演进

专题文已在 series: octans 下分波沉淀,本文不重复展开。

注意事项

  1. 本文是架构原则与阅读地图,不是 API 契约或版本发布说明。
  2. 早期 vault 白皮书含对话体与营销式措辞,公开改写已收敛为工程记录语气。
  3. 若 arch 总览与某篇 decision 冲突,以带 supersedes 关系的决策链与更新的专题文为准。

相关阅读

来源

本文综合改写自 Octans 当前 arch/architecture-overview 原则,并对照早期 vault「系统全局架构与技术选型白皮书」中的产品直觉(原稿已从本仓 drafts 移除,见 git 历史);已标注 supersede 边界,避免把历史栈名单写成当前真理。