120-视频理解-大模型视频分析-抽帧-自动字幕摘要-高光片段
文章目录
【120.Python+AI】视频理解:用大模型分析视频内容,自动生成字幕、摘要和高光片段
📖 文章简介: 本文系统讲解用大模型实现视频理解的完整方案,让一个小时的视频在几分钟内变成字幕、摘要和高光清单。文章从"视频是信息密度最高却最难消费的内容形态"切入——没人愿意拖完一小时录像找三句话,而纯人工剪辑摘要的成本高到无法规模化;随后拆解视频理解的三段式技术路线:抽帧(按场景切换+固定间隔的混合抽帧策略,1小时视频压到300帧的成本控制)、帧理解与帧间关联(多模态模型逐帧描述、时间轴拼接、去重合并同类帧描述,避免"每秒都在说废话")、内容产出(自动字幕生成:Whisper音轨转写与画面描述对齐;视频摘要:帧描述+字幕文本喂LLM生成章节式摘要;高光片段定位:让LLM从时间轴中选出信息密度最高的片段并输出起止时间戳,ffmpeg无损剪切);给出视频RAG的进阶方案(帧描述+字幕双通道入库,按时间戳召回原片定位)。附关键Python代码与1小时视频的处理成本实测,配以Mermaid流程图展示从视频文件到结构化产出的完整流水线,适合有视频内容处理需求的开发者阅读参考。

