跳到正文

目录

Jellyfin:不把媒体库交给云端的自建方案

Jellyfin 解决的不是"播放视频"这件小事,而是"你的媒体库要不要交给别人"。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 的根本区别,不是"开源还是闭源"这个标签,而是三个具体的工程选择:

  1. 认证完全本地。用户、权限、token 全部存在你自己的服务器上,不依赖云端账号。
  2. 硬件转码完全开放。只要你的设备驱动支持,Intel QuickSync、NVIDIA NVENC 等硬件加速无需付费。
  3. 元数据刮削可自选。刮削器是开源的 agent,直接连接 TMDB、TVDB 等公开数据源,数据落进本地数据库。

系统由几套子系统拼起来

Jellyfin 不是单体应用,而是几套独立子系统在同一个进程里协作。用一张图把边界划清楚,后面逐个展开。

┌──────────────────────────────────────────────────┐
│                  Jellyfin Server                  │
│                                                   │
│  ┌──────────┐  ┌──────────┐  ┌───────────────┐  │
│  │ 媒体库扫描 │  │ 元数据刮削 │  │  插件系统      │  │
│  │ (文件监控) │  │ (TMDB等)  │  │  (字幕/通知等) │  │
│  └────┬─────┘  └────┬─────┘  └───────────────┘  │
│       │             │                             │
│  ┌────┴─────────────┴──────┐  ┌───────────────┐  │
│  │      SQLite / PostgreSQL │  │  认证 / 权限    │  │
│  └──────────────────────────┘  └───────────────┘  │
│                                                   │
│  ┌──────────────────────────────────────────────┐ │
│  │           FFmpeg 转码引擎                     │ │
│  │  H.265→H.264 / 4K→1080p / 硬解 (QSV/NVENC)   │ │
│  └──────────────────┬───────────────────────────┘ │
└─────────────────────┼─────────────────────────────┘
                      │
          ┌───────────┼───────────┐
          │           │           │
     ┌────┴────┐ ┌────┴────┐ ┌────┴────┐
     │ Web 端  │ │ 移动端  │ │ TV 端   │
     │ (自带)  │ │ (官方)  │ │ (Android│
     │         │ │         │ │  TV等)  │
     └─────────┘ └─────────┘ └─────────┘

三条主线的职责边界:

  1. 媒体库扫描 + 元数据刮削:把文件系统变成可浏览的影音库。它扫描文件夹、识别文件名、从 TMDB / TVDB 拉海报和简介,写入本地数据库。
  2. FFmpeg 转码引擎:播放时在本地把源文件实时转成客户端能解码的格式。这是 Jellyfin 最吃 CPU / GPU 的部分。
  3. 认证与权限:决定谁能看到哪些库、能以什么清晰度播放。认证完全本地,不经过任何外部服务。

关键一点:这三者是在同一进程里协作的,不是三个独立服务。媒体库扫描出文件 → 刮削补元数据 → 播放请求进来 → FFmpeg 按需转码 → 权限模块先拦一道。理解了这个"单进程多子系统"的模型,就不会把 Jellyfin 的配置想复杂——绝大多数设置都在一个控制台里完成,因为它们共享同一份配置和数据库。

一次播放请求如何穿过整个系统

把抽象结构串起来,看一个具体例子:你在手机上用 4G 网络点播一部 4K HDR 电影。

  1. 手机 App 向 Jellyfin Server 发起播放请求,携带登录时拿到的 access token。
  2. 认证模块校验 token 有效,并确认账号有权访问这部电影所在的媒体库。这里的鉴权是本地的——token 由你自己的服务器签发和校验。
  3. 服务器对比源文件格式客户端能力。源文件是 HEVC 10bit HDR,客户端在 4G 下只能接受 1080p SDR,两边不一致,于是决定走转码。
  4. FFmpeg 读取源文件,用 GPU 做硬件解码 + 缩放 + 色调映射,输出 H.264 1080p SDR 流。
  5. 转码后的流以 HLS 分片形式推给客户端,客户端边下边播。
  6. 播放结束,播放进度写入本地数据库,下次接着看。

整个过程,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)手机 4G4K→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 的边界在哪

维度JellyfinPlexEmby
许可证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 / TypeScriptJellyfin 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 硬件加速

两个端口和三个目录的分工值得说明:

  • 8096 HTTP、8920 HTTPS,是控制台和流媒体的统一入口。
  • /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,utility

Intel 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 全核满载。

初始化配置

首次设置

  1. 访问 http://your-server:8096
  2. 选择语言(支持简体中文)。
  3. 创建管理员账号。
  4. 添加媒体库,选类型(电影 / 剧集 / 音乐)和对应文件夹。
  5. 配置元数据刮削源(电影走 TMDB,剧集走 TVDB,音乐走 MusicBrainz 等)。
  6. 完成,等扫描结束后媒体库就有了内容。

媒体文件命名规范

