Jellyfin:不把媒体库交给云端的自建方案
posts posts 2026-05-05T11:40:00+08:00Jellyfin 把媒体库的存储、索引、转码与权限控制全部留在本地进程里,不向任何外部云服务发请求。这篇文章从不转码的直接播放讲到要转码的完整链路,从部署到底层机制,讲清楚为什么硬件转码免费、什么场景该选它、什么时候该选别的方案。技术笔记开源, DockerJellyfin 解决的不是"播放视频"这件小事,而是"你的媒体库要不要交给别人"。Plex 和 Emby 把媒体库索引、播放记录甚至一部分转码能力挂在云端账号上;Jellyfin 把存储、索引、转码、权限控制全部留在本地进程里,从头到尾不向外部服务器发请求。它不是功能上最花哨的方案,核心是把"媒体服务器"重新掌握回自己手里。
一句话判断
Jellyfin(github.com/jellyfin/jellyfin,GPL-2.0)是一个完全自托管的媒体服务器:扫描并索引你的本地影音文件、按需转码、通过 Web / iOS / Android / 智能电视客户端播放。它从 Emby 分叉而来,把 Emby 走向闭源后锁进付费墙的能力——尤其是硬件转码——重新开放。
选择它的边界很简单:
- 如果你不想为硬件转码付订阅费、不想媒体库的任何元数据经过别人的服务器、愿意自己管理和维护一台 Linux / NAS,Jellyfin 是开销最小、掌控最彻底的选择。
- 如果你更看重官方客户端开箱体验、不想折腾 Docker 和转码配置,Plex 或 Emby 省事得多。
阅读路径
- 只想快速上手:搭建顺序 → Docker 部署 → 初始化配置。
- 想理解它怎么工作:系统由哪几套子系统拼起来 → 一次播放请求如何穿过整个系统 → 转码:什么会触发,什么是兜底。
- 想真正落地:Docker 部署 → 硬件加速 → 安全加固 → 从 Plex / Emby 迁移。
- 想判断该不该用:和 Plex、Emby 的边界 → 什么场景该用、什么场景不该用 → 常见问题。
一开始:Jellyfin 是什么,为什么会出现
Jellyfin 的开源故事藏着一个明确的分叉动机。Emby 早期是开源的,后来把越来越多能力改成专有和订阅制,硬件转码就是其中被锁起来的一项。2018 年,社区从 Emby 的最后一个开源版本分叉出 Jellyfin,目标是把"媒体服务器"这个核心能力保持在自由软件范畴内——不向任何云端服务请求,不把任何功能藏在付费墙后面。
这个定位决定了它和 Plex / Emby 的根本区别,不是"开源还是闭源"这个标签,而是三个具体的工程选择:
- 认证完全本地。用户、权限、token 全部存在你自己的服务器上,不依赖云端账号。
- 硬件转码完全开放。只要你的设备驱动支持,Intel QuickSync、NVIDIA NVENC 等硬件加速无需付费。
- 元数据刮削可自选。刮削器是开源的 agent,直接连接 TMDB、TVDB 等公开数据源,数据落进本地数据库。
系统由几套子系统拼起来
Jellyfin 不是单体应用,而是几套独立子系统在同一个进程里协作。用一张图把边界划清楚,后面逐个展开。
┌──────────────────────────────────────────────────┐
│ Jellyfin Server │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ 媒体库扫描 │ │ 元数据刮削 │ │ 插件系统 │ │
│ │ (文件监控) │ │ (TMDB等) │ │ (字幕/通知等) │ │
│ └────┬─────┘ └────┬─────┘ └───────────────┘ │
│ │ │ │
│ ┌────┴─────────────┴──────┐ ┌───────────────┐ │
│ │ SQLite / PostgreSQL │ │ 认证 / 权限 │ │
│ └──────────────────────────┘ └───────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ FFmpeg 转码引擎 │ │
│ │ H.265→H.264 / 4K→1080p / 硬解 (QSV/NVENC) │ │
│ └──────────────────┬───────────────────────────┘ │
└─────────────────────┼─────────────────────────────┘
│
┌───────────┼───────────┐
│ │ │
┌────┴────┐ ┌────┴────┐ ┌────┴────┐
│ Web 端 │ │ 移动端 │ │ TV 端 │
│ (自带) │ │ (官方) │ │ (Android│
│ │ │ │ │ TV等) │
└─────────┘ └─────────┘ └─────────┘三条主线的职责边界:
- 媒体库扫描 + 元数据刮削:把文件系统变成可浏览的影音库。它扫描文件夹、识别文件名、从 TMDB / TVDB 拉海报和简介,写入本地数据库。
- FFmpeg 转码引擎:播放时在本地把源文件实时转成客户端能解码的格式。这是 Jellyfin 最吃 CPU / GPU 的部分。
- 认证与权限:决定谁能看到哪些库、能以什么清晰度播放。认证完全本地,不经过任何外部服务。
关键一点:这三者是在同一进程里协作的,不是三个独立服务。媒体库扫描出文件 → 刮削补元数据 → 播放请求进来 → FFmpeg 按需转码 → 权限模块先拦一道。理解了这个"单进程多子系统"的模型,就不会把 Jellyfin 的配置想复杂——绝大多数设置都在一个控制台里完成,因为它们共享同一份配置和数据库。
一次播放请求如何穿过整个系统
把抽象结构串起来,看一个具体例子:你在手机上用 4G 网络点播一部 4K HDR 电影。
- 手机 App 向 Jellyfin Server 发起播放请求,携带登录时拿到的 access token。
- 认证模块校验 token 有效,并确认账号有权访问这部电影所在的媒体库。这里的鉴权是本地的——token 由你自己的服务器签发和校验。
- 服务器对比源文件格式和客户端能力。源文件是 HEVC 10bit HDR,客户端在 4G 下只能接受 1080p SDR,两边不一致,于是决定走转码。
- FFmpeg 读取源文件,用 GPU 做硬件解码 + 缩放 + 色调映射,输出 H.264 1080p SDR 流。
- 转码后的流以 HLS 分片形式推给客户端,客户端边下边播。
- 播放结束,播放进度写入本地数据库,下次接着看。
整个过程,Jellyfin 没有向任何外部服务器发过请求——认证本地、转码本地、媒体文件本地。这就是它和 Plex / Emby 最根本的区别。
转码:什么会触发,什么是兜底
转码是 Jellyfin 对硬件要求最高的环节,也是最容易误解的部分。一个原则贯穿始终:能不转码就不转码。转码是兜底,不是默认路径。
播放路径只有两种:
- 直接播放(Direct Play):客户端能解码源文件、带宽也够,文件不经过转码,原样推给客户端。Jellyfin 几乎不占 CPU。这是理想状态,占绝大多数本地局域网场景。
- 转码(Transcode):源文件编码、容器、分辨率、HDR 或带宽任意一项客户端受不住,才触发 FFmpeg 实时转换。这是兜底。
什么因素会逼出转码,逐一看:
| 触发维度 | 具体原因 | 典型应对 |
|---|---|---|
| 视频编码 | 客户端不支持 HEVC / AV1 等,只认 H.264 | 转成 H.264 |
| 视频位深 | HEVC 10bit,客户端只支持 8bit | 降位深到 8bit,通常伴随转码 |
| 分辨率 | 4K 源,客户端或带宽只能吃 1080p | 缩放到 1080p |
| 动态范围 | HDR 源,客户端只有 SDR 屏 | 色调映射(tone mapping)后再输出 |
| 容器 / 字幕 | 源是 MKV + PGS 图形字幕,目标设备不兼容 | 换装 / 烧录字幕 |
| 带宽 | 外网带宽不足,码率扛不住原文件 | 重新压缩到更低码率 |
这里面两个概念值得真正理解:硬件加速和色调映射。
硬件加速:转码最贵的部分是编解码。CPU 软转 1080p 很吃力,4K 基本跑不动;用 GPU 里的专用编解码单元(Intel QuickSync / QSV、NVIDIA NVENC、AMD AMF)能把转码能力提升一个数量级,而且功耗远低于 CPU 满载。关键是:在 Jellyfin 里这些硬件加速是免费的——它不锁在付费墙后面,只要内核驱动认到设备就行。这正是它和 Plex / Emby 最容易引起选择的差异点。
色调映射(Tone Mapping):HDR 视频记录的是远超 SDR 屏幕能显示的亮度信息。把 HDR 往 SDR 缩,不是简单裁剪,而是把高动态范围的亮度映射到 SDR 范围——否则画面会发灰或烧坏高光。Jellyfin 在 4K HDR → 1080p SDR 的转码路径里会做这一步。注意:色调映射本身有计算成本,在 CPU 上跑尤其贵,强烈建议用支持它的 GPU 加速路径。
一个务实的判断标准:能把"源文件直接播放"做对,比"转码调得有多好"重要得多。转码矩阵只需要覆盖少数真实场景——手机外网看 4K、老旧电视看 HEVC——绝大多数本地播放应当落在直接播放上。
转码矩阵:常见场景一览
| 源文件 | 目标设备 | 转码动作 | 硬件需求 |
|---|---|---|---|
| 4K HDR (HEVC) | 手机 4G | 4K→1080p, HDR→SDR, HEVC→H.264 | 需要 GPU(含色调映射) |
| 1080p H.264 | 浏览器 | 直接播放,不转码 | 无 |
| 原盘 ISO/BDMV | 电视 | 封装→MP4(重封装) | 低 |
| HEVC 10bit | 老旧电视 | HEVC→H.264, 10bit→8bit | 需要 GPU |
| 4K SDR | 局域网电视 | 若电视支持 HEVC,直接播放 | 无 |
注:ISO / BDMV 原盘那行是"重封装"(remux),只改容器不重新编码,成本低。
和 Plex、Emby 的边界在哪
| 维度 | Jellyfin | Plex | Emby |
|---|---|---|---|
| 许可证 | GPL-2.0,完全开源 | 专有 + 部分开源 | 专有(Jellyfin 由旧版本分叉而来) |
| 价格 | 完全免费 | 免费 + Premium 订阅 | 免费 + Premiere 订阅 |
| 认证 | 本地 token,无外部服务 | 需 Plex 账号(部分功能) | 需 Emby Connect(可选) |
| 硬件转码 | 免费(依赖硬件驱动) | Premium 订阅 | Premiere 订阅 |
| 元数据刮削 | 开源 Agent,直连 TMDB 等 | 专有 Agent(部分付费) | 部分付费 |
| 官方移动端 | 有(官方 iOS / Android) | 有,成熟度高 | 有 |
| 数据隐私 | 完全自主 | 部分依赖云服务 | 部分依赖云服务 |
一句话:如果不想为硬件转码付费、也不想媒体库的任何元数据离开你的服务器,选 Jellyfin。如果看重官方移动端 App 的开箱体验,Plex 或 Emby 更省事。
技术栈
| 组件 | 技术 | 说明 |
|---|---|---|
| 后端 | C# / ASP.NET Core | 跨平台,性能足够 |
| Web 前端 | React / TypeScript | Jellyfin Web,自 10.8 起从 Ember.js 迁移到 React |
| 数据库 | SQLite(默认)/ PostgreSQL | 数据量大了可切 PostgreSQL |
| 媒体处理 | FFmpeg | 所有转码和封装都走 FFmpeg |
| 认证 | 自签发的 access token | 无状态 token,不依赖外部服务 |
Docker 部署
Docker(最快上手)
docker run -d \
--name jellyfin \
-p 8096:8096 \
-p 8920:8920 \
-v /path/to/media:/media \
-v jellyfin-config:/config \
-v jellyfin-cache:/cache \
jellyfin/jellyfin:latest访问 http://your-server:8096 完成初始化向导。8920 是内置 HTTPS 端口,先不急着用它——更稳妥的 HTTPS 方案见"安全加固"一节。
Docker Compose(生产推荐)
services:
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
ports:
- "8096:8096"
- "8920:8920" # HTTPS
volumes:
- ./config:/config
- ./cache:/cache
- /path/to/media:/media:ro
- /etc/localtime:/etc/localtime:ro
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
devices:
- /dev/dri:/dev/dri # Intel QuickSync / VAAPI 硬件加速两个端口和三个目录的分工值得说明:
8096HTTP、8920HTTPS,是控制台和流媒体的统一入口。/config存服务器配置、用户、库定义与元数据数据库——这是备份的第一优先级,丢了等于重新搭建。/cache存转码缓存与缩略图缓存,丢了会自动重建,可以放心清理。/media指向媒体文件,建议只读挂载,防止 Jellyfin 误写你的源文件。
硬件加速配置
转码是 Jellyfin 对硬件要求最高的环节。没有硬件加速时,一颗 4 核 CPU 大概能同时转 1-2 路 1080p,4K 基本跑不动;启用 GPU 编解码后能力提升几个量级。
NVIDIA GPU:
services:
jellyfin:
image: jellyfin/jellyfin:latest
runtime: nvidia
environment:
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=compute,video,utilityIntel QuickSync(推荐,功耗低,核显够用):
用 Docker 时把核显设备映射进容器即可,/dev/dri 是 Intel iGPU 的默认设备路径。
services:
jellyfin:
image: jellyfin/jellyfin:latest
devices:
- /dev/dri:/dev/dri配置完成后,进控制台 → 播放 → 转码,选对应的硬件加速方案(Intel 选 QSV 或 VAAPI,NVIDIA 选 NVENC),并勾选需要加速的编码格式。
判断硬件加速有没有生效的一个通用方法:强制转码一部片子再取消,看转码日志里的编码器是否带 bframe / qsv / nvenc 字样,或者看 GPU 的编解码占用是否起来。纯 CPU 转码在任务管理器 / htop 里表现为 CPU 全核满载。
初始化配置
首次设置
- 访问
http://your-server:8096。 - 选择语言(支持简体中文)。
- 创建管理员账号。
- 添加媒体库,选类型(电影 / 剧集 / 音乐)和对应文件夹。
- 配置元数据刮削源(电影走 TMDB,剧集走 TVDB,音乐走 MusicBrainz 等)。
- 完成,等扫描结束后媒体库就有了内容。
媒体文件命名规范
Jellyfin 靠文件名识别媒体,命名不规范会导致刮削失败或张冠李戴。这是自建媒体库最容易踩的坑,值得一开始就定下规矩。
| 媒体类型 | 推荐结构 | 刮削源 |
|---|---|---|
| 电影 | Movie Name (Year).ext,如 Inception (2010).mkv | TMDB |
| 剧集 | Show/Season 01/Show S01E01.ext | TVDB |
| 音乐 | Artist/Album/01 Track.ext | MusicBrainz |
| 图片 | 按文件夹分组即可 | 无需刮削 |
几个容易出问题的点:
- 剧集必须带季目录。Jellyfin 靠
SxxEyy识别单集,混在一个文件夹里容易识别错乱。 - 电影加年份。同名电影很多,
(Year)是消歧最有效的手段,也在 TMDB 上命中更准。 - 多版本电影用
Movie Name (2010) - Bluray-1080p.mkv这类后缀区分版本,Jellyfin 会在播放界面让你选。
国内网络环境下的元数据问题
Jellyfin 默认从 TMDB / TVDB 拉取海报、简介和评分,这些服务在国内访问不稳定。两种解决方式:
- 配置 HTTP 代理(推荐):在 Docker 环境变量里加
HTTP_PROXY=http://your-proxy:port。 - 申请自有 API Key:在 TMDB 官网申请 Key,填入控制台 → 媒体库 → 元数据管理器,绕过公共 Key 的速率限制,也更稳定。
核心功能
媒体库管理
添加媒体库后,Jellyfin 自动扫描文件并刮削元数据:海报、背景图、剧情简介、演职员、评分、季/集信息。刮削结果写入本地 SQLite 或 PostgreSQL,不依赖云端缓存。
用户与权限
管理员可以为每个用户单独设置:
- 可访问的媒体库(比如不给小孩看大人的电影库)。
- 内容分级限制(按 MPAA 或自定义分级)。
- 同时播放数上限与最高清晰度。
- 是否允许远程访问。
这套权限完全在本地运行,不需要像 Plex 那样把用户列表同步到云端。
字幕
Jellyfin 通过插件支持自动下载字幕(OpenSubtitles 等),也支持手动上传。有一件事和多数人直觉不同:字幕渲染发生在客户端而不是服务器——Web 端用浏览器字体,桌面端和电视端用系统字体。如果客户端设备缺中文字体,中文会渲染成方块;这时在控制台 → 播放 → 字幕设置里指定一个中文字体路径即可。
插件生态
Jellyfin 的功能边界由插件定义。使用频率最高的:
| 插件 | 解决的问题 |
|---|---|
| OpenSubtitles | 播放时自动匹配和下载字幕 |
| MetaBuddy | 批量修复元数据缺失或错误 |
| Telegram 通知 | 新内容入库时推送到 Telegram |
插件通过控制台 → 插件 → 目录安装,无需手动下载文件。
安全加固
自建服务暴露到公网,最简单的反面教材是把 8096 端口直接映射出去。几个实际可用的加固步骤,从必须到可选:
- 反向代理 + HTTPS:用 Nginx / Caddy 反代
8096,把 TLS 终止放在更成熟的一层,隐藏真实端口。比直接用内置8920更可控、更易集成本域名和 Let’s Encrypt 证书。 - 不要把端口裸奔到公网:如果只在家用,用 VPN / Tailscale 组网访问即可,根本不暴露端口。
- 启用强密码与二次认证:控制台 → 设置里开启面向公网账号的二步验证,尤其是有远程访问权限的账号。
- 定期备份
/config:它包含全部配置与用户。装好 cron 定时备份,迁机时直接还原。 - 给用户开权限时最小化:家庭成员各自建账号,各自限库,别都共享管理员。
什么时候用 Jellyfin,什么时候不用
建议直接上 Jellyfin 的情况
- 有一台 NAS 或 24 小时开机的 Linux 服务器,媒体文件已经整理好。
- 不想为硬件转码付订阅费(Plex Pass 和 Emby Premiere 都把这功能锁在付费墙后面)。
- 看重隐私——媒体库索引、播放记录、用户列表全部留在本地。
- 愿意花一点时间配置,换取完全的控制权。
建议先等等,或选别的方案的情况
- 家里主力设备是 iPhone / iPad,且最看重 App Store 官方客户端。Jellyfin 官方 iOS 客户端在持续完善,但离 Plex 官方应用的成熟度还有距离。
- 需要开箱即用,不想折腾 Docker 和硬件转码配置。Plex 的安装体验和自动配置明显更友好。
- 依赖 TV Guide / 直播录制,且国内源基本不可用。
- 4K HDR 转码需求很大,但服务器没有 GPU 或核显。纯 CPU 转 4K 基本不可用——不过这种情况下用 Plex 也一样需要 GPU。
从 Plex / Emby 迁移的注意点
迁移的核心是保住元数据和播放记录,而不是保留那份数据库。推荐做法:
- 先保留原媒体文件的目录结构(Jellyfin 读取同一份
/media即可)。 - 新建 Jellyfin,挂载同一份媒体目录,重建库并重跑刮削。
- 播放进度一般无法直接平移——Jellyfin 的数据库格式与 Plex / Emby 不同。如果进度对你重要,先接受一部分丢失,或按需手动补记。
推荐搭建顺序
- 先用 Docker 跑起来,不配置硬件加速,验证媒体库刮削和 Web 端播放正常。
- 确认文件命名规范、元数据刮削成功率达标后,再接入 GPU 硬件加速。
- 配置外网访问(反向代理 + HTTPS,不要直接暴露 8096 端口)。
- 最后按需安装字幕插件和通知插件,并给每个家庭成员建独立账号。
核心数据
- 仓库:github.com/jellyfin/jellyfin,Stars 约 5 万级、Forks 约 5 千级(以 shields.io 实时徽章为准)。
- 许可证:GPL-2.0,主语言 C#,默认分支 master。
- 应用端:官方 Web(React)、官方 iOS / Android,第三方 iOS 客户端 Swiftfin。
参考链接
- GitHub:github.com/jellyfin/jellyfin
- 官方文档:jellyfin.org/docs
- 下载:jellyfin.org/downloads
- 插件仓库:repo.jellyfin.org/plugins
- 第三方 iOS 客户端 Swiftfin:apps.apple.com
参与讨论
使用 GitHub 登录。欢迎补充事实、异议与实践。
讨论暂时无法加载。