1. 从一段“笨办法”说起:为什么要做这个 Skill
去年下半年,我手头同时压着三个项目复盘,每个项目都攒了十几份会议录屏和几十页的 PPT。那段时间我干得最多的事,就是戴着耳机一遍遍拖进度条,把视频里讲到的关键结论手敲进文档,再把 PPT 里的图表一张张截图、配文字说明。一个两小时的录屏,光整理成能看的文字稿,就得耗掉我大半天。更崩溃的是,PPT 里那些藏在备注栏里的补充说明,往往才是真正有价值的部分,但肉眼翻页根本注意不到。
后来我开始琢磨:视频和 PPT 本质上都是“信息密度不均匀”的载体。视频里大量时间花在过渡、寒暄、重复强调上,真正有信息量的可能只占两三成;PPT 则是把结论高度压缩在页面里,但缺少上下文和推导过程。如果能把这两类内容自动提取成结构化的文字,再让模型帮我做摘要和要点归纳,那省下来的时间就非常可观了。
这就是Agent Skill:视频/PPT 内容提取 Skill诞生的起点。它要解决的问题很具体:把视频(音频轨)和 PPT(含备注)里的内容,自动转成干净、可检索、可二次加工的文字素材。适合谁用?做会议纪要的职场人、需要整理课程资料的学习者、做竞品分析的产品同学、以及任何经常和“录屏+幻灯片”打交道的人。哪怕你完全不懂编程,只要会配置一个 Skill,就能把它挂到自己的 Agent 工作流里。
我把它定位成一个“内容提取中间件”——它不负责帮你写报告,也不负责做花哨的总结,它只干一件事:把非结构化的音视频和幻灯片,变成结构化的文本。剩下的摘要、翻译、问答,交给下游的模型或你自己处理。这种“单一职责”的设计,是我踩了很多坑之后才想明白的,后面会详细讲。
2. 整体设计思路:为什么是“提取”而不是“总结”
2.1 核心需求拆解:三类用户的真实痛点
在动手之前,我先梳理了身边十几位同事和朋友的反馈,发现需求其实分成三层。
第一层是**“我要文字”**。很多人只是想把视频里的语音转成文字,方便搜索和引用。这类需求最朴素,但市面上很多工具要么收费贵,要么对中文识别效果一般,要么导出格式乱七八糟。
第二层是**“我要结构”**。光有文字不够,还得知道哪段是开场、哪段是核心论点、哪段是问答。PPT 也一样,不能只给我一堆散页文字,得保留页码、标题、备注的对应关系。
第三层是**“我要能接着用”**。提取出来的内容要能直接喂给下游的 Agent,比如自动生成会议纪要、自动对比两版 PPT 的差异、自动把课程内容做成问答卡片。这就要求输出格式必须是机器友好的,比如 Markdown 或 JSON。
这三层需求决定了 Skill 的设计不能只做一个“转录工具”,而要做成一个带结构信息的提取管道。我见过太多工具只解决了第一层,结果用户拿到一大坨文字后还是得手动整理,等于白干。
2.2 方案选型:为什么不用现成的“一键总结”服务
市面上有不少“上传视频自动出摘要”的服务,我也试过几个。它们的问题在于:摘要质量不可控,而且你拿不到原始提取结果。比如某次我用一个工具处理技术分享视频,它把“这个方案在并发场景下会有锁竞争问题”总结成了“该方案性能较好”,完全把意思搞反了。原因很简单,摘要模型在压缩信息时,会丢失它认为“不重要”的细节,而这些细节对你可能恰恰是关键。
所以我决定把 Skill 拆成两个独立阶段:提取阶段和加工阶段。提取阶段只做“忠实还原”,把视频的语音转成带时间戳的文字,把 PPT 的每页文字、备注、甚至图表标题都抽出来,不做任何主观删减。加工阶段才交给下游模型去做摘要、翻译、问答。这样你既能拿到“原料”,也能按需“烹饪”,而不是被迫接受一份别人嚼过的饭。
另一个选型考量是本地优先。很多会议录屏涉及内部信息,上传到第三方服务有合规风险。所以 Skill 的设计尽量让核心提取环节在本地完成,只有需要调用大模型做加工时才走网络,而且调用哪家模型、传什么内容,完全由你控制。这一点对企业和团队用户尤其重要。
2.3 技术路线:语音识别 + 幻灯片解析 + 结构化输出
具体到技术实现,整个 Skill 分成三条并行的处理线。
第一条线是音频处理。视频文件先用 FFmpeg 把音轨抽出来,转成 16kHz 单声道 WAV,这是绝大多数语音识别模型的标准输入格式。然后调用语音识别引擎做转录,输出带时间戳的文本片段。这里有个关键选择:是用本地模型还是云端 API?我的建议是,如果对准确率要求极高且内容不敏感,可以用云端;如果涉及内部信息,本地模型虽然慢一点,但胜在可控。Skill 里我把两种方式都做成了可切换的配置项。
第二条线是幻灯片解析。PPT 文件本质是个 ZIP 包,里面 XML 记录了每页的文字、位置、层级关系。用 python-pptx 这类库可以逐页读取文本框内容,同时把备注栏也抽出来。这里有个坑:很多 PPT 的正文是图片或 SmartArt,直接读 XML 读不到文字。所以 Skill 里加了一个可选的 OCR 兜底步骤,对读不到文字的页面做截图识别。
第三条线是结构化输出。把音频转录结果和幻灯片内容按时间轴或页码对齐,输出成统一的 Markdown 或 JSON。Markdown 适合人看,JSON 适合机器处理。对齐逻辑是:如果视频里提到了“第三页”,就尝试把那段语音和第三页的幻灯片内容关联起来;如果无法对齐,就分别输出两个独立章节。
提示:三条线的处理顺序可以并行,但输出对齐需要等前两条线都完成。实际跑的时候,音频转录通常是最慢的环节,建议先启动它,再去处理幻灯片。
3. 核心细节解析:每个环节的坑与技巧
3.1 音频提取:为什么必须重采样到 16kHz
很多人拿到视频后直接丢给语音识别接口,结果要么报格式不支持,要么识别准确率惨不忍睹。问题往往出在采样率上。大多数视频的音轨是 44.1kHz 或 48kHz 立体声,而主流语音识别模型是在 16kHz 单声道数据上训练的。不重采样,模型会先做一次内部转换,这个转换过程可能引入失真,尤其是对高频辅音(比如 s、sh、f)的识别影响很大。
我的做法是用 FFmpeg 一步到位:
ffmpeg -i input.mp4 -vn -acodec pcm_s16le -ar 16000 -ac 1 output.wav参数解释:-vn去掉视频轨,-acodec pcm_s16le指定 16 位小端 PCM 编码,-ar 16000重采样到 16kHz,-ac 1转单声道。实测下来,这一步能让中文语音识别准确率提升 5 到 10 个百分点,尤其是对带口音的普通话。
还有一个细节:如果视频很长(超过一小时),建议先按静音段切分。语音识别模型对超长音频的处理效率会下降,而且一旦中间出错,整个文件都要重跑。用 FFmpeg 的静音检测可以自动切分:
ffmpeg -i output.wav -af silencedetect=noise=-30dB:d=0.5 -f null -这条命令会输出静音段的起止时间,你可以据此把长音频切成若干段,每段单独识别,最后再拼接。切分粒度建议控制在 5 到 10 分钟,太短会增加调用次数,太长又失去容错意义。
3.2 语音识别:本地模型与云端 API 的取舍
语音识别这块,我试过三种方案,各有适用场景。
| 方案类型 | 代表工具 | 准确率 | 速度 | 隐私性 | 适用场景 |
|---|---|---|---|---|---|
| 本地轻量模型 | 某开源中文识别模型 | 中等 | 快 | 高 | 内部会议、日常记录 |
| 本地大模型 | 某开源大参数模型 | 较高 | 慢 | 高 | 敏感内容、高准确率要求 |
| 云端 API | 主流云服务商 | 高 | 快 | 低 | 公开内容、追求效率 |
我的建议是:日常内部会议用本地轻量模型就够了,识别出来的文字虽然偶尔有错别字,但结合上下文基本能看懂。如果是重要的对外内容,或者要直接引用原文,再考虑云端 API。Skill 里我把识别引擎做成了插件式,换引擎只需要改一行配置。
还有一个提升准确率的技巧:给识别引擎传一个“热词表”。比如你的会议里经常出现某个产品名、技术术语,提前把这些词加进去,识别引擎会优先匹配。这个功能很多云端 API 都支持,本地模型也可以通过微调或后处理实现。我试过在一个技术分享视频里加入二十个专业术语,识别准确率从 82% 提升到了 91%。
3.3 幻灯片解析:正文、备注、图表一个都不能少
PPT 解析的难点不在读取文字,而在判断哪些文字是“内容”,哪些是“装饰”。比如页脚的公司名、页码、模板里的装饰性文字,这些如果都抽出来,会严重干扰后续处理。
我的过滤策略是:先按文本框的位置和大小排序,位于页面顶部或底部、高度很小的文本框,大概率是页眉页脚,直接跳过。正文区域的大文本框优先保留。备注栏则全部保留,因为备注往往是演讲者真正想表达的内容,信息密度比正文还高。
对于图表,python-pptx 能读到图表标题和数据标签,但读不到图表背后的数据表。如果图表是嵌入的 Excel 对象,可以尝试提取;如果是图片,就只能靠 OCR。这里有个经验:优先提取图表标题和坐标轴标签,这两个信息往往就能说明图表在讲什么,不必强求拿到原始数据。
注意:有些 PPT 用了大量艺术字或文本框叠加,导致文字顺序混乱。遇到这种情况,建议按文本框的坐标做一次排序,从上到下、从左到右,还原阅读顺序。我写了一个简单的排序函数,按
top坐标为主、left坐标为辅排序,效果比默认顺序好很多。
3.4 结构化输出:Markdown 给人看,JSON 给机器看
输出格式这块,我坚持“双轨制”。Markdown 用于人工阅读和二次编辑,JSON 用于下游 Agent 消费。
Markdown 的结构大致是这样:
## 视频转录 ### [00:00:00 - 00:05:30] 开场与背景 (转录文字...) ### [00:05:30 - 00:20:15] 核心方案讲解 (转录文字...) ## 幻灯片内容 ### 第 1 页:封面 - 标题:xxx - 备注:xxx ### 第 2 页:问题背景 - 正文:xxx - 备注:xxxJSON 则把每个片段做成对象,包含type(audio/slide)、start_time、end_time、page_number、content、notes等字段。这样下游 Agent 可以按时间或页码检索,也可以做跨模态对齐。
这里有个设计决策:要不要做自动对齐?我一开始想用语音里提到的页码去匹配幻灯片,后来发现准确率不高,因为演讲者不一定按页码顺序讲。所以最终方案是“弱对齐”——只在明显提到页码时做关联,其余情况分别输出,让用户自己判断。这个取舍很关键,强行对齐反而会引入错误。
4. 实操过程:从零跑通一个完整提取流程
4.1 环境准备与依赖安装
先说明一下,这个 Skill 我是在一台普通笔记本上跑的,配置是 16GB 内存、无独立显卡。如果你有 GPU,本地模型的速度会快很多,但没有也能跑,只是慢一点。
基础依赖就三样:FFmpeg、Python 环境、以及语音识别和 PPT 解析的库。
# 安装 FFmpeg(以常见 Linux 发行版为例) sudo apt-get install ffmpeg # 创建虚拟环境 python -m venv skill-env source skill-env/bin/activate # 安装核心依赖 pip install python-pptx pip install openai-whisper # 本地语音识别 pip install pillow pytesseract # OCR 兜底如果你打算用云端语音识别,还需要装对应服务商的 SDK。我建议先把本地方案跑通,再考虑要不要换云端,因为本地方案不依赖网络,调试起来更省心。
4.2 视频处理完整流程
假设你有一个meeting.mp4,完整处理流程分四步。
第一步,抽取音频并重采样。
ffmpeg -i meeting.mp4 -vn -acodec pcm_s16le -ar 16000 -ac 1 meeting.wav跑完后检查一下文件大小,一个两小时的会议音频大约 200MB 左右,如果明显偏小,可能是音轨没抽出来。
第二步,语音识别。
import whisper model = whisper.load_model("base") # 中文场景建议用 medium 或 large result = model.transcribe("meeting.wav", language="zh", verbose=False) for segment in result["segments"]: start = segment["start"] end = segment["end"] text = segment["text"] print(f"[{start:.0f}s - {end:.0f}s] {text}")这里base模型速度快但准确率一般,medium是准确率和速度的平衡点,large最准但慢。我的经验是,中文内容至少用 medium,base 对中文的识别错误率偏高。
第三步,按静音段切分并合并结果。如果音频超过 30 分钟,建议先切分再识别,避免内存溢出。切分逻辑前面讲过,这里不重复。
第四步,输出 Markdown。把识别结果按时间戳整理成章节,每 5 分钟或每个话题切换点作为一个二级标题。话题切换点可以通过文本相似度检测,相邻片段主题差异大时切一刀。
4.3 PPT 处理完整流程
PPT 处理相对简单,但细节多。
from pptx import Presentation prs = Presentation("slides.pptx") for i, slide in enumerate(prs.slides, start=1): print(f"### 第 {i} 页") # 提取正文 for shape in slide.shapes: if shape.has_text_frame: for para in shape.text_frame.paragraphs: text = "".join(run.text for run in para.runs) if text.strip(): print(f"- {text.strip()}") # 提取备注 if slide.has_notes_slide: notes = slide.notes_slide.notes_text_frame.text if notes.strip(): print(f"- 备注:{notes.strip()}")这段代码能覆盖大部分常规 PPT。如果遇到图片型幻灯片,加一个 OCR 步骤:
from PIL import Image import pytesseract # 把幻灯片导出为图片后识别 img = Image.open("slide_3.png") text = pytesseract.image_to_string(img, lang="chi_sim+eng") print(text)提示:OCR 对排版复杂的幻灯片效果一般,建议只对“正文文本框为空但页面有图”的幻灯片启用,避免无谓的计算开销。
4.4 参数选择与效果验证
跑完整个流程后,怎么判断提取质量?我一般看三个指标。
语音识别方面,随机抽 10 个片段,人工核对错字率。如果错字率超过 10%,说明模型选小了或者音频质量有问题,需要换模型或做降噪。
幻灯片解析方面,检查是否有页面输出为空。如果某页明明有内容却输出为空,大概率是图片型页面,需要启用 OCR。
结构化输出方面,检查时间戳是否连续、页码是否完整。如果发现时间戳跳跃,可能是音频切分时丢了片段。
我整理了一个简单的验证清单:
| 检查项 | 合格标准 | 不合格时的处理 |
|---|---|---|
| 语音错字率 | 低于 10% | 换更大模型或加降噪 |
| 幻灯片空页率 | 低于 5% | 启用 OCR 兜底 |
| 时间戳连续性 | 无跳跃 | 检查切分逻辑 |
| 备注提取率 | 100% | 检查备注栏读取代码 |
5. 常见问题与排查技巧实录
5.1 语音识别出来全是乱码或空白
这是最常见的问题,原因通常有三个。一是音频格式不对,比如采样率不是 16kHz,或者声道数不是 1。解决办法就是老老实实按前面的 FFmpeg 命令重采样。二是音频音量太低,识别引擎把静音当成了主要内容。可以用 FFmpeg 做一次音量归一化:
ffmpeg -i meeting.wav -af "volume=2.0" meeting_loud.wav三是语言设置错了,比如中文内容用了英文模型。检查language参数是否设为zh。
5.2 PPT 备注读不出来
python-pptx 读取备注的前提是幻灯片确实有备注页。有些 PPT 在另存为时丢掉了备注,或者备注是以批注形式存在。这时候可以尝试用python-pptx的slide.has_notes_slide判断,如果返回 False,说明确实没有备注。如果明明有备注却读不到,可能是文件格式问题,建议用 PowerPoint 重新另存为.pptx格式再试。
5.3 处理速度太慢怎么办
一个两小时的视频,用medium模型在无 GPU 的笔记本上跑,大概需要 40 到 60 分钟。如果嫌慢,有三个优化方向。一是换小模型,base模型能快一倍,但准确率下降。二是用云端 API,速度取决于网络,通常几分钟就能出结果。三是只处理关键片段,先用静音检测找出“有声音且音量较高”的片段,只识别这些片段,跳过纯静音和低音量部分。
5.4 输出内容太乱,怎么整理
提取出来的原始内容确实会比较乱,尤其是语音转录部分,会有大量“嗯”“啊”“这个”之类的口语词。我的做法是加一个轻量清洗步骤,用正则表达式去掉明显的语气词和重复词:
import re def clean_text(text): # 去掉常见语气词 text = re.sub(r"[嗯啊呃哦]", "", text) # 去掉重复标点 text = re.sub(r"[,。]{2,}", ",", text) # 去掉多余空格 text = re.sub(r"\s+", " ", text) return text.strip()注意不要过度清洗,否则可能把有意义的停顿和强调也去掉。我一般只做一轮轻量清洗,保留原始转录作为备份。
5.5 常见问题速查表
| 问题现象 | 可能原因 | 排查步骤 | 解决方案 |
|---|---|---|---|
| 识别结果空白 | 音频格式错误 | 检查采样率和声道 | 用 FFmpeg 重采样 |
| 识别错字多 | 模型太小 | 查看模型参数 | 换 medium 或 large |
| 备注丢失 | 文件格式问题 | 检查 has_notes_slide | 重新另存为 pptx |
| 处理超时 | 音频太长 | 查看文件时长 | 切分后分段处理 |
| 输出乱码 | 编码问题 | 检查文件编码 | 统一用 UTF-8 |
| 页码错乱 | 文本框顺序乱 | 检查坐标排序 | 按 top/left 排序 |
注意:排查问题时,建议先用一个 5 分钟以内的短视频做测试,快速验证流程是否通畅,再处理长视频。这样能省下大量等待时间。
6. 这个 Skill 还能怎么扩展
跑通基础流程后,我陆续加了一些扩展功能,这里分享三个我觉得最实用的。
第一个是批量处理。如果你有一整个文件夹的录屏和 PPT,可以写一个循环脚本,自动遍历所有文件,输出到对应的 Markdown 文件。我加了一个简单的进度条,跑批量任务时心里有数。
第二个是跨模态对齐。虽然前面说弱对齐,但对于结构清晰的课程视频,可以尝试用语音里提到的关键词去匹配幻灯片标题,自动建立“这段语音对应哪几页 PPT”的索引。这个功能对做课程笔记特别有用。
第三个是下游 Agent 对接。提取出来的 JSON 可以直接喂给摘要 Agent、翻译 Agent 或问答 Agent。我试过把提取结果丢给一个摘要 Agent,让它生成会议纪要,效果比直接对视频做摘要好很多,因为摘要 Agent 拿到的是干净的结构化文本,而不是带噪声的音视频。
最后分享一个小技巧:给提取结果加一个“元数据头”,记录源文件名、处理时间、使用的模型版本、音频时长、幻灯片页数。这样以后回溯问题时,一眼就能看出是哪次处理、用了什么配置。这个习惯帮我省了很多重复排查的功夫。
我个人在实际操作中的体会是,这类提取 Skill 的价值不在于“全自动”,而在于“把重复劳动压缩到最低,把判断权留给人”。它帮你把音视频和幻灯片里的文字捞出来、排整齐,但哪些内容重要、哪些结论成立,还是得你自己过一遍。把它当成一个勤快但不会思考的助手,用起来最顺手。