跳至正文
老丹的足迹 —— 代码写给机器,游记写给自己,感悟写给时间
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面

从零开始:用 Docker 部署 Jellyfin 并启用英特尔核显硬件加速

一、为什么选择 Jellyfin

Jellyfin 是一款完全开源免费的媒体服务器。它可以把硬盘上的电影、剧集、音乐和照片整理成漂亮的媒体库,并串流到电视、手机、平板、电脑等各种设备上。它没有订阅费用,没有云端依赖,所有数据都在自己的掌控之中。

相比 Plex 和 Emby,Jellyfin 最大的优势是完全开源、功能不设限。Plex 和 Emby 的部分高级功能(如硬件转码、移动端同步)需要付费订阅,而 Jellyfin 的硬件加速、多用户管理、家长控制等功能全部免费开放。

本文以英特尔核显为核心,记录从部署到排查的完整过程,包括硬件加速配置、媒体库命名规范、常见播放错误排查等实战经验。

二、硬件与内核兼容性检查

第 6 代(Skylake)及更新的 Intel Core 处理器,核显型号为 HD Graphics 500 系列及以上,均支持 QSV 硬件加速。

查看核显型号:

lspci -nn | grep -i vga

以本文测试机为例,输出为:

00:02.0 VGA compatible controller: Intel Corporation Tiger Lake-LP GT2 [UHD Graphics G4] [8086:9a78] (rev 01)

这是第 11 代 Tiger Lake 平台,支持 QSV。

内核版本要求:建议不低于 5.13。特殊平台的最低内核版本:

处理器平台最低内核要求
Jasper Lake / Elkhart Lake(N5095、N5105)5.16+
Alder Lake-N Refresh(N150、N250、N350)6.9+
12 代 Alder Lake5.17+

确认核显设备节点存在:

ls -l /dev/dri

正常输出示例:

crw-rw----+ 1 root video  226,   0 Sep 10 20:15 card0
crw-rw----+ 1 root render 226, 128 Sep 10 19:09 renderD128

renderD128 是渲染节点,Jellyfin 的硬件加速主要通过它访问 GPU。

三、宿主机驱动安装与权限配置

3.1 安装用户态驱动

Docker 容器本身不包含 GPU 驱动,必须在宿主机上安装。

Ubuntu / Debian:

sudo apt update
sudo apt install -y intel-media-va-driver-non-free vainfo

intel-media-va-driver-non-free 是 Intel iHD 驱动,第 10 代酷睿(Comet Lake)及更新的处理器需要它才能正常使用 QSV。

3.2 验证驱动

vainfo

如果输出类似下面这样,说明驱动有问题:

Trying display: wayland
libva info: VA-API version 1.23.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so
libva info: va_openDriver() returns -1
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva info: va_openDriver() returns -1
vaInitialize failed with error code -1 (unknown libva error),exit

这说明 iHD 驱动没有正常工作。解决方法:

sudo apt install -y intel-media-va-driver-non-free
export LIBVA_DRIVER_NAME=iHD
vainfo

正常输出应包含 va_openDriver() returns 0 和 Supported profile and entrypoints 列表。

3.3 权限配置

将当前用户加入 render 组:

sudo usermod -aG render $USER

执行后需要重新登录或重启系统才能生效。

注意:如果你使用 PUID 和 PGID 以特定用户身份运行容器,需要确保该 UID/GID 对应的用户在宿主机的 render 组中。

四、Docker Compose 部署 Jellyfin

4.1 创建目录

mkdir -p ~/jellyfin/{config,cache,media}
cd ~/jellyfin

4.2 创建 docker-compose.yml

services:
  jellyfin:
    image: jellyfin/jellyfin:latest
    container_name: jellyfin
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Shanghai
      - LANG=C.UTF-8
      - LC_ALL=C.UTF-8
    volumes:
      - ./config:/config
      - ./cache:/cache
      - /mnt/udisk1/tv:/media/tv1:ro
    ports:
      - "8096:8096"
    devices:
      - /dev/dri:/dev/dri

核心参数详解:

  • devices: - /dev/dri:/dev/dri:最关键的一项,将宿主机核显设备映射到容器内。
  • PUID / PGID:设置为拥有媒体文件的用户 ID 和组 ID(用 id 命令查看)。
  • volumes 中的 :ro:将媒体目录以只读方式挂载,防止 Jellyfin 误删文件。
  • LANG / LC_ALL:确保容器内 UTF-8 编码正常,避免中文目录和文件名乱码。

4.3 多磁盘映射的正确写法

如果有多个磁盘存放媒体文件,不能让两个不同的宿主目录映射到同一个容器路径:

