Files
blogs/docs/diaries/wbsy/nas-media.md
SilverAg.L fa16a643aa
All checks were successful
部署文档 / build (push) Successful in 1m3s
Edit Diary: nas media
Signed-off-by: SilverAg.L <caclx@outlook.com>
2026-02-18 01:29:47 +08:00

11 KiB
Raw Blame History

Jellyfin 真的好用吗?

我的结论是:实则不然。但 DIY 这一块本就是矮个子拔高个,也没那么多平替可以挑。

Important

  • 本文字里行间夹带着作者的私货,行文并不严谨,谨慎阅读。
  • 本文有关的折腾流程时间跨度较长,经验之谈不说没有,也只能说碎得跟渣一样。所以不是笔记而是大作文。

硬件加速,硬件呢

我是 Linux Docker 部署的。由于因特耳的核显驱动闭源,官版 Docker 容器搞起来后还需要exec -it进去装 Intel 驱动。即便是nyanmisaka版开箱即用 Jellyfin 镜像,也需要手动映射渲染节点(他们就没设置过render用户组,若要映射整个/dev/dri后续就需要进去groupadd)。

::: details docker-compose.yml See AgxCOy@liteyuki/agserver.svc.

services:
  jellyfin:
    image: nyanmisaka/jellyfin:latest
    container_name: jellyfin
    network_mode: 'host'
    volumes:
      - /var/lib/jellyfin:/config
      - jellyfin-cache:/cache
      - /media:/media
      # - /dev/dri/renderD128:/dev/dri/renderD128
      - type: bind
        source: /usr/share/fonts/opentype
        target: /usr/local/share/fonts/custom
        read_only: true
    devices:
      - /dev/dri/renderD128:/dev/dri/renderD128
      #- /dev/dri/card0:/dev/dri/card0
    restart: 'unless-stopped'
    # Optional - alternative address used for autodiscovery
    # environment:
    #   - JELLYFIN_PublishedServerUrl=
    extra_hosts:
      - 'host.docker.internal:host-gateway'
volumes:
  jellyfin-cache:
    driver: local

:::

媒体库组织

我还是更习惯树形文件系统,媒体库还是太难为我了。那样的话,事情或许也很简单——许多成品 NAS 都有自带视频、相册之类的浏览功能。但很遗憾,自己装的 Ubuntu Server 自然什么都没有。

我针对的还是 Jellyfin “神奇”的资源组织方式。就像这篇《基于 Jellyfin 和音流的 nas 影音库搭建及踩坑》所说,“为什么不直接读取音乐标签进行专辑聚合”呢?

音乐:混乱的元数据

然而事实上,即使真的能做到自动专辑聚合,元数据本身的刻录和查询也是一片混乱。上面援引的博文推荐 MusicTag 这个工具,但同是从网易云那刮削,下载下来本是《紫罗兰永恒花园 OST》的曲目能给它识别成《凹凸世界五周年》也是给我看笑了。更别说国外的 MusicBrainZ 数据库有相当一部分冷门曲目并没有收录(尽管 Spotify 等平台能够找到),手动录入更是个吃力不讨好的体力活。

误刮削

::: tip 最简方案 文档这么说:我管你怎么整理,我只知道是同一张专辑就该塞在同一个文件夹

