Skip to content
twinkling.top服务JellyfinEN
板型Pi 4B 4GB minimum, 8GB if more than one stream transcodes
内核6.6.51+rpt-rpi-v8
空闲温度48 °C
内核架构arm64
参考机:Pi 4B 8GB / Bookworm 64-bit

部署配方 · 媒体

Pi 4 上的 Jellyfin:什么格式才不用转码

关于树莓派上的 Jellyfin,最诚实的总结是:它是个称职的文件服务器,是个平庸的转码器。只要客户端自己解得动,一切都很顺;一旦需要树莓派用 CPU 转码,4B 大约只够一路 1080p,再多就开始掉帧。这篇讲的是怎么整理媒体库,让转码几乎不发生。

jellyfin/jellyfin:10.10.7 · 2026-08-22

Jellyfin rack plate: board stack and host ports
服务参数
容器镜像jellyfin/jellyfin:10.10.7
宿主端口:8096/tcp, :7359/udp
数据目录/srv/homelab/jellyfin/config
内存预留900 MB
CPU 上限2.0 vCPU (cpus: "2.0") — transcoding is the only heavy job on this rack
更新节奏follow the stable branch, roughly every two months; read the release notes for library schema migrations before pulling
ARM 兼容arm64 native. Hardware H.264 decode works through the V4L2 device; HEVC and AV1 will fall back to software even on a Pi 5
端口映射与暴露面
宿主容器proto暴露用途
:80968096tcp仅局域网web UI, API and the apps on the TV and phones
:73597359udp仅局域网client auto-discovery on the local network

部署步骤

  1. 先在宿主机上挂载共享

    挂载和验证都在宿主机上做完再碰 Docker。容器带着空的 /media 启动会显示空库,然后把你引到错误的方向去排查。

    run
    sudo mkdir -p /mnt/nas/media
    sudo mount -a
    ls /mnt/nas/media | head
    findmnt /mnt/nas/media -o TARGET,SOURCE,FSTYPE,OPTIONS
  2. 用你自己的用户建配置和缓存目录

    官方镜像里 Jellyfin 以 uid 1000 运行。让 Docker 以 root 建出来的目录,会导致服务能启动却写不了自己的数据库。

    run
    sudo mkdir -p /srv/homelab/jellyfin/{config,cache}
    sudo chown -R 1000:1000 /srv/homelab/jellyfin
  3. 启动并看开头几行日志

    最该确认的是 V4L2 设备有没有被接受。Docker 拒绝某个设备节点时容器会立刻退出,并给出明确报错。

    run
    cd /srv/homelab/jellyfin && docker compose up -d
    docker logs --tail 30 jellyfin | grep -i -E 'v4l2|device|startup complete'
  4. 加媒体库时填容器内路径,不是宿主机路径

    Jellyfin 里的库路径是 /media/movies,不是 /mnt/nas/media/movies。填错的话,库能扫描成功,但重启后一个文件都找不到。

    run
    docker exec jellyfin ls /media
    # 这里打印出来的,才是你在媒体库对话框里该填的路径
  5. 在请别人用之前,先证明直连播放成立

    在每个客户端上播一个确定的 H.264 文件,同时盯着仪表盘。写着 Direct Play 的流对树莓派几乎零成本;原因一栏写软件转码的,才是你要找的目标。

    run
    docker stats --no-stream jellyfin
    # 播放期间 CPU 低于 15%,说明是直连播放

直接播放就是全部设计目标

树莓派的 VideoCore GPU 只硬解 H.264,其它格式基本帮不上忙。所以媒体库统一成 H.264 + AAC,容器用 MP4 或 MKV,并且所有客户端都设为直接播放。做到这一点,一台 4B 同时推三路流,CPU 占用不到 15%。

HEVC 是最有意思的一种。Pi 5 能硬解,Pi 4 不能,最近三年的手机都能。要不要保留 HEVC 文件,完全取决于你手上哪些客户端比这个编码格式还老。

文件编码Pi 4BPi 5常见手机本机架结论
H.264 1080p硬解硬解直接播放保留,这就是目标格式
HEVC 1080p软解,掉帧硬解直接播放只在电视能解时保留
HEVC 4K不行勉强通常可以别放进库
AV1不行不行仅最新手机不要收

媒体文件到底放在哪

媒体放在 NAS 上通过 SMB 共享,在树莓派上挂到 /mnt/nas/media,再以只读方式挂进容器。树莓派存元数据数据库和图片,NAS 存文件。这个分工很关键:树莓派挂了,你损失的是一次重新扫描,不是一整个媒体库。

只读不只是洁癖:它让 Jellyfin 在媒体旁边写 .nfo、下封面的习惯变成无害行为,也让一个配错的库路径不可能删掉任何东西。

shell
# 树莓派上的 /etc/fstab
//192.168.10.5/media /mnt/nas/media cifs credentials=/etc/cifs-media.cred,uid=1000,gid=1000,ro,vers=3.0,nofail,x-systemd.automount 0 0