🎬 个人主页: 源码骑士
❄ 专栏传送门: 《Android开发基础》《python基础课程》
⭐️热衷从源码视角拆解技术底层原理,将复杂架构讲得通俗易懂
🎬 源码骑士的简介:
5年Android Framework系统开发经验,曾主导多项系统级性能优化专项
技术栈覆盖Android系统全链路(Binder/Handler/AMS/WMS/启动流程)及Java后端全家桶(Spring + MyBatis + Redis + Oracle)
累计产出原创技术文章100+篇,文章以流程图为特色,被读者评价为"看一篇胜过啃一周源码"
导入语
公司年度大会的录像、两小时的线上培训、客户发来的产品演示视频……视频是这个时代信息密度最高的内容形态,也是消费成本最高的形态——文字可以扫读、音频可以倍速,视频想了解内容只能拖进度条碰运气。
需求就藏在这份痛苦里:把一小时视频变成字幕(可搜索)、摘要(可速览)、高光片段(可转发)——三件事做掉,视频就从"黑盒文件"变成"可检索、可消费的知识"。
以前这需要剪辑师花半天;现在,多模态大模型+Whisper的组合可以全自动完成。这篇文章拆解完整流水线:怎么抽帧最省、怎么让模型看懂画面、怎么把时间轴变成结构化产出。
1 ~> 总体思路:视频降维成"带时间戳的图文"
核心思想一句话:视频本身不进模型,把视频降维成"带时间戳的图文序列"再进模型。 画面走抽帧+视觉理解,声音走Whisper转写——两路信息都带时间戳,在时间轴上对齐后,一小时视频就变成了模型能读的一页纸。
2 ~> 第一步:抽帧——成本控制的关键
2.1 抽多少帧才够
抽帧密度的成本账(1小时视频):
每秒1帧 = 3600帧 → 视觉API调用3600次,又贵又慢
混合策略 ≈ 300帧 → 成本降92%,信息保留95%+
混合抽帧策略:
基础帧:固定每10秒一帧(保底覆盖)→ 360帧减档
关键帧:场景切换处必抽(内容突变点)→ ffmpeg检测
合并去重后 ≈ 300帧上下
2.2 抽帧代码
import subprocess
def extract_frames(video_path: str, out_dir: str = "frames"):
# 场景切换帧(内容突变点,信息密度最高)
subprocess.run([
"ffmpeg", "-i", video_path,
"-vf", "select='gt(scene,0.35)',showinfo", # 场景变化阈值
"-vsync", "vfr", f"{out_dir}/scene_%04d.jpg",
], check=True)
# 固定间隔帧(保底覆盖,防长镜头漏采)
subprocess.run([
"ffmpeg", "-i", video_path,
"-vf", "fps=1/10", # 每10秒1帧
f"{out_dir}/interval_%04d.jpg",
], check=True)
帧文件名映射回时间戳(ffmpeg的showinfo输出里有精确的pts_time),每一帧都必须带着它的时间戳出生——后面所有产出物的"定位回原片"全靠它。
3 ~> 第二步:帧理解与帧间关联
3.1 逐帧描述:带着上下文问
直接让模型逐帧独立描述,会得到一堆重复废话(连续300帧里290帧画面几乎没变)。正确姿势是带着上一帧的描述问:
def describe_frames(frame_list: list[tuple[float, str]]):
"""frame_list: [(时间戳, 帧路径)],按时间排序"""
timeline = []
prev_desc = ""
for ts, path in frame_list:
prompt = "描述这一帧画面的关键内容(主体、动作、屏幕文字)。"
if prev_desc:
prompt += (f"上一帧内容:{prev_desc}\n"
f"若与上一帧基本相同,只回答'同前';"
f"有变化则只描述新增/变化的部分。")
desc = ask_vision(encode_image_smart(path), prompt) # 第116篇
if desc != "同前":
timeline.append({"time": ts, "desc": desc})
prev_desc = desc
return timeline
"同前"机制一举两得:成本骤降(重复帧几乎不消耗生成token)、时间轴自动瘦身(留下的都是内容变化点,即"帧间关联"的骨架)。300帧描述完,时间轴上通常只剩30~50个变化节点。
3.2 与字幕时间轴对齐
# Whisper转写自带时间戳(第119篇的faster-whisper)
segments, _ = whisper_model.transcribe("audio.wav", language="zh")
subtitle_events = [{"time": s.start, "text": s.text} for s in segments]
# 两路按时间戳合并排序 = 完整的视频理解时间轴
timeline = merge_by_time(vision_timeline, subtitle_events)
到这一步,视频已经被"翻译"成这样一份文档:
[00:02:15] 画面:演讲者翻到标题为"增长数据"的PPT页
[00:02:18] 语音:去年我们的用户量增长了百分之三百
[00:05:40] 画面:切换到产品演示环节,出现手机操作界面
[00:05:47] 语音:接下来给大家演示新版本的核心功能
...
这页"纸"就是后续所有产出的原料。
4 ~> 第三步:三类产出物
4.1 自动字幕:导出标准SRT
def to_srt(segments) -> str:
def fmt(t):
h, rem = divmod(int(t), 3600)
m, s = divmod(rem, 60)
return f"{h:02d}:{m:02d}:{s:02d},000"
return "\n\n".join(
f"{i}\n{fmt(seg.start)} --> {fmt(seg.end)}\n{seg.text}"
for i, seg in enumerate(segments, 1)
)
Whisper的时间戳直接转成SRT格式,导回剪辑软件或播放器即挂即用。比人工听打快两个数量级,需要人工介入的只有专有名词校对。
4.2 章节式摘要
def summarize(timeline_text: str) -> str:
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content":
"以下是视频的时间轴记录(画面描述+语音转写)。"
"请生成章节式摘要:按内容划分3~8个章节,"
"每章给出:起止时间、章节标题、3句话内容概括。\n\n"
+ timeline_text}],
)
return resp.choices[0].message.content
章节摘要比整段摘要实用得多——观众拿着章节标题直接跳转到感兴趣的段落,"可速览"的承诺才算兑现。
4.3 高光片段定位
def find_highlights(timeline_text: str) -> list[dict]:
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content":
"从以下视频时间轴中,选出3~5个信息密度最高、"
"最适合做传播片段的高光时刻。输出JSON数组:"
'[{"start": "秒数", "end": "秒数", "title": "片段标题", '
'"reason": "入选理由"}]\n\n' + timeline_text}],
response_format={"type": "json_object"},
)
return json.loads(resp.choices[0].message.content)["highlights"]
拿到起止时间戳,ffmpeg无损剪切(不重编码,秒级完成):
ffmpeg -ss 135 -to 218 -i input.mp4 -c copy highlight_01.mp4
高光选择的好坏取决于Prompt里的"标准"——"信息密度最高"适合发布会,"情绪最激动"适合比赛录像,"操作演示最完整"适合教程。把你们内容团队挑片子的口头标准写进Prompt,就是机器剪辑的品味来源。
5 ~> 进阶:视频 RAG
处理过的视频别扔——时间轴入向量库,视频就变成可检索资产:
# 时间轴节点逐条向量化(第98篇Chroma即可)
for node in timeline:
col.add(
documents=[f"{node.get('desc','')} {node.get('text','')}"],
metadatas=[{"video_id": vid, "timestamp": node["time"]}],
ids=[f"{vid}_{node['time']}"],
)
# 查询:"哪个视频里讲了用户增长数据?"
# → 命中节点 → 元数据里的 video_id + timestamp
# → 直接定位到原片的第几分几秒
这就是多模态视频RAG的最小实现:检索到的不是一段文字,而是"某视频的第5分40秒"。会议录像库、培训视频库接上它,"找内容"从拖进度条变成一句话查询。
5.1 成本实测(1小时视频)
处理成本画像(gpt-4o-mini + whisper API):
抽帧300张视觉理解 ≈ ¥1~2
Whisper 60分钟转写 ≈ ¥2.5
摘要/高光文本生成 ≈ ¥0.1
─────────────────────────
合计 ≈ ¥4~5 / 小时视频,全程约10分钟
对照:人工剪辑摘要半天工时 —— 成本下降两个数量级
思考 && 总结
- 核心思路是降维: 视频不进模型,抽帧+音轨转写成"带时间戳的图文序列"——画面走视觉理解、声音走Whisper,时间轴上对齐。
- 抽帧用混合策略: 场景切换帧抓突变+固定间隔帧保底,1小时压到300帧,成本降92%;每帧出生即带时间戳。
- "同前"机制双赢: 带上帧描述提问、无变化答"同前"——成本骤降,时间轴自动瘦身为内容变化点。
- 三类产出一条链: 字幕(Whisper时间戳转SRT)、章节摘要(LLM分段)、高光片段(LLM选段+ffmpeg无损剪切);挑片标准写进Prompt就是机器品味。
- 视频RAG闭环: 时间轴入库,检索命中"某视频第几分几秒"——录像库从黑盒变成可查询的知识资产,成本约5元/小时。
至此"看听说画视频"五感全部打通。下一篇回到本地部署主线与多模态的交汇点:LLaVA本地多模态模型——不花一分钱API费,在自己电脑上分析图片。
结尾
各位小伙伴,本文的内容到这里就全部结束了,源码骑士在这里再次感谢您的阅读!
源码骑士 — Android Framework & 全栈开发
👀 关注:跟博主一起从源码视角深耕底层原理,见证每一次成长
❤️ 点赞:让优质内容被更多人看见,让知识传递更有力量
⭐ 收藏:把核心知识点存好,在需要时随时查、随时用
💬 评论:分享你的经验或疑问,评论区一起交流避坑
🔄 一键四连:不要忘记给博主"一键四连"哦!
🗡️ 寄语:技术之路难免有困惑,但同行的人会让前进更有方向
结语:一帧一世界,一秒一印记——视频理解的全部技巧,就是把流动的画面定格成带时间戳的文字。当一小时录像变成一页纸,信息的消费效率就完成了数量级的跃迁。不要忘记给博主"一键四连"哦!
火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。
更多推荐
所有评论(0)