# ❌ 错误写法:后面的会覆盖前面的
volumes:
  - /mnt/disk1/tv:/media/tv:ro
  - /mnt/disk2/tv:/media/tv:ro

正确写法是映射到不同子路径:

volumes:
  - /mnt/disk1/tv:/media/tv/disk1:ro
  - /mnt/disk2/tv:/media/tv/disk2:ro
  - /mnt/disk3/tv:/media/tv/disk3:ro

这样在 Jellyfin 网页里添加媒体库时,只需要填写一个路径 /media/tv,它会自动递归扫描所有子目录。以后新增磁盘也只需加一行映射,不用再去改 Jellyfin 的媒体库配置。

4.4 启动服务

docker compose up -d

查看日志:

docker compose logs -f

五、Jellyfin 界面配置

浏览器访问 http://你的服务器IP:8096,按向导完成初始设置。

5.1 添加媒体库

进入 控制台 → 媒体库 → 添加媒体库,选择内容类型(电影、电视节目等),然后添加文件夹。

关键点:这里填的必须是容器内路径,例如 /media/tv1,而不是宿主机的 /mnt/udisk1/tv。

5.2 开启硬件加速

进入 控制台 → 播放 → 转码。

推荐方案:QSV

  1. 硬件加速:选择 Intel Quick Sync Video (QSV)
  2. QSV 设备:填入 /dev/dri/renderD128
  3. 启用硬件解码:勾选
  4. 硬件编码:根据核显支持情况勾选 H.264 和 H.265
  5. 低电压编码模式:11 代(Tiger Lake)及更早的处理器必须勾选

备选方案:VAAPI

  1. 硬件加速:选择 Video Acceleration API (VAAPI)
  2. VA API 设备:填入 /dev/dri/renderD128
  3. 勾选 启用硬件解码

QSV vs VAAPI 选择建议:QSV 是 Intel 专有技术,直接调用媒体引擎,通常比 VAAPI 有更高吞吐和更好的 HDR 色调映射表现。对于第 7 代及以后的 Intel 处理器,优先选择 QSV。

六、媒体库命名规范(关键)

这是实际部署中最容易踩坑的地方。即使文件本身正常,命名不规范也会导致 Jellyfin 无法识别或播放报错。

6.1 电视剧的正确目录结构

/media/tv1/剧名/
├── Season 01/
│   ├── 剧名 S01E01.mkv
│   ├── 剧名 S01E02.mkv
│   └── ...
├── Season 02/
│   └── ...

核心规则:

  • 剧名文件夹 → Season XX 子文件夹 → 剧名 SXXEXX.mkv
  • 季目录必须用 Season 01 格式,不要用 S01、SE01、第十五季、第1季 等
  • 文件名必须包含 S01E01 这种格式,不能写成 E01、01、第1集 等
  • 如果只有一季,也建议保留 Season 01 目录

6.2 正确示例

/media/tv1/老友记/
├── Season 01/
│   ├── Friends (1994) - S01E01 - The One Where Monica Gets A Roommate (1080p BluRay x265 Silence).mkv
│   ├── Friends (1994) - S01E02 - The One With The Sonogram At The End (1080p BluRay x265 Silence).mkv
│   └── ...
└── Season 10/
    └── ...

这种命名完全符合 Jellyfin 标准,能被正确识别。

6.3 常见错误命名

错误写法正确写法
第十五季/Season 15/
S01/Season 01/
第1集.mkv剧名 S01E01.mkv
E01.mkv剧名 S01E01.mkv
01.mkv剧名 S01E01.mkv

6.4 电影命名规范

/media/movies/电影名 (年份)/
├── 电影名 (年份).mkv
├── 电影名 (年份).zh.srt
└── poster.jpg

电影文件名建议带年份,必要时加 TMDB ID:

流浪地球2 (2023) [tmdbid=843527].mkv

七、字幕、音轨与多轨道支持

7.1 字幕格式支持

Jellyfin 支持几乎所有主流字幕格式,但分为两类:

  • 文本型字幕(SRT、ASS/SSA、WebVTT):以文字形式存储。SRT 兼容性最好,通常不会触发转码。ASS/SSA 带有复杂样式,浏览器可能无法完美渲染,有一定概率触发转码。
  • 图像型字幕(PGS、VobSub):本质是一张张图片。Jellyfin 无法在客户端直接叠加显示,必须将字幕“烧录”进视频画面中。

关键问题:“烧录”字幕会强制触发视频转码。即使视频本身可以硬解,只要选择了 PGS/VobSub,或客户端无法渲染的 ASS,Jellyfin 就必须启动 FFmpeg 重新编码视频。