把视频设备交给容器

Raspberry Pi OS 上的硬解走 V4L2 的 mem2mem 设备 /dev/video10 到 /dev/video12。它们在宿主机上存在,在容器里不存在——这就是为什么同一个文件 VLC 播得好好的,Jellyfin 里却把四个核全占满。

把这三个设备透传进去,并让容器加入 video 组。Raspberry Pi OS 上组号是 993,某些 arm64 发行版是 44,所以要在宿主机上确认,别照抄教程里的数字。

shell
getent group video
# raspberry pi os 上是 video:x:993:
ls -l /dev/video1*
# 只透传真实存在的节点;节点不存在会让 docker 直接拒绝启动容器

把转码器从用户面前藏起来

即便硬解都配好了,总会有客户端请求服务器软转不了的那个码率。给每个用户设一个和网络匹配的码率上限——千兆有线 12Mbps,平板上 wifi 的 4Mbps——并且强制生效,这样请求就变成了「要么直接播放要么不播」,而不是卡顿的转码。

H.264 的硬件转码值得开启:连续两路 1080p 走 V4L2,比一路纯软转还省 CPU。

shell
docker exec jellyfin ffmpeg -hide_banner -hwaccels | head -5
# 看到 v4l2m2m 才算设备透传生效了

compose 文件

整份文件放在 /srv/homelab/jellyfin/compose.yaml。标签固定版本号,不用 latest——树莓派上回滚比升级麻烦得多。

compose.yaml
services:
  jellyfin:
    image: jellyfin/jellyfin:10.10.7
    container_name: jellyfin
    restart: unless-stopped
    ports:
      - "8096:8096/tcp"
      - "7359:7359/udp"
    environment:
      TZ: Asia/Shanghai
      JELLYFIN_PublishedServerUrl: http://192.168.10.20
    volumes:
      - /srv/homelab/jellyfin/config:/config
      - /srv/homelab/jellyfin/cache:/cache
      - /mnt/nas/media:/media:ro
    devices:
      - /dev/video10:/dev/video10
      - /dev/video11:/dev/video11
      - /dev/video12:/dev/video12
    group_add:
      - "993"          # video group on Raspberry Pi OS
    networks: [rack]

networks:
  rack:
    external: true

加固清单

  • 只通过局域网内的反向代理访问,外网访问走 WireGuard,不开公网端口
  • 在 Jellyfin 后台关闭远程访问,服务不向家外自我暴露
  • 一人一个账号,不共用登录,管理员权限只保留在一个账号上
  • V4L2 设备只读透传,容器去掉一切用不到的能力
  • 媒体目录以只读方式挂载:服务端本来就不该往媒体库里写东西

备份方案

配置目录每晚同步到 NAS;媒体库本身就在 NAS 上,由 NAS 那边负责备份——树莓派上没有任何不可替代的数据。唯一值得手工导出的是用户列表和观看进度,因为「继续观看」重新累积起来要靠好几周的观看量。

上线后验证

  • 电视上播放 1080p H.264,Jellyfin 仪表盘显示 Direct Play
  • 两路同时播放时 docker stats 的 CPU 占用低于 20%
  • 客户端 App 里自动发现能直接出现条目,不用手输 IP
  • 重启容器后不会全库重扫,说明配置卷可写且持久

踩过的坑

  • 媒体只读挂载会破坏内置的字幕下载功能——它要把 .srt 写在视频旁边。要么提前下好字幕,要么接受它失败、改用把字幕存到配置目录的选项。
  • 不透传 V4L2 设备时 Jellyfin 不会报警,它只是默默软解、吃满四个核,让这台派给人一种「坏了」的感觉,而你多半会先怀疑网络。
  • CIFS 挂载没加 x-systemd.automount,容器会在共享挂载完成之前启动,看到空目录,直到下次重启都显示库里有零个条目。
  • Jellyfin 会定期写元数据数据库。放在 SD 卡上就是慢性死亡;把 /config 留在固态盘上。

硬件与选型问答

Jellyfin 用 Pi 4 够吗,还是必须 Pi 5?
4GB 的 4B 稳跑两三路 1080p 直连播放。只有当你的库是 HEVC、而客户端又解不动时,才值得买 Pi 5——它的 HEVC 硬解是唯一真正改变这台机器能力的升级。
Jellyfin 和 Immich 能跑在同一块 8GB 的板子上吗?
能,本机架就是这么跑的。给 Jellyfin 算 900MB(两路流),给 Immich 算 1.2GB(五万张照片以内),剩下的留给反代和监控。绝对不能做的是把两者塞进一块 4GB 的板子还指望转码能用。
为什么不直接用 NAS 自带的影音套件?
如果 NAS 自带并且支持你的客户端,那就用它——省下 900MB 和一个下午。Jellyfin 在这里站得住脚,是因为电视端的客户端更好用,而且观看记录和用户账号属于你,而不属于某个厂商的账号体系。