[NAS 系列第二弹]配置全自动的影视文件下载、刮削和整理

在上一篇文章中，我记录了硬件组装和系统安装的过程，最后成功安装了 Arch Linux：

接下来我将着重描述应用软件的使用和配置。今天这篇主要写如何配置全自动的影视文件下载、刮削和整理。

注：

读者继续前需确保自己对 BT、PT 等概念有着基本的认识；

nastools 需要有认证站点账号才能正常使用，后续不会额外描述，请自行获取认证站点账号使用；

本篇仅描述思路和整体流程，不会将所有相关知识都罗列出来，还请结合 相关资料 食用；

本篇不解决网络问题，默认 docker 镜像等均可连接外网，如果不行请手动为镜像配置 HTTP_PROXY、HTTPS_PROXY。

综述

在介绍流程前，我需要针对这套流程的各个组件分别做一个简单的介绍，让读者对此有一个整体的认识。下面对这些组件分小节描述。

资源来源

很好理解，我们要下载的文件总是有一个来源的，在这个场景中，我们的资源来源主要指各类 PT 站点。

索引器

为了在站点中查找资源，我们需要索引器。顾名思义，索引器就是在站点中搜索用户输入的内容，并返回结果的工具。

下载器

在索引结束，我们挑选出匹配的资源后，需要将资源的种子交给各类 BT 下载工具，让其解析种子内容并下载到本地。

媒体服务器

在文件下载到本地后，我们需要一个集中入口以访问和管理我们的视频文件，提供远程播放等功能。这种工具即媒体服务器。

刮削器

所谓刮削器，就是从一个视频文件中提取这个视频相关的影片图片、评分、描述等信息的工具。这类工具一般的实现机制是使用视频的文件名去开放的影片信息站点（如 TMDB）找到匹配的影片信息，然后用匹配到的影片信息标记这个视频文件。
一般来说媒体服务器会自带刮削功能，可以识别本地文件对应的影片，但效果较差，往往无法匹配到。

转移器

转移器和刮削器紧密相关。上面提到媒体服务器会自带刮削功能，但效果较差。主要有两个途径解决这一点：

不使用媒体服务器的自带刮削，自己手动使用第三方工具（如 TMM ）手动刮削；

把视频文件的名字改为简单的 “影片名 + 年份” 的格式，这种格式的命名被媒体服务器的自带刮削识别的概率几乎是百分百。

这里的第二种途径就是我说的 “转移”，但由于下载器不仅要下载视频文件，还需要保证视频文件存在，不然无法做种。因此转移也大体分出了四个类型：

移动 / 重命名（直接修改原始文件，不能继续做种）

复制（拷贝一份，可以继续做种但浪费一半的硬盘空间）

软链接（不额外占用空间，但由于软链接往往不会被视为文件，使用一般的文件管理器浏览目录时无法看到软链接）

硬链接（不额外占用空间，可以被文件管理器识别，但无法跨硬盘分区）

实践上往往选择软链接和硬链接做文件的转移。

总结

以上，我介绍了这个流程的各个组成部分，为了方便理解拆得比较零散，很多工具都是同时具有其中的多项功能的。

在后文中，我将使用 nastools 接入资源来源并作为索引器、转移器， qbittorrent 作为下载器，emby 作为刮削器、媒体服务器来进行配置。

前置依赖

下列应用程序均使用 docker / docker compose 运行，在 Arch Linux 中，可以通过如下命令安装：

Copy
sudo pacman -S docker docker-compose

运行 Qbittorrent

使用 johngong/qbittorrent:latest 镜像运行，以下是我的 compose.yml 样例：

Copy
services:
container:
network_mode: host
environment:
- UID=1000
- GID=1000
- UMASK=022
- TZ=Asia/Shanghai
- QB_WEBUI_PORT=54321 # web 端口
- QB_EE_BIN=false
- QB_TRACKERS_UPDATE_AUTO=true
- QB_TRACKERS_LIST_URL=https://raw.githubusercontent.com/ngosang/trackerslist/master/trackers_best.txt
volumes:
- /home/amtoaer/Downloads:/Downloads # 下载目录
- /home/amtoaer/.config/nas/qbittorrent:/config # 配置文件
image: johngong/qbittorrent:latest
restart: always

使用 docker compose up -d 运行，打开 ip:${QB_WEBUI_PORT}能够看到页面即可，此处不赘述：

运行 Emby

Emby 本身是付费软件，此处使用的是破解版，如有需要还请购买正版。

使用如下 compose 文件：

Copy
services:
container:
network_mode: bridge
image: lovechen/embyserver:latest
environment:
- UID=1000
- GID=1000
- GIDLIST=0
volumes:
- /home/amtoaer/.config/nas/emby:/config # 配置文件
- /home/amtoaer/Videos:/Videos # 媒体目录（非下载目录）
ports:
- 54319:8096 # 左边是宿主机端口
devices:
# 此处需参考官方文档，可能需挂载内容不一致
- /dev/dri:/dev/dri
restart: always

同样 docker compose up -d 运行，打开 ip:port 访问 web 页面，完成初始化过程，进入到主页（初始化完成应该是空的，不过布局与此一致）：

运行 nas-tools

Copy
services:
container:
network_mode: bridge
ports:
- 54317:3000 # 左边是宿主机端口
volumes:
- /home/amtoaer/.config/nas/nas-tools:/config # 配置文件
- /home/amtoaer/Downloads:/Downloads # 下载目录
- /home/amtoaer/Videos:/Videos # 媒体目录
environment:
- PUID=1000
- PGID=1000
- UMASK=022
- NASTOOL_AUTO_UPDATE=false
- NASTOOL_CN_UPDATE=false
image: nastool/nas-tools:latest
restart: always