最佳实践:尽量使用 SRT 字幕,对 Intel 核显最友好。

7.2 多音轨和多字幕自由切换

Jellyfin 完全支持在播放时自由选择 MKV 文件内嵌的多条音轨和字幕轨道。

在播放界面中,点击 “对话气泡” 图标(字幕)或 “音符/扬声器” 图标(音频),会弹出当前文件包含的所有轨道列表。

注意:在直接播放时,所有轨道都可自由切换。但在转码播放时,部分客户端可能会锁定音轨或无法选择某些字幕。

7.3 外挂字幕和音轨命名

电影名.mkv              (主视频)
电影名.zh.srt           (中文字幕)
电影名.en.forced.srt    (英语强制字幕)
电影名.zh.default.ass   (默认中文字幕)
电影名.zh commentary.aac(中文导评音轨)

语言识别靠后缀(如 .zh、.chs、.zh-CN),而不是靠文件名里的“中文”两个字。

7.4 自动下载字幕插件

Jellyfin 本身没有内置的自动字幕下载功能,但可以通过安装插件实现:

插件名称主要特点字幕源
Open Subtitles官方插件,需要注册 OpenSubtitles.com 账号OpenSubtitles.com
Subbuzz聚合多个字幕源,覆盖面广Addic7ed, Opensubtitles, Podnapisi 等
Bazarr功能强大的独立字幕管理工具多种字幕源
SubtitleGrabber通过网页抓取,无需 API 密钥OpenSubtitles.org

安装方法:进入 控制台 → 插件 → 目录,找到对应插件,点击 安装。安装后重启 Jellyfin 容器使插件生效。

八、Jellyfin 如何管理视频文件

8.1 核心机制:遍历 + 数据库

Jellyfin 管理视频的方式可以概括为:遍历目录负责“发现文件”,数据库负责“记住和管理”。

当你添加媒体库时,Jellyfin 会:

  1. 递归遍历指定目录及其所有子目录
  2. 按扩展名过滤视频、字幕、音频等支持的文件
  3. 解析命名,判断是电影还是剧集
  4. 抓取元数据,从 TMDB、TVDB 等在线数据库获取海报、简介、演员、评分
  5. 写入数据库,保存文件路径、识别结果、元数据、播放状态

Jellyfin 默认使用 SQLite 数据库,文件位于 /config/data/ 目录下。数据库不存储视频文件本身,只存路径和相关信息。

8.2 实时监控与定时扫描

  • 实时监控:通过文件系统通知(inotify)监听媒体目录,新增或删除文件时自动更新。但在 Docker 中挂载网络存储(如 NFS、SMB)时,inotify 可能失效。
  • 定时扫描:在“控制台 → 计划任务”中设置,比如每天凌晨扫描一次。
  • 手动扫描:在媒体库设置中点击“扫描媒体库”立即更新。

8.3 元数据可以外置保存

默认元数据存在数据库里,但 Jellyfin 也支持把元数据写到媒体文件夹旁边:

  • .nfo 文件:包含电影/剧集的元数据
  • 图片文件:poster.jpg、fanart.jpg、logo.png

开启方式:控制台 → 媒体库 → 你的媒体库 → 元数据保存方式,勾选“保存元数据到媒体文件夹”。

8.4 界面能对文件做什么

  • 删除媒体文件:在影片详情页点击 ⋮ → 删除,可选择“仅从库中移除”或“删除文件”。
  • 编辑元数据:修改标题、简介、评分、海报等信息。
  • 扫描与刷新:手动同步数据库与文件系统状态。
  • 文件夹视图:在“控制台 → 媒体库 → 显示”中开启,按硬盘实际文件夹结构展示。

不能做的:Jellyfin 无法在界面中直接移动或重命名视频文件。

九、多用户管理与内容隔离

9.1 创建独立用户

在 控制台 → 用户 → 点击 + 号,为每位家庭成员创建专属账户。

9.2 按用户分配媒体库权限

  1. 在 控制台 → 用户 中,点击对应用户头像下的 ...,选择 “媒体库访问”
  2. 取消勾选“启用对所有媒体库的访问”
  3. 在下方列表中,按需勾选该用户允许访问的媒体库

应用场景:儿童账户只勾选“儿童电影”、“儿童动画”;成人账户勾选“电影”、“剧集”、“4K 电影”等完整库。

9.3 家长控制

进入 控制台 → 用户 → 点击用户 → 家长控制,可以设置:

  • 最高允许分级:比如设置为 PG-13,该用户无法看到 R 级或更高级别的电影
  • 阻止未分级内容:勾选后,未标注分级的影片也会被隐藏

9.4 访问时间表

