Internet Archive视频采集与智能片段筛选实践
项目背景
在视频相关的科研课题中,找到数据只是第一步。真正耗时的工作通常是从长视频中定位画面清晰、动作明确、镜头连续的短片段,并把结果整理成后续实验能够直接使用的数据。
基于目前需求在AI协助下完成了下面的项目,这个项目围绕 Internet Archive 公开资源实现了一套完整处理流程:先采集动漫、动画、短剧等视频的元数据,再自动分析源视频,最终输出 2~15 秒有效片段的起止时间。程序不会批量保存最终视频片段,只保留元数据、原视频链接和时间戳,便于后续按需取用。
从技术路线来看,它不是单纯的爬虫,也不是端到端的模型训练项目,而是一个“数据采集 + 传统计算机视觉 + 本地多模态大模型”的混合系统。
整体架构
flowchart TD
A[Internet Archive 搜索 API] --> B[获取候选视频标识]
B --> C[Metadata API 获取文件与作品信息]
C --> D[清洗、分类、去重]
D --> E[导出 CSV / JSON 数据集]
E --> F[按需下载源视频]
F --> G[FFprobe 探测媒体信息]
G --> H[PySceneDetect 检测镜头边界]
H --> I[OpenCV + NumPy 规则粗筛]
I --> J[Qwen3-VL 多模态模型复核]
J --> K[dHash 相似片段去重]
K --> L[输出时间戳、复核表与统计结果]
整条管线分为两个相对独立的阶段:
- 元数据采集:得到结构化的视频数据集和可访问的原视频链接。
- 片段筛选:对视频进行镜头切分、画质分析和语义判断,输出符合条件的片段时间范围。
使用到的技术
| 技术 | 在项目中的作用 |
|---|---|
| Python 3.12 | 编写采集、分析、筛选和导出逻辑 |
| Internet Archive API | 搜索视频并获取作品元数据、文件列表和下载地址 |
urllib | 发起 HTTP 请求、下载视频和调用 Ollama 接口 |
ThreadPoolExecutor | 并发获取多个视频的元数据 |
| FFprobe | 检查视频流、编码、分辨率、帧率和时长 |
| PySceneDetect | 使用自适应算法检测镜头切换位置 |
| OpenCV | 视频解码、定点抽帧、图像缩放和视觉指标计算 |
| NumPy | 完成均值、中位数、标准差和帧间差分计算 |
| Qwen3-VL 4B | 判断片段是否具有连续场景、清晰主体和有效动作 |
| Ollama | 在本地部署和调用视觉模型 |
| dHash | 生成感知哈希,去除内容相似的候选片段 |
| CSV / JSON / JSONL | 保存数据集、结果、统计信息和断点状态 |
| PowerShell + venv | 完成 Windows 环境初始化和运行封装 |
unittest | 验证分类、切片、时间码、去重和导出逻辑 |
第一阶段:采集 Internet Archive 元数据
使用官方 API,而不是解析网页
项目使用 Internet Archive 的 Advanced Search API 搜索候选资源,再通过 Metadata API 获取每个条目的完整信息。检索条件主要围绕以下字段构造:
mediatype:限制为电影或视频资源;subject:匹配 anime、animation、short film、short drama 等主题;title和description:补充召回标题或简介中包含相关词汇的资源;language:优先查找中文相关记录。
相比直接抓取网页,官方 JSON API 的字段更稳定,也更适合科研数据的批量处理。
数据清洗与标准化
Internet Archive 中同一个条目通常包含原始文件、转码文件、缩略图、字幕等多种文件。项目会从文件列表中选择 source=original 的视频;如果存在多个原视频,则优先保留体积最大的一个。
采集结果统一为 21 个字段,主要包括:
- 标题、作者、语言和描述;
- 原视频链接和作品详情页链接;
- 时长、分辨率、帧率、格式和文件大小;
- 字幕链接、许可证地址和许可证状态;
- 数据分类、集数信息、唯一标识和采集时间。
描述中的 HTML 标签会被清理;视频与字幕文件名会进行 URL 编码;中文“第十二集”和英文 S01E12、Episode 12 等形式会被正则表达式转换为统一的集数标识。
并发、重试与断点续跑
元数据接口属于网络 I/O,因此项目使用线程池并发请求,提高采集速度。面对 HTTP 429、500、502、503、504 或网络超时,会采用指数退避策略重试。
每获得一条有效记录,程序都会立即追加到 JSONL 检查点,并执行 flush + fsync 强制落盘。即使采集中途关闭,下一次运行也能跳过已经完成的记录。最终 CSV 和 JSON 通过临时文件原子替换生成,避免异常中断留下不完整文件。
第二阶段:寻找有效视频片段
FFprobe 探测视频
Internet Archive 中的视频格式并不统一,可能是 MPEG4、WebM、Matroska、QuickTime 或较早的 MPEG1、MPEG2。视频下载后,程序先调用 FFprobe 检查:
- 是否存在可用的视频流;
- 视频编码、宽高和平均帧率;
- 容器中记录的真实时长。
这一步可以提前排除损坏文件,也为后面的镜头切分提供可靠的媒体信息。
PySceneDetect 划分连续镜头
项目使用 PySceneDetect 的 AdaptiveDetector 检测镜头边界。自适应检测会根据相邻帧的变化寻找转场,相比固定阈值,更能适应亮度和运动差异较大的动画、真人视频。
检测出的镜头会进一步转换为候选片段:
- 少于 2 秒的镜头直接舍弃;
- 2~15 秒的镜头直接成为候选;
- 超过 15 秒的长镜头切成接近 6 秒的小段。
这样既满足最终片段的时长约束,也避免把整段长镜头直接交给模型处理。
OpenCV 与 NumPy 规则粗筛
如果每个候选都调用视觉模型,速度和显存占用都会很高。因此程序先从每个片段等间隔抽取 6 帧,再计算几项成本较低的视觉指标:
| 指标 | 计算方式 | 目的 |
|---|---|---|
| 亮度 | 灰度图均值 | 排除严重过暗的画面 |
| 清晰度 | 拉普拉斯方差 | 排除明显模糊的画面 |
| 信息量 | 灰度标准差 | 排除纯色、片头或信息过少的画面 |
| 运动量 | 相邻采样帧绝对差均值 | 排除接近静止的画面 |
| 时长奖励 | 与 6 秒目标时长的距离 | 优先选择长度适中的片段 |
规则分数满分为 100 分,其中亮度和清晰度各占 25 分,运动量占 20 分,信息量和时长各占 15 分。严重过暗、模糊、近似纯色或静态的候选会在这一阶段被直接拒绝。
快速版本还会把整段视频按时间划分为若干区域,从每个区域选择最接近 6 秒的候选,默认最多分析 60 个。这样既限制计算量,也能避免候选只集中在视频开头。
Qwen3-VL 语义复核
通过规则筛选后,得分最高的少量候选会进入多模态模型。项目使用 Ollama 在本机运行 qwen3-vl:4b,不调用收费云端 API,也不需要把视频数据上传到第三方服务。
程序把 6 张采样帧压缩为 JPEG 并转成 Base64,通过 Ollama 的 /api/chat 接口提交。提示词要求模型判断:
- 人物或主要场景在时间上是否连续;
- 是否存在快速混剪、闪回或明显转场;
- 主体、动作和画面是否清楚;
- 是否为静态图、纯文字或大面积遮挡;
- 是否包含对话、走动、转身、开门、取物、打斗等明确动作。
模型必须返回固定 JSON 结构:
1 | { |
只有模型明确接受、评分不低于 70 且置信度不低于 0.65 的候选,才会进入最终结果。低置信度或字段相互矛盾的结果不会静默丢弃,而是写入人工复核表。
使用 dHash 去除重复片段
同一视频中经常存在片头重复、静止特写或高度相似的镜头。程序分别计算候选片段首帧、中间帧和尾帧的 dHash,再通过汉明距离比较视觉签名。
相似度过高的片段只保留模型评分更高的一条。快速版本还会在全部视频结果之间进行一次全局去重,降低最终数据集中的视觉重复率。
最终实现效果
元数据采集结果
当前项目已经生成 200 条有效视频元数据:
| 数据分类 | 数量 |
|---|---|
动画 animation | 104 |
动漫 anime | 92 |
短剧 short_drama | 4 |
| 合计 | 200 |
文件格式覆盖 MPEG4、Matroska、QuickTime、MPEG1、MPEG2 和 WebM,其中 MPEG4 数量最多。每条数据都包含原视频直链,并尽可能保留时长、分辨率、帧率、字幕和许可证信息。
六种格式抽样实验
项目对六种视频格式各抽取一条进行验证,实验结果如下:
| 指标 | 结果 |
|---|---|
| 处理视频 | 6 条 |
| 成功选出片段的视频 | 5 条 |
| 最终片段 | 10 条 |
| 需要人工复核的候选 | 7 条 |
| 未得到有效片段的视频 | 1 条 |
六条视频总时长约 78 分钟,单条视频的镜头数从 7 个到 482 个不等。传统规则先过滤大量低质量候选,再由模型复核排名靠前的片段,证明这套分层策略能够处理不同编码、时长和内容类型的视频。
第一次抽样中,QuickTime 视频没有通过严格筛选。切换到快速管线,将 252 个候选按时间覆盖缩减为 60 个规则候选,并把模型复核数量调整为 5 个后,最终成功得到 1 条有效片段,处理耗时约 167 秒。
最终输出
系统会生成以下结果:
selected_clips.csv:最终通过筛选的片段及起止时间;review_required.csv:低置信度候选,供人工确认;failed_videos.csv:下载、解码失败或没有有效片段的视频;checkpoint.jsonl:视频级断点续跑状态;summary.json:镜头数、候选数、模型调用数、耗时等统计。
时间戳统一为 HH:MM:SS.mmm 格式。例如:
1 | episode_or_part,start_time,end_time,duration |
CSV 使用 UTF-8 BOM 编码,可以直接用 Excel 打开。程序处理完一条视频后会删除缓存中的源文件,因此磁盘空间不会随着全量任务持续增长。
工程化设计
为了让长时间运行的科研任务更稳定,项目还实现了几项工程能力:
- 视频下载支持 HTTP Range 断点续传和指数退避重试;
- 采集阶段和筛选阶段都有独立的 JSONL 检查点;
- 每完成一个视频就重新导出结果,降低中断造成的数据损失;
- 支持按格式过滤和“每种格式一条”的小样本验证;
- 支持限制规则候选、模型候选和最终片段数量;
- 提供 Windows PowerShell 初始化与运行脚本;
- 使用本地 Ollama 模型,便于控制成本和数据流向。
项目现有 29 个单元测试,覆盖元数据分类、集数解析、原视频选择、字幕过滤、片段切分、时间码转换、感知哈希距离、检查点和原子导出等逻辑,当前测试全部通过。
当前局限与后续方向
目前已经验证的是系统的可运行性和跨格式处理能力,还不能把抽样结果直接解释为算法精度。要形成更完整的科研结论,后续仍需要:
- 建立人工标注的测试集,计算 Precision、Recall、F1、漏选率和误选率。
- 对比纯规则、纯视觉模型和混合管线,完成消融实验。
- 分析亮度、模糊度、运动量以及模型阈值对结果的影响。
- 固定模型版本、硬件环境和运行参数,保证实验可复现。
- 引入音频、字幕或更密集的时序特征,弥补稀疏抽帧可能遗漏瞬时转场的问题。
- 增加真实网络、视频解码和 Ollama 服务的集成测试。
总结
这个项目把一个宽泛的“从网络视频中寻找有效素材”问题拆成了多个成本逐渐增加的步骤:官方 API 负责获得数据,PySceneDetect 负责找边界,OpenCV 和 NumPy 负责低成本排除明显无效片段,Qwen3-VL 负责语义层面的严格判断,最后通过感知哈希和人工复核保证结果质量。
这种混合方案的关键不在于堆叠模型,而在于让不同技术处理自己最擅长的问题。规则算法便宜、稳定、可解释,大模型擅长复杂语义判断,两者结合后,既控制了推理成本,也让整个过程更容易调试和复现。