那么事情也好办,就按专辑名来呗。好比如:music/{album or "[standalone]"}/{artist1,artist2} - {title}

  • 为什么要or "[standalone]"

    • 不单独收纳没有专辑的单曲,结果就会被淹没在大几百首、好几页的“歌曲”页面。
  • 要是有专辑重名了(比如两张专都叫Fragrance

    • 没招,默认合并(甚至可以看到重复的曲号,都是第六首)。只能手工分离(Fragrance - SoundzImageFragrance - Hatsune Miku)。 :::

电子书:吃力不讨好

至于小说漫画,或者说书籍媒体库,那只能说真搭一个私人图书馆也是同样的编排要求,满满的工作量。

不禁想到米哈游创始人蔡浩宇的“快乐守恒定律”:你做的过程中如果很轻松快乐,那么你做出来的结果未必能给人带来快乐。
媒体库编排是不是也要“苦其心志、劳其筋骨”,借阅者、用户才能有好的体验呢?但话又说回来,像 Jellyfin 这样的家庭影院通常都是自己管理自己用,费那么大功夫组织这些文件,观赏的体验又能改善多少呢?

我相信大多数*并不在乎资源来源*的读者去找网络上流通的小说肯定优先去找 txt、doc(x) 这种容易打开的格式。但现有的私人图书馆,无论 Jellyfin 这种顺手实现的,还是 Kavita 这种专用的,都不支持这些格式。Calibre 也许可以,但书目的元数据就成了另一桩麻烦事

::: tip 最简方案 那当然是通通转换成 pdf单纯当作文件管理器那样访问文件夹、文件最简单。但 pdf 对移动端并不友好,文字内容并不能自适应,更多还是用于漫画。 :::

进阶一点的方案就只能按照文档来了。啰嗦是显然的,但如前面的“快乐守恒定律”所言,苦一苦自己,阅读体验才能好起来。

首先讨论相对容易些的漫画。“画”嘛,总归是一张张的图片序列。把它们打成压缩包1 (当然多数网站已经打好包给你下载了),我们就得到本体了。顺带一提.cbz.zip.cbr.rar.cb7.7z有需要的话改个后缀名就是了。至于元数据Jellyfin 文档指出只有 epub 书籍才允许元数据集成在文件里,对于这种漫画压缩包,需要另写ComicInfo.xml。也就是说,每一本、系列的每一话,都需要单独的文件夹放置元数据和本体

然后是 epub 电子书,它的话则更麻烦亿些。现有的 epub 编辑器并没有像写 bilibili 专栏(或者像 Word 文档)那样自动编纂页面的能力,操作起来更像是手搓 HTML 博客。所以,图方便的话更建议在线转换.txt .doc(x)文档。

::: details EPUB 内容物 epub 的 mimetype 通常标application/epub+zip,说明其本质是压缩包。解压出来通常分这么几块:

  • mimetype:资源类型标识,内容如上。
  • META-INF/container.xml标明电子书OEBPS 包)的根目录。
  • OEBPS/
    • Images/cover.*:封面
    • Styles/*.css:网页排版
    • Text/*.*htm*:反正必须是 HTML。
    • content.opf:电子书的元数据、内容物信息。
    • nav.*htm* nav.opf:电子书的目录。前者为 epub3 标准,后者为 epub2 标准,通常在content.opf里特别标注。
    • Fonts/ Audio/ ...:其他内容。

所以我称编辑 epub 这件事为“手搓 HTML 博客”,因为本来就需要按章回编排 HTML 内容。每一章是一页 HTML不恰好对应一篇博文吗 :::

::: warning 书目目录索引 和 Calibre 等阅读器不同Jellyfin 对目录的跳转以 OEBPS 包为基准,而不是以目录文件为基准。如果发现 Jellyfin 里点目录里的章标题没有反应,你需要用 Sigil 等编辑器将nav.*移动到OEBPS/目录下。 :::

::: note 文件组织 实测结论是:可以不像漫画那样遵循官方文档“一书一目录”的要求,但应尽量避免“一目录只有一 epub”的情形。像以下情形 Jellyfin 会误判:

  • Books
    • 正经的
      • 《时间简史》.epub
      • 毛泽东
        • 《实践论》.pdf
        • 《矛盾论》.pdf
      • 《葬送的芙莉莲》.pdf
    • 不正经的

扫描结果是:“不正经的”和《时间简史》。其余读物无法直接访问(可能仍能搜索到)。 :::

元数据刮削:一笔糊涂账

前面我也论述过,音乐专辑的元数据库就是几桌草台班子。但比起草台班子,更令我恼火的当属大把大把的、查无此人的“黑户”。怎么来的?音声、同人志、网文。

我的整理方式和 acgdb 类似3D 区、音声区作者分发、油管录播、DLsite 正作)、书目区(漫画和文集)、写真区、插画区。

3D 区无论玩恋活还是 MMD既有图集又有视频无法按媒体类型区分。即便真要分它算电视节目电影MV分不明白。

音声区大量的音频资源,摆烂一点直接用电子书库、按文件夹访查也不是不行,但显示出来反倒是专辑名(或者说 DLsite、系列作品名更显眼而非每一集的标题若要用音乐库收纳就得改造一番目录树适配它那个“一个专辑只有一个目录”的原则工作量也不小。

至于书目区,像上面列的“正经读物”想获取元数据并不难。那“不正经读物”呢?对比出版物,网文显然算不上“正经”,但豆瓣之流依然有机会找到。所谓的同人文受限于作者的圈地自萌,但若是有缘知道 Ta 发布的平台,也是能记下元数据的(同人圈子对打 Tag 这件事很看重。那么只剩下来源不正经、题材也不正经的“那种”作品了它们流通的地方通常都是论坛这种早期网络社区只知道个标题甚至标题也不一定知道。What can I say?

偏偏这种不在台面上的“资源”我收纳了不少,哪怕有自动化工具,后续校对也是个体力活,何况很多资源只能一件件手工入库。饶了我吧。

穿透与反向代理

如今连网易云也改得不知为何物了,于是我随身听的需求便也转向 Jellyfin。最简单的方法可以是 ZeroTier但安卓有“同一时间只允许一个 VPN”的限制所以在群友指导下搞了内网穿透FRP

此后,我遇到了子网划分的问题。起初这个问题并不起眼,直到我在户外同时尝试走 ZeroTier 和穿透,我才发现 frp 连上之后似乎更像是在本地回环,而 Jellyfin 似乎对本地回环不设限速

写着写着总会变成报流水账。

AI 对此的解法是在 frp 这里记录下真实 IP。我选配的服务商支持 Proxy Protocol也更推荐这么实现。但在实地测试后发现 Jellyfin 并不直接支持 Proxy Protocol那么就只能在 frpc 跟 Jellyfin 之间多加一层 nginx 做反向代理了frps 显然我是动不了的)。

方法很简单frp 侧仍旧启用 Proxy Protocol在 nginx 里剥离真实 ip。我是在 Ubuntu Server 上安装的 nginx据称已集成real-ip模块。那么编辑/etc/nginx/sites-enabled/default(我是图方便直接原地开刀了):

server {
  listen 8097 proxy_protocol;
  listen [::]:8097 proxy_protocol;

  #root /var/www/html;
  set_real_ip_from 127.0.0.1;
  real_ip_header	proxy_protocol;

  # Add index.php to the list if you are using PHP
  #index index.html index.htm index.nginx-debian.html;

  server_name _;

  location / {
    proxy_pass	http://127.0.0.1:8096;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Protocol $scheme;
    proxy_set_header X-Forwarded-Host $http_host;

    # for websocket
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    # First attempt to serve request as file, then
    # as directory, then fall back to displaying a 404.
    #try_files $uri $uri/ =404;
  }

  # ...
}

此外 Jellyfin 文档还提到要给真实 IP“打码”。由于有些配置项是写在 http 全局块里,目前也不清楚会不会对其他监听造成影响,我就先没整这个了。


  1. 还请注意不要把文件夹层级包含进去。换言之,用软件打开压缩包应直接显示图片序列↩︎