文章

一张截图,反查它是哪部作品的哪一帧

一张截图,反查它是哪部作品的哪一帧

它解决什么

手里只有一张视频截图,想知道出自哪部作品、对应哪个时间点。

人工去搜基本靠猜。这个工具把截图丢给一个识图接口,拿回候选作品编号、相似度和命中帧的时间码。

1
python scripts/avscan.py search 截图.jpg

输出是这样的:

1
2
3
1. XXXXX-001  89.93%  @ 00:21:56 / 00:22:20 / 00:21:53 / 00:21:48
2. XXXXX-002  89.85%  @ 00:26:27 / 00:26:30
3. XXXXX-003  89.54%  @ 00:44:43 / 00:45:29

相似度、多个命中帧的时间点一次给全。

接口是什么样

核心就一个 multipart 上传:

1
2
3
POST https://www.avscan.cc/search
Content-Type: multipart/form-data
表单字段: file=<图片>   (image/*, ≤8MB)

返回 JSON,结构简单到不需要文档:

1
2
3
4
5
6
7
8
9
{
  "results": [
    {
      "video_code": "XXXXX-001",
      "best_similarity": 89.93,
      "frames": [{ "image_name": "XXXXX-001_00-21-56.jpg", "similarity": 89.93 }]
    }
  ]
}

两个细节值得说:

  • 没有分页。limit、top_k、page、offset 传了也被忽略,服务端固定返回最多 20 条,按相似度降序。
  • 时间码藏在文件名里。XXXXX-001_00-21-56.jpg 这一段就是命中帧的时间点,HH-MM-SS 格式,解析一下就有了。

缩略图也是拼 URL 拼出来的:

1
https://avscan.cc/thumb/{番号}/{帧名去掉扩展名}.webp

400×224 的 WEBP,CDN 缓存一年。

CLI 的几个设计选择

只用标准库

urllib 手搓 multipart 请求,不依赖 requests。代价是代码长一点,好处是任何装了 Python 的机器直接能跑——不用先建虚拟环境装依赖。

1
2
3
4
5
6
7
8
# 关键就是自己拼 boundary
body = b"".join([
    f"--{boundary}\r\n".encode(),
    f'Content-Disposition: form-data; name="file"; filename="{name}"\r\n'.encode(),
    b"Content-Type: image/jpeg\r\n\r\n",
    data,
    f"\r\n--{boundary}--\r\n".encode(),
])

双输出格式

默认给人看表格,--json 给程序看:

1
2
python scripts/avscan.py search 截图.jpg          # 表格
python scripts/avscan.py search 截图.jpg --json   # 原始 JSON

这个设计是为 Agent 准备的——--json 的输出可以直接被解析,不用再写正则去啃表格。

批量与缩略图

1
2
3
4
5
# 批量识别,导出 CSV
python scripts/avscan.py batch 图1.jpg 图2.jpg -o results.csv

# 下载全部命中帧的缩略图
python scripts/avscan.py thumbs 截图.jpg -o ./thumbs --skip-placeholder

--skip-placeholder 会过滤掉灰色占位图。这个功能需要 Pillow,属于可选依赖——不用就不装。

批量模式下加了间隔,因为接口会限流:429 出现就退避一下,否则整批都会失败。

作为 Agent Skill 用

仓库里除了 README 还有一份 SKILL.md,遵循 agentskills.io 的格式。丢进任何支持该标准的 agent 的技能目录,它就知道:

  • 用户给本地图片 → 直接调 CLI
  • 用户给图片 URL → 先下载到临时文件再调
  • 拿到 JSON → 按番号分组,缩略图用 Markdown 内联渲染

最后一条容易被忽略:让 Agent 输出图片,而不是输出图片地址。地址是给程序用的,人是看图的。

怎么提高命中率

实测下来有效的几条:

先裁剪到特征区域。 整张 1080p 截图里可能一半是黑边或字幕,裁到主体部分命中率明显更高。同理,有水印的先去掉。

相似度分档看。 85 以上基本可信,70 到 85 需要人工确认,70 以下当参考。全部只给一个最高分是不够的,因为服务端返回的是排序结果,前几名往往差不到 1 个百分点。

纯色图会虚高。 一张没有特征的黑屏或单色画面,也可能拿到很高的相似度——因为算法在低信息量下容易给高分。这种情况必须结合排序和常识判断。

同一张图会命中服务端缓存。 秒回且结果完全一致,批量测试时别误以为是本地缓存。

用之前

依赖只有 Python 3.8+,没有第三方库:

1
2
3
git clone https://github.com/poisonhs/avscan-frame-search.git
cd avscan-frame-search
python3 scripts/avscan.py stats        # 先跑个不需要图片的命令验证网络

stats 会返回站点当天的检索量、收录帧数和热搜,可以用来确认接口通不通。

说明

这个工具的用途是成人内容的元数据检索,结果会涉及相关作品编号。请遵守所在地法律法规,只在合法范围内使用。

仓库:poisonhs/avscan-frame-search

本文由作者按照 CC BY 4.0 进行授权