
最近整理 NAS 上的电影和剧集文件时,遇到一个很实际的问题:下载目录里的文件名经常非常混乱,包含资源站水印、清晰度、压制组、音轨、字幕信息,甚至还有拼音缩写、别名、错别字。如果全部手工整理,不仅耗时,也很容易出错。
伴随Ai编码的使用,我现在已经比较少的使用现有的代码了,主要还是为了避免一些安全上的问题,毕竟要部署在我的装着各种资料的nas上。
于是做了一个小工具:AutoReel。
它的目标很简单:
监听一个输入目录,自动识别电影和剧集,然后按 Emby / Jellyfin / Plex 友好的目录结构移动并重命名文件。
项目地址:
https://github.com/walker22026/AutoReel代码的编写过程远远的超出的我的开始预估,框架搭建起来容易,但是真正的运行,能用就有一些问题,当然更谈不上好用。
最主要的问题就是我的节目源主要来自于阿里云或者百度云,这个共享资源为了避免被“和谐”采取各种名称变型,导致猜测也猜不出来,这种情况下,我尝试使用llm来进行节目真实名称的理解,效果并不好。最终还是选择简化处理的模式,能够自动处理的自动处理,无法识别的放入特定目录中,等待使用人接入。避免llm自动处理导致的节目的整理混乱。
项目定位
AutoReel 不是一个复杂的媒体库管理系统,也不替代 Emby、Jellyfin、Plex。
它只做一件事:
把下载目录里的影视文件,整理到标准媒体库目录中。
例如:
输入目录:
/emby/source/毒液:最后·一舞.2160p.DV.HDR (2024)/xxx.mp4
整理后:
/emby/电影/毒液:最后一舞 (2024)/毒液:最后一舞 (2024).mp4剧集则整理为:
/emby/剧集/低智商犯罪 (2026)/Season 01/低智商犯罪 - S01E01.mp4当前执行策略
AutoReel 启动后会监听输入目录。
当前设计中有三个核心目录:
输入目录:/host/emby/source
电影目录:/host/emby/电影
剧集目录:/host/emby/剧集输入目录下还会自动生成:
_unrecognized 未识别目录
_duplicates 重复文件目录
_pending_delete 无媒体文件待清理目录整体流程是:
输入目录
├── 单个视频文件
│ ├── 识别成功 -> 移动到电影/剧集目录
│ └── 识别失败 -> 移入 _unrecognized
│
├── 子目录
│ ├── 作为一个批次处理
│ ├── 全部视频识别成功 -> 整个目录整理
│ ├── 任一视频识别失败 -> 整个目录移入 _unrecognized
│ └── 目标文件已存在 -> 整个目录移入 _duplicates
│
└── _unrecognized / _pending_delete
└── 扫描时跳过为什么不用硬链接
最初考虑过硬链接,这样可以让下载目录和媒体库目录同时存在一份“看起来独立”的文件,但实际只占一份空间。
不过最终我选择了直接 move 模式,也就是:
直接移动并重命名原始文件。
原因是我的使用场景更偏向媒体库整理,不需要继续做种,也不希望一个文件在多个位置看起来同时存在。这样逻辑更简单,也更容易理解:整理完成后,源目录里就不再保留原文件。
电影处理规则
电影分两种情况。
单视频目录
如果一个目录中只有一个视频文件,优先使用目录名识别电影。
例如:
毒液:最后·一舞.2160p.DV.HDR (2024)/
xxx.mp4清洗后会识别为:
毒液:最后·一舞
2024然后通过 TMDB 查询,整理为:
电影/毒液:最后一舞 (2024)/毒液:最后一舞 (2024).mp4多视频目录
如果一个目录下有多个视频文件,则更像电影合集或系列电影。
例如:
夺宝奇兵/
Raiders.of.the.Lost.Ark.1981.mkv
Indiana.Jones.and.the.Last.Crusade.1989.mkv
Indiana.Jones.and.the.Dial.of.Destiny.2023.mkv这种情况下不会只用目录名“夺宝奇兵”去匹配一部电影,而是逐个视频文件识别。只有全部识别成功后,才会整体移动。
如果其中任何一个文件无法识别,整个目录会被移动到 _unrecognized,避免整理一半导致目录结构被破坏。
剧集处理规则
剧集采用“目录优先”的原则。
原因是很多剧集文件名非常简单,例如:
低智商犯罪(2026)/
01 4K.mp4
02 4K.mp4
03 4K.mp4如果直接把 01 4K.mp4 拿去 TMDB 搜索,很可能会误识别成电影,比如:
01 -> 某部电影
02 -> 另一部电影
03 -> 又一部电影这是非常危险的。
所以现在的策略是:
目录名负责识别剧名
文件名只负责提取集数也就是说:
低智商犯罪(2026)用于识别剧集本身。
而:
01 4K.mp4
02 4K.mp4只会被解释为第 1 集、第 2 集,不会再拿去搜索电影。
整理后:
剧集/低智商犯罪 (2026)/Season 01/低智商犯罪 - S01E01.mp4
剧集/低智商犯罪 (2026)/Season 01/低智商犯罪 - S01E02.mp4如果无法从文件名中提取集数,整个目录会进入 _unrecognized,避免错误重命名。
文件名清洗
国内资源站的文件名经常包含大量无效信息,例如:
凶器.6v电影 地址发布页 www.6v123.net 收藏不迷路
双子杀手 4K原盘REMUX 杜比视界 国英双音 内封字幕
穿条纹睡衣的男孩.The Boy in the Striped Pajamas.2008.BluRay.1080P.H265.10bit.英语.中英特效字幕AutoReel 会先做本地清洗,去掉常见水印和技术标签:
6v电影
地址发布页
收藏不迷路
www.xxx.com
4K
REMUX
杜比视界
国英双音
内封字幕
1080P
BluRay
H265清洗后的结果更适合提交给 TMDB 查询。
例如:
双子杀手 4K原盘REMUX 杜比视界 国英双音 内封字幕会清洗为:
双子杀手年份匹配策略
年份是防止误识别的重要依据。
例如如果文件名里有:
某电影 (2019)那么 TMDB 返回的结果必须是:
2019或者允许很小的容差:
2018 / 2020如果搜索结果只有 2000 年的同名电影,就不会匹配成功。
这样可以避免“同名不同年份”的电影被错误整理。
别名机制
有些电影或剧集的中文名、英文名、民间译名并不一致。
AutoReel 支持别名表:
/config/aliases.json示例:
{
"毒液:最后·一舞": "Venom: The Last Dance",
"芭蕾杀姬": "Ballerina",
"特 工 绍 特": "Salt"
}别名表优先级高于普通搜索。
这对于 TMDB 搜不到、中文名不标准、或者文件名被严重缩写的情况很有用。
为什么取消 LLM
项目中曾经尝试加入 LLM 作为兜底识别方式,希望通过大模型推断文件名。
但实际测试后发现效果并不稳定。
原因是:
- 影视文件名高度依赖 TMDB 数据。
- 很多冷门片、译名、资源站缩写并不在 LLM 的可靠知识范围内。
- LLM 可能“猜得很像”,但并不一定准确。
- 对于自动重命名文件来说,错误识别的代价比识别失败更高。
所以最后取消了 LLM。
当前原则是:
宁可识别失败进入 _unrecognized,也不要自信地改错文件名。这也是整个项目后期优化的核心原则。
重复文件处理
如果目标文件已经存在,AutoReel 不会覆盖。
例如目标目录中已经有:
电影/乱战 (2005)/乱战 (2005).mkv新的输入目录又识别到了同一个目标路径,那么整个目录会被移动到:
source/_unrecognized/_duplicates/并写入原因文件:
目录中xxx目标文件已存在.txt这样可以人工判断:
- 是重复下载
- 是不同版本
- 是需要保留
- 还是可以删除
未识别目录的人工处理
识别失败的文件或目录会进入:
source/_unrecognized目录中会生成原因文件,例如:
目录中xxx文件未识别到.txt
目录xxx无法识别.txt人工处理方式很简单:
- 进入
_unrecognized - 修改文件名或目录名
- 把它移回输入目录
- AutoReel 会重新扫描并处理
这样保留了人工接入能力,也避免程序盲目处理。
群晖 NAS 的特殊处理
在群晖上,目录中可能会出现:
@eaDir这是 Synology 的扩展属性目录。
AutoReel 会跳过这些目录,避免把它们作为附属文件移动到媒体库中。
同时也会跳过:
.DS_Store
__MACOSXDocker 部署
项目使用 Docker 部署。
示例 docker-compose.yml:
services:
media-organizer:
build: .
container_name: AutoReel
restart: unless-stopped
environment:
WATCH_DIR: /host/emby/source
MOVIE_DIR: /host/emby/电影
TV_DIR: /host/emby/剧集
UNRECOGNIZED_DIR_NAME: _unrecognized
DUPLICATE_DIR_NAME: _duplicates
PENDING_DELETE_DIR_NAME: _pending_delete
TMDB_API_KEY: "你的 TMDB v3 API Key"
TMDB_LANG: zh-CN
FILE_ACTION: move
DRY_RUN: "false"
SCAN_ON_START: "true"
QUIET_SECONDS: "10"
MIN_FILE_SIZE_MB: "100"
LOG_LEVEL: INFO
volumes:
- /volumeUSB1/usbshare/emby:/host/emby
- ./config:/config启动:
docker compose up -d --build查看日志:
docker compose logs -f停止:
docker compose down我的目录配置
我的 NAS 目录结构是:
输入目录:
/volumeUSB1/usbshare/emby/source
电影目录:
/volumeUSB1/usbshare/emby/电影
剧集目录:
/volumeUSB1/usbshare/emby/剧集Docker 中挂载为:
volumes:
- /volumeUSB1/usbshare/emby:/host/emby容器内配置为:
WATCH_DIR: /host/emby/source
MOVIE_DIR: /host/emby/电影
TV_DIR: /host/emby/剧集Dry Run 的作用
首次运行建议开启:
DRY_RUN: "true"这时 AutoReel 只会打印计划,不会真正移动文件。
日志中会看到:
[DRY-RUN][move] source/xxx.mkv -> 电影/xxx/xxx.mkv确认识别结果没问题后,再改为:
DRY_RUN: "false"当前已知边界
AutoReel 当前仍然是一个轻量工具,不追求覆盖所有媒体管理场景。
目前已知边界包括:
- 依赖 TMDB,NAS 必须能访问
api.themoviedb.org - 冷门片、译名混乱、缩写严重时仍可能需要别名表
- 多版本电影、导演剪辑版、加长版暂时没有单独版本管理
- 原盘目录、ISO、BDMV 结构还没有完整特殊处理
- USB 移动硬盘作为输入目录时,监听机制可能影响硬盘休眠,需要结合 NAS 实测
项目原则
这个项目一路调整下来,最终形成了几个原则:
- 自动化不能以错误整理为代价。
- 文件名越混乱,越应该保守处理。
- 识别失败可以人工修正,识别错误反而更麻烦。
- 剧集目录不能用单集文件名去搜电影。
- 对 NAS 用户来说,Docker 部署和低配置门槛很重要。
- 配置尽量集中在
docker-compose.yml,不再依赖 Web 页面或额外配置文件。
总结
AutoReel 解决的是一个很小但很实际的问题:
下载目录很乱,媒体库需要干净。
它不会替代完整的媒体库系统,但可以作为下载目录到媒体库目录之间的一层自动整理工具。
目前它已经可以处理:
- 电影自动识别
- 剧集批量整理
- 文件名水印清洗
- TMDB 匹配
- 年份校验
- 别名映射
- 重复文件隔离
- 未识别文件人工接入
- Docker 部署
- 群晖特殊目录跳过
后续可以继续优化的方向:
- 更完善的电影版本识别
- 更强的原盘目录支持
- 更友好的未识别清单
- 更低唤醒的移动硬盘监听模式
- 更完善的别名维护方式