核心概念
这一页把 YiYi Media 里的术语一次讲清。后面所有文档都沿用这里的叫法。 完整对照表见术语表。
一、部署结构
部署模式(Deployment Mode)
产品只有两种正式部署模式,它是第一层信息架构,其它术语都挂在它下面:
| 模式 | 标识 | 标准拓扑 | 节点模型 | 许可证 Edition |
|---|---|---|---|---|
| 单机版部署 | STANDALONE | 一台服务器,三个容器(YiYi-media-standalone + -postgres + -redis) | 一个内置 Storage、一个内置 Play Agent;用户只能新增手动反代地址 | edition=STANDALONE |
| 分布式部署 | DISTRIBUTED | Control / User / Media / Edge 可异机部署,基础设施与服务按分布式拓扑运行 | Storage / Play Agent 为外部工作节点,按配额新增与扩容 | edition=DISTRIBUTED |
control、user、media、edge 是分布式部署内部的角色,不是独立部署模式。 Storage 二进制部署、Storage Docker 部署与 Play Agent 部署是分布式版的节点运行方式,同样不是部署模式。
两种模式不能只改配置原地互转,必须走授权的专用版本升级操作与部署拓扑迁移, 见单机版迁移到分布式版。
控制面 / 节点层
- 控制面(Control Plane):
frontend、gateway、config、user、media五个服务, 负责编排、元数据、账号与授权。 - 节点层(Node Layer):由
storage与play-agent两类工作节点(Worker Node) 组成,负责存储与播放。
服务模块本身是独立的进程,只是可以被聚合到同一个容器里:单机版把它们收进一个 yiyi-app 容器,分布式版按角色分散到多台机器。
内置节点与外部节点
| 类型 | 标识 | 出现在 | 规则 |
|---|---|---|---|
| 内置节点(Embedded Node) | node_scope = EMBEDDED | 仅单机版 | 固定一个 Storage(node-local-storage)与一个 Play Agent(node-local-play-agent),随主应用安装、启动、升级;禁止删除、卸载、独立升级与修改服务类型;不向用户展示节点令牌 |
| 外部节点(External Node) | node_scope = EXTERNAL | 仅分布式版 | 在「节点管理」里创建后自助部署,可按授权配额新增与横向扩容,支持独立远程升级与卸载 |
内置节点只代表「随系统部署」这一个实例,不代表允许用户新增同类节点。
注册中心
config 服务扮演的角色。所有服务与节点向它报到,彼此通过它发现地址。 节点只需知道注册中心地址,不必维护 IP 清单。
三种节点记录
在节点管理里可以登记三类东西(前两类在单机版是内置的、不可新增),它们不是一回事:
| 类型 | 服务名 | 作用 | 可用模式 |
|---|---|---|---|
| 文件管理节点 | YiYi-control-storage | 真实运行的 Storage 服务,负责文件浏览、刮削与流代理 | 单机版:内置 1 个;分布式版:外部节点,可多实例 |
| 播放代理节点 | YiYi-play-agent | 真实运行的 Play Agent,Emby 协议出口 | 单机版:内置 1 个;分布式版:外部节点,可多实例 |
| 手动反代地址 | manual-play-agent-endpoint | 只是登记一个已经存在的反向代理入口,不参与部署与远程升级,系统只对它的 /health 做心跳 | 两种模式都可用;单机版中它是唯一能新增的项目 |
手动反代地址靠入口令牌(X-YiYi-Endpoint-Token 请求头)来标识请求归属哪条分发线路。 反代上没有注入这个头,请求就按直连处理,该地址上的用户级授权不生效。
二、存储
挂载源(Provider)
一个网盘账号或一个本地目录的接入配置,用挂载编码(providerCode)标识。 编码全局唯一,创建后不可修改——它是媒体库来源、访问控制、统计报表共同依赖的身份。
三类挂载源:
| 类型 | 代码标识 | 说明 |
|---|---|---|
| 本地磁盘 | LOCAL_DISK | 本机目录,支持 inotify 实时监控变更 |
| Google Drive | GOOGLE_DRIVE | 支持多账号共享池分流、云端变更同步、DoH 解析 CDN 候选 IP 优选 |
| 115 网盘 | ONE_ONE_FIVE | 走 Open API,支持秒传(hash 命中时 0 字节传输) |
| 三类都能挂、都能管文件,但播放侧直链级适配目前只覆盖 Google Drive 与 115 | ||
| (取签名直链、账号分流由播放节点自己做);本地磁盘直读。未来会兼容更多网盘类型。 |
WebDAV 与 S3 不是挂载源
WebDAV 和 S3 的协议能力用于对外提供访问——比如把选定挂载源经 storage 的 /dav/* 出口暴露给标准 WebDAV 客户端(见文件运维), 它们不是接入类型。
挂载(Mount)
把一个已启用的挂载源以 FUSE 映射成本地文件系统。配置项包括源目录、本地挂载点、 只读/读写、自动挂载、UID、GID 与八进制权限位(默认 0755)。
本地磁盘类型的挂载源不需要重复挂载。
单机版默认关闭主机 FUSE 挂载
单机版的 Storage 与其它服务同处一个容器,为挂载提权会扩大整个容器的权限影响面, 因此本期默认关闭主机 FUSE 挂载,聚合容器不使用 privileged,不授予 SYS_ADMIN。 云盘管理、文件浏览、上传下载、媒体同步与刮削不受影响。
Spool(持久暂存区)
写入挂载点的数据先落在本地 spool,再由任务链路上传到网盘。 这样即使挂载被卸载、进程被重启,未完成的上传仍能由任务链路恢复。
三、媒体
媒体库 / 来源目录 / 同步项 / 聚合项
四个层级要分清:
媒体库(Library)
└── 来源目录(Source)= 文件节点 + 挂载源 + 目录路径
└── 同步项(Sync Item)= 单个来源同步进来的一条媒体记录
↓ 跨来源按作品身份合并
聚合项(Aggregate Item)= 对外呈现的一个条目,界面上说的「N 个标题」一部作品在三个网盘上各有一份,就是三个同步项合并成一个聚合项。 聚合项下可以看到每个「文件来源」,也可以单独删掉某一个来源。
媒体库不扫描磁盘
中央媒体库只聚合存储侧已经刮削好的结果。刮削发生在 Storage 节点上, Media 服务负责同步与聚合。所以「建库」不等于「扫盘」。
媒体类型
只有三档:不限、电影(MOVIE)、剧集(SERIES)。 没有动漫、音乐、照片这类独立库类型。
同步模式
| 模式 | 标识 | 行为 |
|---|---|---|
| 增量同步 | INCREMENTAL | 只处理上次同步之后的新增变更,保留用户编辑 |
| 全量同步 | FULL | 全量比对并删除存储侧已不存在的差集,保留用户编辑 |
| 强制全量覆盖 | FORCE_FULL | 清空该来源数据后重插,会清除用户编辑 |
三档都可以先跑 Dry-run(同步预览):只比对身份键不落库,给出新增、更新、删除的数量与 逐条删除清单,含用户编辑的项会标出字段名,可以逐条勾选保留。
元数据覆盖(Override)
人工改写刮削结果,作用域分三级:
| 作用域 | 可覆盖字段 |
|---|---|
ITEM(作品) | 标题、原始标题、上映/首播日期、时长(仅电影)、简介、类型标签、封面、扩展属性 JSON |
SEASON(季) | 季标题、季封面 |
EPISODE(集) | 集标题、集封面、集简介 |
覆盖值优先于刮削值;留空的字段不覆盖。普通增量/全量同步不会冲掉覆盖,FORCE_FULL 会。
刮削与探测
- 刮削(Scrape):Storage 侧抓取元数据,模式分
LIGHT与DIRECT。 - 补全(Backfill):刮削后补齐缺失字段。
- 技术元数据探测:Play Agent 内嵌 ffprobe,在播放时异步补全容器格式、时长与音视频轨道, 不阻塞播放,也不替代刮削。
虚拟媒体库
不绑定存储目录、由外部数据或系统统计动态生成的媒体库。两种类型:
| 类型 | 标识 | 来源 |
|---|---|---|
| API 拉取 | API | 通用 HTTP 接口,用 JSONPath 抽取 TMDB ID 与条目数组,支持 5 种认证方式与 {{变量}} 密钥引用 |
| 智能库 | SMART | 系统自动计算:EVERYONE_WATCHING(大家在看)或 NODE_CACHE(节点缓存) |
虚拟库靠 TMDB ID 与中央媒体库求交集,只展示已经存在的内容——它不会把外部榜单里 你没有的片子变出来。
四、任务
存储任务
storage 节点上的持久化任务队列,12 种类型:
读取(READ)、上传(UPLOAD)、下载(DOWNLOAD)、离线下载(REMOTE_UPLOAD)、 复制(COPY)、移动(MOVE)、目录合并(MERGE)、备份(BACKUP)、 新建目录(MKDIR)、重命名(RENAME)、删除(DELETE)、整理器批量删除(ORGANIZER_DELETE)。
任务有 16 种状态,归入三个集合:
| 集合 | 状态 |
|---|---|
进行中(ACTIVE) | 排队中、预处理中、下载中、上传中、运行中、暂停中、取消中 |
需关注(ATTENTION) | 已暂停、失败、部分失败、已阻塞 |
已结束(FINISHED) | 已完成、已取消、已忽略、已跳过 |
READ、DELETE、RENAME、MKDIR 四类不可暂停、恢复、取消或重试。
Trace ID
贯通任务与日志的链路标识。一个任务在文件日志、系统日志与任务详情里都能用同一个 Trace ID 串起来。
调度任务
控制面的定时任务,内置 25 个,分布在 config、media、storage、user、play-agent 五个服务上。 全部可以在调度中心启停、改频率、手动触发、终止与重试。
五、播放
播放入口 / 线路(Route)
用户实际连上去播放的那个地址。两类:
NODE:某个 Play Agent 节点(单机版即内置的node-local-play-agent)MANUAL:某个手动反代地址
流量配额可以按入口单独设,NODE 与 MANUAL 互斥计账——走反代不会重复计入背后那个节点。 两种部署模式都支持这两类线路。
直连播放(Direct Stream)
Play Agent 不做转码与转封装,播放以直连为主:把网盘的文件流原样交给客户端。 同一作品的多个版本以多条 MediaSource 下发,由客户端自行挑选; 服务端不会替你降级——挑不动就播不出来。
VFS 缓存与智能启播
Play Agent 本地的视频缓存层,用稀疏文件按 Range 落盘。两种模式:
| 模式 | 标识 | 行为 |
|---|---|---|
| 启播加速(推荐) | SMART_STARTUP | 只保存开场所需数据;用 ffprobe 探测容器元数据的真实位置并缓存对应字节 |
| 传统预读 | READ_AHEAD | 按预读窗口持续缓存,会占用更多硬盘 |
淘汰策略是 LRU + 最长保留时间双阈值。单个响应里可以混合「本地缓存段」与「上游有界直传段」, 保持原文件偏移。
智能启播不是「只缓存头尾」
MP4 的 moov box、MKV 的索引、首段音视频数据可能相隔很远,按固定百分比或固定尾部缓存会浪费空间。 所以方案是「少量基础缓存 + ffprobe 受控访问记录 + 启播回放验证」,探测成功即停。
CDN 优选
节点内对上游网盘 CDN IP 的优选:DoH 解析候选 IP、测延迟与吞吐、池内轮询负载均衡、 必要时切换主 IP。注意这不是节点之间的播放调度——系统不做基于负载或延迟的自动选节点。
六、用户与运营
角色与委派
- 管理员:全部菜单,且豁免限速、流量配额与节点授权(流量仍计入统计)。
- 普通用户:默认只能进用户门户。
- 委派菜单权限:管理员可以把部分后台菜单交给非管理员。 可委派的只有 8 项:节点管理、文件管理、媒体管理、调度中心、系统配置、用户管理、邀请管理、播放设置。
配额三件套
| 维度 | 字段 | 说明 |
|---|---|---|
| 带宽限速 | bandwidthLimitKbps | 令牌桶执行,支持热更新;0 或留空表示不限速 |
| 并发流数 | maxConcurrentStreams | 0 不限,或 1 / 2 / 3 路 |
| 播放流量 | traffic quota | 按日/周/月周期重置,分用户级与入口级两层 |
没有存储空间配额
配额只有上面三类。不存在按用户限制存储空间的能力。
三种码
| 名称 | 作用 | 时长粒度 |
|---|---|---|
| 注册码 | 决定「能否注册」与「新账号多久到期」,可预设标签并在核销时继承 | 天(accountDurationDays,0 = 永久) |
| 续费码 | 只延长已有账号的有效期,由用户在门户自助粘贴激活 | 天(durationDays,必填) |
| 邀请码 | 用户用自己的邀请名额生成,新用户核销后建立上下级链路 | 由邀请设置的有效期决定 |
注册码有 5 条核销路径:邮箱注册、注册码激活已有账号、账号找回、Telegram 注册、Google 注册。
邀请树不含返佣
邀请管理提供名额发放、可视化邀请树与链路禁用,但没有任何返佣、提成或层级奖励逻辑。 邀请树只表示「谁邀请了谁」,不表示分润层级。
用户标签
8 色标签,用于运营分层与检索,支持单个与批量打标、按「任一 / 全部 / 无标签」筛选。 标签不参与任何权限判定。
客户端准入
访问管控按 User-Agent 做白名单/黑名单准入,规则带优先级(P1 最高,按序匹配启用规则)。
只有 User-Agent 一个维度
访问管控不支持 IP 黑白名单或设备指纹封禁。IP 只出现在会话列表与播放报表里作为展示字段。 按用户限制并发与带宽属于用户级配额,不在这个模块。
媒体来源访问控制
按挂载源粒度(nodeId + providerCode)限制媒体的可见与可播范围:
PUBLIC:任意有效用户可见可播RESTRICTED:仅显式授权的用户
查不到策略记录时按 RESTRICTED 处理(fail-closed)。两道防线:Media 查询层做软过滤, Play Agent 在输出任何字节前做硬拦截。被拒绝时用户侧统一表现为「不存在」(404 或从集合省略), 不泄露受限内容的存在性。
七、授权
租约(Lease)
授权不是一份永久密钥文件,而是一份短期租约:装完后用发布方给的一次性授权码激活, 之后系统自动定期续租。租约文件存在本地,校验完全离线完成,不依赖联网。
十种状态
UNACTIVATED、ACTIVE、GRACE、EXPIRED、SUSPENDED、REVOKED、DEACTIVATED、 CONFLICTED、INVALID、CLOCK_SKEW。 只有 ACTIVE 与 GRACE 允许业务操作,后台顶部的横幅会告诉你在哪一种。
其中三种都会停止业务,但原因完全不同,不要混为一谈:
| 状态 | 原因 | 怎么恢复 |
|---|---|---|
DEACTIVATED | 本机被主动反激活、让出了部署名额 | 用迁移码在新机器激活 |
CONFLICTED | 同一份授权在多台机器上同时使用,被自动阻断 | 停掉多余的机器,再由发布方解除阻断 |
REVOKED | 整份许可证被发布方撤销 | 需发布方处理 |
宽限期(GRACE)
租约到期但还没到宽限截止时的状态。此时后台顶部显示黄色横幅并明示宽限截止时间, 业务照常提供。越过宽限截止才进入 EXPIRED 与受限模式。
受限模式
不删数据、不卸载挂载,保留管理员登录、授权激活与状态查询、日志导出与数据备份; 拒绝新建播放会话、文件写入、调度任务与新节点注册。 完整清单见授权与版本。
Edition(版本)
许可证里的产品版本标识:STANDALONE(单机版)或 DISTRIBUTED(分布式版)。 写在签名租约里,由服务端强制执行能力边界。部署形态与 Edition 严格一一匹配, 不匹配时保留激活、许可证状态、日志与备份能力,不开放业务功能,不删除客户数据。 历史许可证没有 Edition 声明时按 DISTRIBUTED 兼容。
节点配额
授权里唯一强制的配额:分别限制 Storage 与 Play Agent 节点数量。 分布式版新增节点时向授权中心占用名额,删除节点时释放。 单机版的 maxStorageNodes=1、maxPlayAgentNodes=1 只代表两个内置节点, 不代表允许用户新增节点,且配额在管理台不可覆盖。手动反代地址不占配额。
授权不限制的东西
- 不限制用户数。
- 不做功能模块开关:不会按模块分别授权,所有功能随授权一起可用。
- 不做硬件指纹绑定:不使用 MAC 地址、容器 ID 或 CPU 序列号,允许受控迁移与重新绑定。
- 不是永久离线可用:越过宽限截止即进入受限模式。