视频帧图文相似度
更新时间:2026-09-14
简介
视频帧与文本的相似度算子:视频抽帧过 CLIP 图像塔、文本过 CLIP 文本塔,逐帧算余弦相似度后按 reduce_mode 聚合。CLIP 编码复用 multimodal/_clip_dual_tower.py,与 ClipSimilarityScore 同一份实现。
功能描述
- 双输入列:视频列 + 文本列,两列必须等长,不等长直接抛
ValueError - 文本按整列一次性编码(跳过 None 与空白串),帧按
batch_size微批过图像塔,避免逐帧 batch=1 的吞吐损失 - 图像与文本向量都做 L2 归一化后点积,即标准余弦相似度,取值 [-1,1]
- 抽帧内置
VideoFrameSampler,默认by_count_uniform+count_k=3;sample_mode与时间窗、间隔、时间戳、max_frames参数全部透传 - 抽帧默认走均匀抽取而不是解全部关键帧,帧数可控、代价可预期
VideoFrameSampler输出 BGR 帧,算子内部转 RGB 后再交给CLIPProcessor- 文本编码失败(整列)或该行文本为空时不做图像编码,该行直接返回 None
- 聚合支持
avg/max/min,结果保留 6 位小数;某个微批推理异常只丢这批帧并打日志 - CPU 上强制把
float16回退成float32(CPU 的 fp16 矩阵乘支持不完整) - 权重只从
model_path/model_name本地目录加载,初始化时校验目录存在,不联网下载
算子参数
输入
| 输入 | 含义 |
|---|---|
| videos | 视频列,内容形式由 video_src_type 决定(本地/BOS/HTTP 路径、Base64 字符串、二进制) |
| texts | 文本列,与视频列逐行对应;None 或空白串该行输出 None |
输出
| 输出 | 含义 |
|---|---|
| frames_text_sim | float64,逐帧图文余弦相似度按 reduce_mode 聚合后的结果,取值 [-1,1];抽不到帧、文本为空或推理失败返回 None |
参数
| 参数名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| video_src_type | str | "video_url" | 视频输入类型:video_url(本地/BOS/HTTP 路径)、video_base64、video_binary |
| model_path | str | "/opt/aihc/model" | 权重根目录 |
| model_name | str | "openai/clip-vit-base-patch32" | 相对 model_path 的 CLIP 权重子目录 |
| dtype | str | "float32" | 权重精度:float16 / float32 / bfloat16;CPU 上 float16 自动回退 float32 |
| sample_mode | str | "by_count_uniform" | 抽帧模式,透传 VideoFrameSampler:by_count_uniform / by_interval_time / by_interval_frames / by_fps / by_timestamps |
| start_time_sec | float | 0.0 | 抽帧起始秒 |
| end_time_sec | float 或 None | None | 抽帧结束秒,None 表示到视频末尾 |
| count_k | int 或 None | 3 | by_count_uniform 模式的抽帧数 |
| interval_sec | float 或 None | None | by_interval_time 模式的间隔秒 |
| interval_frames | int 或 None | None | by_interval_frames 模式的间隔帧 |
| target_fps | float 或 None | None | by_fps 模式的目标帧率 |
| timestamps_sec | list[float] 或 None | None | by_timestamps 模式的时间戳列表(秒) |
| max_frames | int 或 None | None | 抽帧数上限,None 不限 |
| reduce_mode | str | "avg" | 帧相似度聚合方式:avg / max / min |
| video_format | str | "mp4" | video_binary / video_base64 输入时的容器格式 |
| batch_size | int | 16 | 图像塔推理微批大小(与 aihc_udf 的 batch_size 是两个参数) |
| rank | int | 0 | 多卡场景 worker 序号,设备取 cuda:(rank % 可见卡数) |
注意事项
- CLIP 文本塔上限 77 token,更长的文本会被截断。
- 本算子不提供
horizontal_flip/vertical_flip帧翻转参数。 - 本算子只出分、不带阈值过滤,过滤在 daft 侧用
where()做。 - 一次
transform会先把该批次所有视频抽出的帧全部转成 PIL 图像再分批推理,峰值内存约等于 UDFbatch_size× 单视频抽帧数 × 帧尺寸。
调用示例
Python
1from __future__ import annotations
2
3import os
4
5import daft
6from daft import col
7
8from daft.aihc.common.udf import aihc_udf
9from daft.aihc.functions.video.video_frames_text_similarity import VideoFramesTextSimilarity
10
11os.environ.setdefault("BOS_ENDPOINT", "http://bj.bcebos.com")
12os.environ.setdefault("BOS_REGION", "bj")
13
14if __name__ == "__main__":
15 if os.getenv("DAFT_RUNNER", "native") == "ray":
16 import ray
17 ray.init(dashboard_host="0.0.0.0", ignore_reinit_error=True)
18 daft.set_runner_ray()
19 daft.set_execution_config(actor_udf_ready_timeout=6000, min_cpu_per_task=0)
20
21samples = {
22 "video": ["bos://your-bucket/sample.mp4"],
23 "text": ["a video clip"],
24 }
25 ds = daft.from_pydict(samples)
26 ds = ds.with_column(
27 "frames_text_sim",
28 aihc_udf(
29 VideoFramesTextSimilarity,
30 construct_args={
31 "video_src_type": "video_url",
32 "model_path": "/path/to/models",
33 "model_name": "openai/clip-vit-base-patch32",
34 "sample_mode": "by_count_uniform",
35 "count_k": 3,
36 "reduce_mode": "avg",
37 "batch_size": 16,
38 },
39 num_cpus=1,
40 num_gpus=1,
41 concurrency=1,
42 batch_size=1,
43 )(col("video"), col("text")),
44 )
45 ds.show()
评价此篇文章
