Jellyfin 自建影音库:海报墙、多用户与硬件转码
硬盘里攒了几 T 的电影和剧,接上电脑打开文件夹,文件名乱七八糟,想找去年看过的那部得翻十分钟。想在客厅电视上看,投屏要装一堆 App,或者干脆抱着笔记本接一根 HDMI 线。好不容易播上了,片名、封面、简介全没有,屏幕上一排文件图标。再加上商业媒体服务器这两年把硬件转码、多用户这些功能往付费里挪,界面里还塞广告,不少人就是那时候开始找替代品的。
Jellyfin 是自建这条路里最常被选中的一个。它把「一堆文件」变成「一个片库」,并且不花钱、不埋广告。
它能干什么
| 项目 | 内容 |
|---|---|
| 媒体库 | 指定目录后自动扫描,按电影、剧集、音乐分类整理 |
| 刮削 | 自动获取海报、简介、评分、演职员和播出信息 |
| 剧集识别 | 按季和集组织,自动排序,支持下一集连续播放 |
| 多用户 | 每个账号独立的观看记录,可以给儿童账号限制分级 |
| 硬件转码 | 用核显把高码率片源实时转成客户端吃得下的码率 |
| 字幕 | 内嵌与外挂都支持,可在线搜索,图形字幕可转文字 |
| 直播电视 | 接电视卡或网络电视源,做节目表和定时录制 |
| 客户端 | 网页、安卓、iOS、电视盒子、智能电视,也有第三方播放器 |
核心体验是那张海报墙:打开就是一张张封面,点进去有简介和进度条,手机上看到一半,回客厅打开电视能接着看。这一层是它真正值钱的地方,不是播放器,而是把无序的文件变成有序的片库。
Docker 部署
mkdir -p /opt/jellyfin/config /opt/jellyfin/cache
docker run -d \
--name jellyfin \
--restart unless-stopped \
-p 8096:8096 \
-v /opt/jellyfin/config:/config \
-v /opt/jellyfin/cache:/cache \
-v /srv/media/movies:/media/movies:ro \
-v /srv/media/tv:/media/tv:ro \
--device /dev/dri:/dev/dri \
jellyfin/jellyfin
几个要点:
- 8096 是网页端口。它还会用 7359 做局域网自动发现、1900 做 DLNA,想让电视自己找到服务器的话,这两个 UDP 端口也要能通
- 配置目录必须持久化,那里放着数据库、元数据和播放进度
- 媒体目录挂载时加
:ro,只读。这是个很小的习惯,能挡住你在客户端里一不小心的删除操作 /dev/dri是核显设备节点,没有核显就把这行去掉
compose 写法
services:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
restart: unless-stopped
ports:
- "8096:8096"
- "7359:7359/udp"
- "1900:1900/udp"
volumes:
- ./config:/config
- ./cache:/cache
- /srv/media/movies:/media/movies:ro
- /srv/media/tv:/media/tv:ro
devices:
- /dev/dri:/dev/dri
environment:
TZ: Asia/Shanghai
PUID: 1000
PGID: 1000
group_add:
- "989"
group_add 里那个数字是宿主机上负责显卡设备的组 ID,用 getent group video 或者 getent group render 查一下再换掉。容器内的进程不在这个组里,就没有权限打开核显,硬解会一直失败而你又看不出原因。
首次配置向导
- 浏览器打开 8096,选界面语言,中文在列表里
- 创建管理员账号。密码别太随意,将来这套东西可能要暴露给外网
- 添加媒体库,选对内容类型:电影选「电影」,剧集选「节目」,选错了刮削时根本找不到合适的元数据源
- 目录填容器里的路径,比如
/media/movies,不是宿主机的路径,这是最容易填错的一栏 - 元数据语言选中文、国家选中国,这两项决定了简介、封面上的文字是什么语言
- 把「自动为所有媒体生成缩略图」之类的选项先关掉,除非你硬盘和 CPU 都很闲
向导跑完先别急着灌片子。等你把命名规范那节读完、把目录理顺,再一次性扫描,能省掉后面大量的手工修正。
命名规范:能不能正确刮削就看这个
刮削器是拿文件名和目录结构去匹配的,命名不规范它只能猜。电影目录的标准样子:
/media/movies/
让子弹飞 (2010)/
让子弹飞 (2010).mkv
剧集更严格,需要「剧名 / 季 / 集」三层,集号用 S01E01 的格式:
/media/tv/
黑镜 (2011)/
Season 01/
黑镜 S01E01.mkv
黑镜 S01E02.mkv
Season 02/
黑镜 S02E01.mkv
几个细节:年份放在括号里,用来区分重名影片;季目录写 Season 01 这种两位数,简写成 S01 也行,但别写成「第一季」;同一个影片有多个版本(比如 1080p 和一个 4K 版本),文件名后面加个短横线加版本名,它会把它们认成同一部片的不同版本,而不是两部电影。
做不到这些的结果很典型:整部剧被识别成一集,或者每一集都变成刮不到任何信息的孤儿条目,海报墙上全是灰色方块。
硬件转码:开还是不开
结论先说:有核显就开,没有就别硬撑。
转码的意义在于:片源是 4K 高码率,而你的电视或手机只吃得下 1080p、或者上行带宽不够,服务器得实时把画面缩小、重新编码再推过去。这件事落在 CPU 上是灾难,落在核显上是小活。
有核显的机器把 /dev/dri 挂进容器,在控制台的「播放 - 转码」里启用硬件加速,选对编码器,再把支持的格式逐项勾上。开对了之后,一部 4K 转 1080p 的片子可能只占百分之十几的 CPU,风扇都不怎么转;开错了或者权限没给到,表现是播放一直转圈,日志里一片错误。
没有核显的纯软解,1080p 单路勉强,4K 基本没戏。这种情况下更实际的做法不是升级 CPU,而是让客户端直连:把码率上限放开甚至关掉转码,让播放器自己解。现在的电视盒子解码能力比很多老服务器强得多,别拿服务器的短处去补客户端的长处。
远程访问的三种方式
第一种,局域网直连。什么都不用配,同一网段内电视和手机能自己发现服务器,速度最快,日常绝大多数时间用这一种。
第二种,反向代理加域名。Nginx 把域名转到 8096,配上证书,任何地方都能用浏览器打开、用 App 登录。注意转发 websocket 相关的请求头,并且把请求体上限和超时时间放宽,否则加载大封面、同步播放进度都会出问题。
第三种,VPN。在外面先连回家里的网络,再用局域网地址访问。配置最麻烦但最安全,也不需要把服务暴露给公网。家里路由器能跑 VPN 的话,这是最省心的方案。
不建议直接把 8096 端口映射到公网。它没有为公网环境做过加固,暴露出去等于把家里的片库交给扫描器。
几个真会踩到的坑
- 中文片名刮不到。元数据语言设成英文了,或者文件名里没带年份。改语言、补年份,然后对那个条目手动刷新元数据,别指望再扫一遍就自己好。
- 一集被识别成一堆。命名不规范,或者目录里混着样本文件、说明文件、花絮。清掉无关文件,按规范重命名,删掉旧条目重新扫描。
- 4K 播放时 CPU 跑满、风扇狂转。硬解没真正开成,或者客户端在强制转码。控制台的播放信息里会写转码原因,通常写着容器不支持或者码率超限,照着原因改。
- 字幕乱码。老字幕是 GBK 编码,按 UTF-8 解就是满屏乱码。在字幕设置里指定编码,或者用工具统一转成 UTF-8。
- 手机在外网播放卡。默认码率上限太低或者家庭上行不够。客户端里限制码率,服务端把转码开起来,让它按你的上行带宽输出。
- 媒体目录忘了只读。客户端里一个误操作就能删掉原片。挂载时加只读,是最省事也最有效的一道防线。
适合你,不适合你
适合:手里有几百 G 到几十 T 的影视资源;想给家里人一套打开就能看的体验,不用教他们找文件;有 NAS 或闲置机器,愿意花一个晚上折腾。
不适合:只想看几个在线平台的剧;完全不想整理文件名和目录;机器是十年前的笔记本还指望它转 4K。这套东西能跑得舒服的前提,是你愿意先把目录理顺——它不是魔法,只是个把规范目录变漂亮的东西。