可以为账户设置 访问时间表,限定其只能在特定时间段使用 Jellyfin。

十、验证硬件加速是否生效

方法一:观察 CPU 占用率

播放一部 H.265 编码的 4K 片源,通过 SSH 在宿主机运行 top。CPU 占用率个位数到 20% 左右说明硬件转码在工作;接近 100% 则说明仍在软解。

方法二:查看播放信息

在 Jellyfin 播放器中点击齿轮图标 → 播放信息,查看“解码器”字段。显示 VAAPI 或 QSV 即表示硬件加速已生效。

方法三:使用 intel_gpu_top 监控

sudo apt install intel-gpu-tools
sudo intel_gpu_top

播放视频时,如果 Video 和 Render 栏有数值变化,说明 GPU 正在参与转码。

方法四:查看 Jellyfin 转码日志

docker exec jellyfin cat /config/log/ffmpeg-transcode-*.log | tail -50

日志中出现 h264_vaapi、hevc_qsv 等硬件编码器标识,说明硬解成功。

十一、常见问题排查

问题 1:容器内看不到 /dev/dri

docker exec -it jellyfin ls -l /dev/dri

如果为空,说明 devices 映射未生效。检查 docker-compose.yml 中 devices 字段是否正确。

问题 2:权限不足(Permission denied / No VA display found)

日志中出现 No VA display found for device /dev/dri/renderD128,说明容器内用户无权限访问渲染节点。

  • 确认 PUID / PGID 与宿主机用户匹配,且该用户已在 render 组中
  • 检查宿主机 renderD128 的组所有者:stat -c "%G" /dev/dri/renderD128

问题 3:QSV 启用了但未被使用

  • 确认 Jellyfin 使用的是 jellyfin-ffmpeg 而非系统 FFmpeg。在“控制台 → 播放 → FFmpeg 路径”中确认路径为 /usr/lib/jellyfin-ffmpeg/ffmpeg
  • 检查日志中是否有 FFmpeg 错误

问题 4:HDR 视频转码绿屏或色彩异常

这是 Intel 第 11 代及更新核显的已知问题。可以尝试在 Jellyfin 中关闭 VPP 色调映射,或改用 VAAPI 进行测试。

问题 5:中文/ASS/SSA 字幕渲染乱码

部分字幕格式会强制触发转码,且可能在渲染时出现豆腐块。建议将字幕转换为 SRT 格式,或安装中文字体:

docker exec -it jellyfin apt install fonts-noto-cjk-extra

问题 6:文件移动或改名后 Jellyfin 找不到

数据库存的是绝对路径,文件移动、改名或 Docker 挂载路径变化都会导致 Jellyfin 显示“缺失”。

问题 7:明明有文件却显示“无法找到有效的媒体源”

这是实际部署中最常见的问题之一。排查顺序:

  1. 确认文件本身可读:
docker exec -it jellyfin /usr/lib/jellyfin-ffmpeg/ffprobe /media/tv1/剧名/Season\ 01/剧名\ S01E01.mkv

如果 ffprobe 能正常输出视频流信息,说明文件本身没问题。

  1. 确认容器内能看到文件:
docker exec -it jellyfin ls -la /media/tv1
  1. 确认后台路径是容器内路径,而不是宿主机路径。
  2. 检查季目录命名:必须用 Season 01 格式,不能用 S01、第十五季 等。
  3. 删除条目 + 替换元数据:在 Jellyfin 后台找到该剧集,点击 ... → 删除 → 选择 “仅从库中移除”,然后执行 “刷新元数据 → 替换所有元数据”。
  4. 如果还不行,删除整个媒体库重新添加。删除媒体库不会删除硬盘上的文件,只清除数据库记录。
  5. 暂时禁用 TMDB 插件:有社区反馈 TMDB 插件有时会破坏媒体库读取。进入 控制台 → 插件 → 电影数据库 (TMDB),暂时禁用它,然后重新扫描。

问题 8:U盘挂载失败(NTFS 元数据不一致)

报错 $MFTMirr does not match $MFT (record 0),说明 NTFS 分区文件系统元数据不一致。

解决方法:

sudo apt install ntfs-3g
sudo ntfsfix /dev/sdb3

如果 ntfsfix 无法修复,需要在 Windows 上执行 chkdsk E: /f(替换为实际盘符),然后关闭 Windows 快速启动,执行一次完全关机。

问题 9:界面报 ChunkLoadError

Loading CSS chunk 6496 failed. (error: .../6496.0ed5f5d94d96c9768f1d.css)

