Memoria 开发记录 19:让视频进入语义搜索——抽帧、去重与代表向量
前言
图片语义搜索相对直接:读取一张图片,生成一个向量,然后与文本向量比较。视频却是一段随时间变化的内容。如果只使用封面,可能完全错过后半段的重要场景;如果对每一帧生成向量,计算和存储成本又无法接受。
Memoria 对视频语义能力做过 MobileViCLIP 模型迁移和导出实验,随后逐步收敛到有限抽帧、帧去重和聚合 embedding。这个过程说明,视频搜索的关键不是“给视频算一个向量”,而是决定哪些时间片段能够代表整段内容。
为什么封面向量不够
视频封面通常来自第一帧或系统生成的缩略图。第一帧可能是黑屏、过场、拍摄者移动手机,无法代表主要内容。例如一段烟花视频的第一秒可能只有夜空,真正有意义的内容在后面。
所以视频至少需要时间采样:
视频时间轴-> 选取若干采样点-> 提取帧-> 生成帧向量-> 去重和聚合-> 得到媒体代表向量
采样点可以均匀分布,也可以结合镜头变化。移动端第一阶段通常优先选择有限均匀抽帧,因为成本可预测。
MobileViCLIP 的迁移与导出实验
提交 2f32851 引入 MobileViCLIP 模型迁移、导出工具、元数据和 Benchmark。视频模型理论上能理解时序关系,比独立图片帧更接近视频语义。
但端侧部署不仅取决于模型效果,还取决于:
- 模型文件体积;
- 算子能否被目标运行时支持;
- 多帧输入的内存峰值;
- 导出后结果是否与参考实现一致;
- 中端手机上的处理时间。
后续提交 fd21f44 和 a384cbe 多次修正导出工具,说明模型“成功导出”并不等于“正确导出”。输入排列、动态维度、归一化和输出头任何一项不一致,都会得到能运行但语义错误的模型。
抽帧后的重复问题
大量视频在几秒内画面变化很小。若固定抽取 12 帧,可能得到 10 张几乎相同的图片。直接平均这些向量,会让静止片段过度主导结果,也浪费推理时间和索引空间。
提交 15218d4 新增 MobileCLIP2 语义索引服务,并支持视频帧去重。基本思路是比较帧向量相似度:
新帧与已保留代表帧高度相似 -> 丢弃
新帧带来明显语义变化 -> 保留
这样保留下来的不是固定数量时间点,而是一组具有信息差异的代表画面。
一个视频应该保存一个还是多个向量
单向量便于与图片统一搜索,但会压缩掉视频内部的多场景信息;多向量召回更准确,却会增加索引规模,并让一个视频可能重复出现在结果中。
可采用两层设计:
- 媒体级聚合向量:用于快速初筛和统一排序;
- 代表帧向量:用于精细匹配和解释命中原因。
搜索“海边烟花”时,媒体级向量帮助快速找到相关视频,代表帧则可以说明命中了烟花片段,而不是只展示无关封面。
持久化 embedding 元数据
视频向量必须记录它是如何生成的,例如:
模型版本
采样帧来源
实际帧数
时间戳
是否检测到重复帧
聚合方法
没有这些元数据,就无法判断旧索引是否需要重建,也无法解释某段视频为什么搜索不到。当前实现已经开始把媒体 embedding 记录与向量一起持久化,这是后续调优的重要基础。
总结
让视频进入语义搜索,是一次从静态内容理解走向时间媒体理解的扩展。
关键经验包括:
- 视频封面不能稳定代表完整内容;
- 端侧视频模型必须验证导出正确性和资源成本;
- 有限抽帧需要配合语义去重;
- 媒体级向量和代表帧向量可以分层使用;
- embedding 必须保存采样和模型元数据;
- 当前抽帧方案适合内容召回,但不能宣称理解完整叙事和音频。
对应提交:2f32851、78f8229、fd21f44、a384cbe、15218d4。