Jellyfin 靠文件名识别媒体,命名不规范会导致刮削失败或张冠李戴。这是自建媒体库最容易踩的坑,值得一开始就定下规矩。

媒体类型推荐结构刮削源
电影Movie Name (Year).ext,如 Inception (2010).mkvTMDB
剧集Show/Season 01/Show S01E01.extTVDB
音乐Artist/Album/01 Track.extMusicBrainz
图片按文件夹分组即可无需刮削

几个容易出问题的点:

  • 剧集必须带季目录。Jellyfin 靠 SxxEyy 识别单集,混在一个文件夹里容易识别错乱。
  • 电影加年份。同名电影很多,(Year) 是消歧最有效的手段,也在 TMDB 上命中更准。
  • 多版本电影Movie Name (2010) - Bluray-1080p.mkv 这类后缀区分版本,Jellyfin 会在播放界面让你选。

国内网络环境下的元数据问题

Jellyfin 默认从 TMDB / TVDB 拉取海报、简介和评分,这些服务在国内访问不稳定。两种解决方式:

  1. 配置 HTTP 代理(推荐):在 Docker 环境变量里加 HTTP_PROXY=http://your-proxy:port
  2. 申请自有 API Key:在 TMDB 官网申请 Key,填入控制台 → 媒体库 → 元数据管理器,绕过公共 Key 的速率限制,也更稳定。

核心功能

媒体库管理

添加媒体库后,Jellyfin 自动扫描文件并刮削元数据:海报、背景图、剧情简介、演职员、评分、季/集信息。刮削结果写入本地 SQLite 或 PostgreSQL,不依赖云端缓存。

用户与权限

管理员可以为每个用户单独设置:

  • 可访问的媒体库(比如不给小孩看大人的电影库)。
  • 内容分级限制(按 MPAA 或自定义分级)。
  • 同时播放数上限与最高清晰度。
  • 是否允许远程访问。

这套权限完全在本地运行,不需要像 Plex 那样把用户列表同步到云端。

字幕

Jellyfin 通过插件支持自动下载字幕(OpenSubtitles 等),也支持手动上传。有一件事和多数人直觉不同:字幕渲染发生在客户端而不是服务器——Web 端用浏览器字体,桌面端和电视端用系统字体。如果客户端设备缺中文字体,中文会渲染成方块;这时在控制台 → 播放 → 字幕设置里指定一个中文字体路径即可。

插件生态

Jellyfin 的功能边界由插件定义。使用频率最高的:

插件解决的问题
OpenSubtitles播放时自动匹配和下载字幕
MetaBuddy批量修复元数据缺失或错误
Telegram 通知新内容入库时推送到 Telegram

插件通过控制台 → 插件 → 目录安装,无需手动下载文件。

安全加固

自建服务暴露到公网,最简单的反面教材是把 8096 端口直接映射出去。几个实际可用的加固步骤,从必须到可选:

  1. 反向代理 + HTTPS:用 Nginx / Caddy 反代 8096,把 TLS 终止放在更成熟的一层,隐藏真实端口。比直接用内置 8920 更可控、更易集成本域名和 Let’s Encrypt 证书。
  2. 不要把端口裸奔到公网:如果只在家用,用 VPN / Tailscale 组网访问即可,根本不暴露端口。
  3. 启用强密码与二次认证:控制台 → 设置里开启面向公网账号的二步验证,尤其是有远程访问权限的账号。
  4. 定期备份 /config:它包含全部配置与用户。装好 cron 定时备份,迁机时直接还原。
  5. 给用户开权限时最小化:家庭成员各自建账号,各自限库,别都共享管理员。

什么时候用 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 迁移的注意点

迁移的核心是保住元数据和播放记录,而不是保留那份数据库。推荐做法:

  1. 先保留原媒体文件的目录结构(Jellyfin 读取同一份 /media 即可)。
  2. 新建 Jellyfin,挂载同一份媒体目录,重建库并重跑刮削。
  3. 播放进度一般无法直接平移——Jellyfin 的数据库格式与 Plex / Emby 不同。如果进度对你重要,先接受一部分丢失,或按需手动补记。

推荐搭建顺序

  1. 先用 Docker 跑起来,不配置硬件加速,验证媒体库刮削和 Web 端播放正常。
  2. 确认文件命名规范、元数据刮削成功率达标后,再接入 GPU 硬件加速。
  3. 配置外网访问(反向代理 + HTTPS,不要直接暴露 8096 端口)。
  4. 最后按需安装字幕插件和通知插件,并给每个家庭成员建独立账号。

核心数据

  • 仓库:github.com/jellyfin/jellyfin,Stars 约 5 万级、Forks 约 5 千级(以 shields.io 实时徽章为准)。
  • 许可证:GPL-2.0,主语言 C#,默认分支 master。
  • 应用端:官方 Web(React)、官方 iOS / Android,第三方 iOS 客户端 Swiftfin。

参考链接

参与讨论

使用 GitHub 登录。欢迎补充事实、异议与实践。