视频描述生成(抽帧)
更新时间:2026-09-14
简介
视频描述生成算子(抽帧路线):按 all_keyframes / uniform 抽帧,每帧单独过 BLIP2 生成 caption,同一候选轮次内各帧的 caption 用 ". " 拼成一条视频级 caption,生成 caption_num 条候选后按 keep_candidate_mode 归约。
功能描述
- 抽帧语义:
all_keyframes只解 I 帧(skip_frame="NONKEY");uniform在frame_num=1时取中间帧、=2时取首尾帧、>2时含首尾均匀取 max_frames上限:关键帧数超上限时再按 uniform 语义抽稀,防止长视频逐帧生成把时间和显存打满- 抽帧只用 PyAV,不走仓库里依赖 torchcodec 的解码路径(torchcodec 需要 CUDA NPP 的
libnppicc.so,镜像里缺库会导致模块 import 失败);本地路径直接交给 av,远端对象先下载到内存再解 - 候选拼接:
per_frame[i][j]是第 i 帧的第 j 条候选,按候选轮次 j 把各帧结果". "拼接,得到第 j 条视频级 caption;空串被跳过 keep_candidate_mode三种取值:random_any随机留 1 条、similar_one_simhash留与参考文本 simhash 汉明距离最近的 1 条、all全部保留similar_one_simhash的参考文本作为可选第二列reference_text传入;该列缺失或该行不是字符串时退化为random_any- simhash 用自带的 64 位实现(window_size=2 的 shingle + 汉明距离),不引入
simhash-pybindC 扩展;候选之间差异明显时选中结果稳定,极端相近的候选汉明距离容易并列,选中哪一条不保证唯一 - 行数恒定:本算子是列式算子,直接输出归约后的 caption 列表,不增删数据行、也不把 caption 回填到原文
- 输入为 None、抽不到帧、或该行生成异常时返回空列表(不是 None),异常只记日志不打断整列
- 权重只从
model_path/model_name本地目录加载,初始化时校验目录存在,不联网下载、不做运行时 pip 安装
算子参数
输入
| 输入 | 含义 |
|---|---|
| video | 视频列,内容形式由 video_src_type 决定(本地/BOS/HTTP 路径、Base64 字符串、二进制) |
| reference_text | 可选,参考文本列,仅 keep_candidate_mode="similar_one_simhash" 时使用 |
输出
| 输出 | 含义 |
|---|---|
| captions | list<large_string>,归约后的视频级 caption;random_any / similar_one_simhash 返回 1 条,all 返回 caption_num 条,失败或抽不到帧返回空列表 |
参数
| 参数名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| video_src_type | str | "video_url" | 视频输入类型:video_url(本地/BOS/HTTP 路径)、video_base64、video_binary |
| model_path | str | "/opt/aihc/model" | 权重根目录 |
| model_name | str | "Salesforce/blip2-opt-2.7b" | 相对 model_path 的 BLIP2 权重子目录 |
| dtype | str | "float16" | 权重精度:float16 / float32 / bfloat16 |
| frame_sampling_method | str | "all_keyframes" | 抽帧方式:all_keyframes(只解 I 帧)或 uniform(均匀抽 frame_num 帧) |
| frame_num | int | 3 | uniform 模式抽帧数 |
| max_frames | int | 16 | 单视频抽帧上限,超出按 uniform 语义抽稀;<=0 表示不限 |
| caption_num | int | 1 | 每个视频生成的候选 caption 条数 |
| keep_candidate_mode | str | "random_any" | 候选归约方式:random_any / similar_one_simhash / all |
| prompt | str 或 None | None | 全局提示词,非空时对每帧都带同一条提示 |
| max_new_tokens | int | 128 | 单帧生成长度上限 |
| do_sample | bool | True | 是否采样;caption_num > 1 时必须为 True 才有多样性 |
| batch_size | int | 8 | 帧推理微批大小(与 aihc_udf 的 batch_size 是两个参数) |
| rank | int | 0 | 多卡场景 worker 序号,设备取 cuda:(rank % 可见卡数) |
注意事项
- 本算子不提供帧翻转参数,也不做样本增删与原文回填:输出严格逐行对应输入。
all_keyframes下抽帧数取决于视频的 I 帧密度,逐帧生成 caption 的耗时随帧数线性增长;批量场景建议改用uniform+ 明确的frame_num。- BLIP2-OPT 权重内嵌 Meta OPT,商用前需确认许可;换 BLIP-2 Flan-T5 版可规避。
- 与「视频描述生成(整段视频)」的差别:本算子逐帧生成再拼接,不建模帧间时序;后者把整段帧序列一次喂给 Video-BLIP。
调用示例
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_captioning_from_frames import VideoCaptioningFromFrames
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
21ds = daft.from_pydict({"video": ["bos://your-bucket/sample.mp4"]})
22 ds = ds.with_column(
23 "captions",
24 aihc_udf(
25 VideoCaptioningFromFrames,
26 construct_args={
27 "video_src_type": "video_url",
28 "model_path": "/path/to/models",
29 "model_name": "Salesforce/blip2-opt-2.7b",
30 "dtype": "float16",
31 "frame_sampling_method": "uniform",
32 "frame_num": 2,
33 "caption_num": 1,
34 "keep_candidate_mode": "random_any",
35 "max_new_tokens": 24,
36 "batch_size": 2,
37 },
38 num_cpus=1,
39 num_gpus=1,
40 concurrency=1,
41 batch_size=1,
42 )(col("video")),
43 )
44 ds.show()
评价此篇文章
