Skip to main content
Glama

Local Media Manager

本地媒体库索引与整理工具:扫描视频文件 → 识别番号 → 落库 → 查询 / 质检 / 整理。

面向「文件名里带番号」的本地媒体库(数万文件量级)。

目的

存储疯涨的年代,本地囤积已经不是最优解。

一部片几 GB 到几十 GB,攒到几千部就是几 TB 硬盘。 但这些内容里真正稀缺的不是文件本身,而是「这是哪一部片」这个信息 —— 文件在网上随时能重新拿到,编号和磁力却得自己攒。

所以这个工具做的事是:硬盘里只留截图、封面和磁力链接,删掉源文件。 让互联网上的分享代替本地囤积,把几 TB 压回几百 MB。

为什么可行 —— 磁力链接是内容的内容寻址引用,只要还有人在做种就一直有效。 留住它,就等于留住了「随时重新取回这部片」的能力,而不必一直占着硬盘。

于是核心成为保卡:卡 = 编号 + 元数据 + 截图封面 + 磁力。 删源文件只是磁盘管理,卡片始终保留。

实测比例约 1 : 2300 —— 918 GB 的源文件,对应的卡片资料(封面 + 截图)合计 400 MB。

Related MCP server: plex-claude-plugin

特点

① 自定义扫描目录,抓出番号

目录范围完全自己定,还能按盘分档 —— 整盘扫 / 只扫指定目录 / 跳过。 (慢盘、病盘尤其需要「只扫已知目录」,不必为了几个文件全文遍历。)

识别从文件名解析编号,文件名认不出时回退到父目录名。 结果是结构化的编号,不是一堆文件名。

② 在线匹配 JavDB

编号拿去 JavDB 匹配元数据:标题、发行日期、时长、演员、标签、评分。 匹配不上的不入库 —— 宁可缺,不可混入错的数据。

③ 抓封面、截图、评论

每个编号抓回来的素材:封面、内容截图、评论文本, 都存本地,离线也能看。评论数还参与置信分。

④ 存磁力链接

抓取并落库该编号的磁力(含中字 / 高清 / 体积标记), 可一键导出成文本档留底 —— 磁力本身只是 hash,丢了得重找。

⑤ 一键清理本地资源

对高置信度的条目(档位 ≥ 高 + 番号核对通过 + 有已验证磁力 + 文件格式典型),一键把本地源文件送进回收站,腾出空间 (需清空回收站才真正释放 —— 程序不代清)。

四个约束:

  • 走回收站,不是永久删除 —— 随时可恢复

  • 只在能进回收站的地方删 —— 动手前查一次目标位置:不是本地内置盘 (移动盘 / U 盘 / 网络盘),或文件系统不是 NTFS / ReFS(exFAT、FAT32 没有回收站),一律拒绝删除。移动盘通常是备份盘,在上面省空间本身 就没意义。判据是运行时查出来的,不依赖配置里写了什么

  • 卡片不删 —— 删的只是源文件,编号 / 元数据 / 截图 / 磁力全部保留

  • 没磁力不许删 —— 拿不回来的东西不给删;判定没跑过的也一律不可删

(宁可漏删,不可错删。逐条手动删的门槛更低,但同样受磁力门控。)

⑥ 还有

格式白名单、增量扫描(跳过未变更文件)、质检(缺元数据 / 缺封面 / 重复)、 Web UI + MCP 工具层(供 Agent 客户端调用)。

实现

分层

core/       解析、扫描、匹配、落库、置信分
services/   扫描 / 抓取 / 文件管理 / 备份
web/        FastAPI + Jinja2(页面与 REST)
adapters/   数据源适配(JavDB / JavBus)

存储 —— SQLite 三个库分工:主库(编号 / 文件 / 元数据 / 磁力 / 评论)、 扫描索引(增量用)、v1 旧库(只读迁移源)。

两条硬规矩

  1. 编号目录不参与匹配(除一层回退)—— 目录名比文件名更容易误匹配

  2. 没有磁力就不许删 —— 删了就找不回来的东西,不该由工具替人决定

零外部程序依赖 —— 时长探测与元数据抓取都是纯 Python 实现, 不需要 ffmpeg,也不需要额外的 CLI 或常驻服务。

前端 —— 首屏只渲染一页卡片,其余随滚动按需追加。 几百上千张一次性渲染会明显卡顿。

引用的项目

元数据来自 JavDB 与 JavBus。两者的接口契约参考了下面两个 MIT 项目, 按其契约用 Python 重实现(未复制其代码):

项目

许可

参考了什么

javdb-cli

MIT

JavDB App API 的端点、参数与签名算法

javbus-api

MIT

JavBus 的页面结构、端点与请求头

⚠️ javdb-cli 的签名常量系其从 JavDB 官方 APK 逆向所得。本项目按 MIT 条款复用其接口契约;该协议随时可能被上游改动而失效。

时长探测不需要 ffmpeg:自写的容器头解析覆盖 mp4 / mkv / avi / wmv 四种容器, 与 ffprobe 在真实语料上实测最大相对差 0.0034%(判定阈值是 10%)。

Install

pip install -r requirements.txt

配置

编辑 config.yaml:

scan_paths:
  - "X:\\"                   # 扫描根目录(可多个)

video_extensions: []         # 追加格式(**追加**语义)
excluded_dir_segments: []    # 追加排除目录(**追加**语义)
database: "storage/library_v2.db"
index_db: "storage/file_index_v2.db"
dictionary: "data/dictionary.json"

video_extensions 与 excluded_dir_segments 都是往上加,不是替换。 选追加而不是覆盖,是因为覆盖语义下少写一项会静默漏扫整类文件;追加最坏只是多扫。

Web UI 里还能改数据源后端与代理(/settings)—— 代理地址由使用者自己填,程序不预设任何端口。

运行

# 命令行扫描
python main.py "你的目录"

# Web UI
python -m uvicorn web.app:app --host 127.0.0.1 --port 8811

开发

pytest tests/ -q

测试结果按有没有本地语料分两种(语料是私有的,不在仓库里):

环境

结果

无本地语料(干净克隆,默认)

846 passed, 8 skipped

有本地语料(开发机)

854 passed

跳过的那 8 条依赖真实的媒体库/校验缓存,靠 pytest.mark.skipif 自动跳过; 要用自己的语料跑,用环境变量指过去:

LMM_REAL_DB=/path/to/library_v2.db \
LMM_LEGACY_LIBRARY_DB=/path/to/library.db \
LMM_VERIFY_CACHE=/path/to/verify_cache.json \
pytest tests/ -q

已知缺口

  • 扫描缓存未接线,重复扫描会重算(大库性能受影响)

  • 定时扫描、目录监听未接线,不随服务启动

  • 暂无「重命名计划(只出计划不执行)」与「按演员/标签检索」

  • 宣传视频的 HLS 录制依赖外部工具(其余功能不需要)

License

MIT

友链

本开源项目已链接并认可 LINUX DO 社区。

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables Plex Media Server administration including library management, media file identification and renaming, batch processing, and automatic ingestion with folder watching.
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides tools for AI clients to scan, match, and scrape TMDB metadata for local media files, with safe sidecar writing or full Jellyfin-style reorganization including file renaming and NFO generation.
    MIT
  • A
    license
    B
    quality
    D
    maintenance
    Enables agents to organize messy folders into structured libraries by scanning, planning, and applying reorganization via a manifest-first, non-destructive workflow.
    16
    6 npm
    1
    MIT