这是浏览器或客户端缓存了旧版本的 Web 界面资源。强制刷新(Ctrl + Shift + R)或清除站点数据即可解决。Jellyfin Media Player 客户端可以在界面空白处右键选择 Reload。

问题 10:U盘自动挂载不稳定

Linux 桌面环境对 U 盘的临时挂载路径(如 /media/用户名/U盘名)重启后可能改变。建议让 U 盘固定挂载:

  1. 找到 U 盘 UUID:sudo blkid
  2. 编辑 /etc/fstab,添加:
UUID=你的UUID /mnt/usbdrive exfat uid=1000,gid=1000,umask=0022,nofail,x-systemd.automount 0 0
  1. 应用配置:sudo mount -a

禁用桌面自动挂载:

gsettings set org.gnome.desktop.media-handling automount false
gsettings set org.gnome.desktop.media-handling automount-open false

或无图形界面时,创建 udev 规则 /etc/udev/rules.d/99-disable-automount.rules:

ACTION=="add", SUBSYSTEM=="block", SUBSYSTEMS=="usb", ENV{UDISKS_IGNORE}="1"

然后:

sudo udevadm control --reload-rules
sudo udevadm trigger

十二、总结

部署流程四步走

  1. 宿主机安装驱动:intel-media-va-driver-non-free(Ubuntu/Debian),并确保用户加入 render 组
  2. Docker 映射设备:在 docker-compose.yml 中添加 devices: - /dev/dri:/dev/dri
  3. Jellyfin 界面开启:控制台 → 播放 → 转码 → 选择 QSV,填入 /dev/dri/renderD128
  4. (可选)开启低电压模式:Jasper Lake / Elkhart Lake 平台必须配置 GuC/HuC

关键要点回顾

  • 硬件加速选择:第 7 代及以后的 Intel 处理器,优先选择 QSV 而非 VAAPI
  • 媒体库命名规范:季目录必须用 Season 01 格式,文件名必须包含 S01E01,不能用中文季名或简写
  • 多磁盘映射:映射到同一父目录的不同子目录,Jellyfin 里只添加一个路径即可
  • 字幕最佳实践:尽量使用 SRT 字幕,避免 PGS/VobSub 强制转码拖累性能
  • 多用户隔离:通过“创建账户 → 分配媒体库权限 → 家长控制”三步,为每位家庭成员打造专属观影界面
  • 界面管理边界:Jellyfin 适合媒体库层面的管理,不适合文件系统层面的整理
  • 播放错误排查:先确认文件本身可读(ffprobe),再检查命名规范,最后考虑删除条目重新识别

通过这套方案,即使是一台搭载 N100 的低功耗迷你主机,也能流畅转码 4K/H.265 视频,为全家提供稳定、免费、私有的媒体串流服务。

作者

老丹

关注我
其他文章
上一个

Ubuntu 26.04 禁用 4G 模块网卡驱动(保留串口)完整指南

下一个

Ubuntu Samba 服务安装与配置完全指南

关于博主

    老丹是一名C/C++后台开发工程师,信奉“无抽象不设计,无性能不生产”。

  • 技术栈:Modern C++、Linux环境编程、多线程/并发、网络编程等。
  • 信条:能用constexpr解决的问题绝不拖到运行时,能靠RAII避免的泄漏绝不写析构。
  • 正在填坑:从解封装到渲染的C++全链路实现,正在驯服FFmpeg与H.264/H.265。
  • 输出原则:这里的每一段代码都经过-Wall -Wextra -Werror -O2的洗礼。

近期文章

  • Ubuntu 防火墙迁移指南:从 UFW 到 firewalld 的完整实践 2026年9月12日
  • Nano 编辑器完全操作指南:从入门到熟练 2026年9月12日
  • SSCG:让自签名证书不再“危险”的生成工具 2026年9月12日
  • Ubuntu Samba 服务安装与配置完全指南 2026年9月12日
  • 从零开始:用 Docker 部署 Jellyfin 并启用英特尔核显硬件加速 2026年9月11日

文章分类

  • C/C++开发 (22)
  • Docker容器 (5)
  • Linux工具包 (17)
  • Linux服务配置 (50)
  • Linux系统 (16)
  • OpenWrt路由 (3)
  • Shell脚本 (3)
  • 代码管理 (1)
  • 安防技术 (4)
  • 数据安全 (36)
  • 未分类 (1)
  • 网络协议 (25)
  • 计算机理论 (23)
  • 音视频技术 (5)
联系我们:📍 地址:中国·广东省深圳市   |   ✉️ 邮箱:support@tanglinux.com   |   💬 QQ:870866607
版权所有:老丹的足迹粤ICP备2026061170号-1       公安备案图标 粤公网安备44030002013274号