运行命令与上面相同，打开 ip:port，登录账号：

配置

接下来需要通过配置来让这几个程序联动，整体的工作流程是这样：

nastools 中配置 PT 站点的账号，并开启对应的索引器；

在 nastools 中搜索或订阅资源，下载时向 Qbittorrent 抛出下载任务；

下载结束后，触发 nastools 的转移，将视频文件通过指定的转移方式从下载目录转移至媒体目录；

emby 将媒体目录设置为媒体库，文件转移结束后识别到媒体目录下有了新的文件，触发刮削流程，将视频显示在 emby 中。

下面分别详述。

配置账号并开启索引器

进入 nastools 侧边栏的 “站点维护”，点击右上角 “新增站点”，添加站点相关信息：

接着在侧边栏 “设置 -> 索引器” 中，打开所有支持的站点：

设置下载器

侧边栏 “设置 -> 下载器” 中，配置连接自己的下载器：

注：

nastools 运行于 docker 中，172.17.0.1 是 docker 默认网络的默认网关，表示宿主机。

监控设置成 “是” 表示下载完毕时触发转移，设置成 “否” 表示监听下载目录，当下载目录下有新文件时触发转移。个人设置为 “否”，通过监听下载目录完成转移。

设置监听目录

如果下载器的监控设置选择了 “否”，需要在侧边栏 “设置 -> 目录同步” 中开启对下载目录的监听，样例如下：

这里我转移方式选择了 “复制”，读者可能会感到奇怪，因为复制明明会占用双倍的存储空间，造成严重浪费。对此好奇的读者可以查看文末我的解释。

设置媒体服务器

点击侧边栏 “设置 -> 媒体服务器”，选择 Emby 并填写内容：

API Key 通过 Emby “设置 -> API 密钥” 生成。

设置 Emby 的媒体库目录

在 Emby “设置 -> 媒体库” 中新增媒体库，一个示例的配置如下：

总结

经过上述配置后，这套流程应该已经可以正常工作了，以下作为演示：

在搜索框搜索影片名称，并点击影片左下方的搜索

点击想下载的种子，选择分类（当然也可以自动）后下载

看到 nastools 自动为 Qbittorrent 添加了任务：

下载完成后自动转移，并被 Emby 刮削展示在媒体库中

至此配置完成。

拓展阅读

为何宁可使用闭源付费的 emby 破解版也不使用 emby 的开源 fork jellyfin？

一言以蔽之，使用体验差异巨大。

最开始我也抱着支持开源的心态，首先尝试了 jellyfin，但在使用过程中，至少发现了如下问题：

整体 UI 丑陋且几乎毫无变化
虽然最近推出了 jellyfin-vue，但也还没有应用到客户端，而且 android 客户端不会使用系统字体，而是自带了一套，观感割裂。

令人难以忍受的高强度磁盘 IO
在刮削时 jellyfin 的硬盘读写极其频繁，emby 这边即使开启 “识别视频片头” 这种依赖读取视频文件的功能，都要比 jellyfin 的普通刮削更加安静迅速。

慢到令人发指的初次刮削速度
曾经我有将近 8T 的资源，使用 jellyfin 在无任何额外设置的前提下居然刮削了数个礼拜。查询 jellyfin 的相关 issue，发现这个问题在很久前就有人提过，但挂了三年多还是 open。

因此，我抛弃了 jellyfin，转投到了 emby 的怀抱。

虽然但是，十分不推荐小伙伴们用盗版软件。因为我最开始是抱着试试的心态，所以没有下决心付费，毕竟 119 刀不是个小支出，但嫖了这么久也差不多到补票时间了。
最近人民币跌太狠了，等涨一些就打算补票入正了。

转移方式为何选择复制，不会占用额外存储空间吗？

如我上文所述，为了不浪费额外存储空间，转移方式往往会在软链接和硬链接中选择，但为什么我要选择复制呢？是因为我硬盘使用的 btrfs 文件系统支持 cow 机制。

简单来说，文件系统中的 cow 是指在复制文件时，新文件仅仅包括了一份元信息，实际的数据块是和原始文件共用的，在后续要对复制的文件做修改时才会实际复制这个文件的数据块。考虑我们的文件转移场景，其实仅仅是想要把视频文件移动到一个新位置，并没有任何对视频文件做修改的需求，所以可以完美利用这个机制达到复用空间的目的。

这样做一方面避免了软链接在文件管理器中无法识别的弊端，又绕过了硬链接只能在同一块物理硬盘的限制（未实际尝试但理论上可行，因为 btrfs 既支持创建跨多块物理硬盘的磁盘分区，又支持分区内子卷的 cow 复制）。

但实际使用发现 nastools 中的复制不支持该特性，查看源码可以得知 nastools 中使用的复制是 shutil.copy2(os.path.normpath(src), os.path.normpath(dest))，而该方法是不支持这种空间复用（又被称为 reflink）的特性的。因此我将代码中此处换成了第三方库 reflink 来达到目的。

实际可以看到通过 reflink 复制过来的视频文件都是没有占用任何额外空间的：

相关资料

上面我介绍的功能只是这些工具的很小一部分，如 nastools 还支持视频订阅、自定义识别词、自定义忽略词等；emby 还支持片头标记、用户管理、视频转码等。需要用户结合资料自行探索：

nastools 官方 wiki

emby 文档