ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ASR+LLM:视频课程自动摘要与知识点提取流水线实践

ASR+LLM:视频课程自动摘要与知识点提取流水线实践 前阵子我接了内部知识库的一个活儿把五十多门录播课转成可检索的课程摘要和知识点清单。一开始我以为这活儿很简单不就是给每门课写个简介嘛结果真上手才发现课程视频动不动就两三个小时人工看完再整理摘要一门课就能烧掉大半天。后来我干脆用 ASR LLM 搭了一条自动化流水线视频丢进去出来的是结构化摘要、知识点列表、章节重点还带时间戳定位。跑通之后五十多门课基本上一个周末就能全量处理完。这篇文章就是我当时完整的设计思路和踩坑记录给同样在做视频课程治理、知识库建设或者在线教育后端的同行一个参考。整个流水线没有特别炫技的操作但坑是真不少。语音识别选型、长音频分段、提示词设计、异步编排、缓存容错、效果评估每一环都有能直接复用的细节也有很多网上教程不会告诉你的教训。下面按我实际推进的顺序一步步拆给你看。1. 视频课程摘要难在哪口语噪声与知识密度并存1.1 录播课不是带字幕的视频我刚做的时候犯过一个认知错误以为把字幕跑出来再丢给大模型摘要就自动出来了。但录播课和普通视频有着本质区别——它的信息密度极不均匀。老师上课时会有大量口语表达这个地方大家注意一下我们等会儿会再讲上节课我们提到了…。这些话对真实课堂有意义但对自动摘要来说全是噪声。更麻烦的是很多老师在关键知识点上会反复换着说法解释比如先给定义再举例子再带着做一遍这是教学设计的合理思路可如果简单用文本压缩的方式处理摘要会把重复的强调和真正的知识点增量混淆。我手工看了几份转写文本之后第一个结论是视频课程摘要的前提是把讲课内容重新组织成知识结构这件事不能指望一句通用 Prompt 解决必须先做中间层的拆分和清洗。1.2 转写错误会被 LLM 放大到不可用做过 ASR 的同学都知道转写准确率不可能 100%。普通访谈场景错几个字问题不大人脑能自动纠错。但在课程摘要里一个关键术语错了后果会一路传导到摘要里。举个真实例子我们有一门课讲 Bloom Filter 布隆过滤器转写引擎在几处把它听成 Bloom 过滤器还有一处直接变成 Bloom 不过滤器。如果直接拿这段文本去让 LLM 总结它会一本正经地生成本讲介绍了 Bloom 不过滤器的基本原理这个错误肉眼几乎排查不出来只会让懂行的人觉得这个知识库质量不行。所以我后来在设计流水线时把术语纠错专门独立成了一个环节先对 ASR 输出做一次领域词典的强制替换和校验再进 LLM。这个步骤在短文本里容易被忽略但在几十小时课程批量处理时属于不做必炸的细节。1.3 目标不是压缩视频而是提取知识结构想清楚交付物形态比急着选技术栈更重要。我最初以为 AI 摘要就是从 2 小时浓缩成 500 字后来跟使用方一聊才发现他们要的其实有三层课程简介用于列表页展示3 到 5 句话讲清楚这门课能学到什么章节摘要按课时或主题段落组织方便学员快速定位这一段在讲什么知识点清单可检索、可跳转的最小粒度单元包含这是什么为什么怎么操作的信息这三层需求决定了流水线不能只走转写 → 一次摘要的流程而要做成分层抽取的结构化管道。这也直接影响了后面 LLM Prompt 的设计方向。2. ASR 选型与长音频分段转写质量决定了摘要的天花板2.1 开源模型和商用 API 的取舍做 ASR 选型时我对比过本地开源的 Whisper、几个商用 API还有之前采购过的老牌识别引擎。结论是只有混合策略是稳的。Whisper 类的开源模型优势在于完全可控本地部署、无外部接口几十小时的视频全量跑不用担心流量费用和隐私问题。但代价是 GPU 占用和推理时间。我们用了 V100 级别的卡1 小时音频的英文转录大约需要 15 到 20 分钟中文普通话更快一些如果换成 Tiny 模型能再压但准确率掉得厉害。商用 API 的准确率通常更好特别是对专业领域的人名、术语覆盖更多价格也部分可以接受。但我不建议直接无脑上传课程音频一是数据合规问题二是长期成本不稳定。我实际的做法是把商用 API 先跑一批人工抽查对比 Whisper 在同领域的差错率如果差距在 2 到 3 个百分点内就优先用本地模型只有对准确率要求极高的精品课程才走 API 并用本地结果做交叉纠正。对比维度 | 本地 Whisper 类 | 商用 API 语音转写准确率 | 普通话和英语都不错专业术语需额外纠错 | 通常略高但专业术语也可能错 成本 | 只有 GPU 和电费 | 按分钟计费大量课程时会很贵 数据隐私 | 完全本地可离线 | 有外网传输需评估合规 并发控制 | 自己控制灵活 | 受配额和限流影响 推荐场景 | 批量、私域、成本敏感 | 少量高质量要求场景2.2 分段策略比想象中重要得多长音频不能一次性塞给 ASR这是常识但分段策略大有讲究。我一开始图省事按固定 30 秒切一刀结果句子被拦腰截断转写质量大面积崩坏。后来改成两步第一步先用 VAD语音活动检测去除开头结尾的静音和长停顿。很多课程视频片头片尾都有主题曲和空白不切掉的话会对后续转写做无意义的功耗。第二步在有效语音的基础上按语义边界切分。我用的策略是 30 秒一段、带 3 秒重叠窗口如果 30 秒内检测到超过 0.8 秒的静音就从这个静音处优先切分。这样既不会把一句完整的话切断也能控制单段文本的长度方便后续 LLM 分片摘要。下面这段是我调通的核心流程用伪代码来描述def split_audio(audio_path): # 1. VAD: 去掉前后静音得到有效区间 active_ranges vad_detect(audio_path) # 2. 在每个有效区间内按 30s 3s overlap 滑动切分 chunks [] for start, end in active_ranges: cursor start while cursor end: chunk_end min(cursor 30, end) chunks.append(audio_path[cursor:chunk_end]) cursor chunk_end - 3 return chunks别小看那个 3 秒重叠。它能让跨段句子在两端都出现后续合并文本时通过拼接规则去掉重复。代价是多转写了一点点文字但换来了转写完整性绝对值。2.3 转写噪声清洗与术语纠错ASR 转写完之后文本里带着大量口语词、无意义停顿词嗯那个以及同音错字。我建了一个清洗模块做下面三件事用正则和词表去掉纯口语填充词用领域词表进行强制替换对可能出错的术语通过原文 同音候选的方式做二次纠正强制替换要小心。如果我直接把Bloom 不过滤器替换成Bloom 过滤器万一 LLM 之后引用这句话时就是一个错误知识。更好的办法是保留原始文本再在清洗结果后附加一行术语映射表让 LLM 在摘要时使用映射后的术语而不是直接改原文。实际效果清洗完后LLM 生成内容里的术语错误率肉眼可见地下降尤其是专业入门课程里一堆概念名词比如死锁线程安全梯度消失这些在通用 ASR 模型里都是重灾区。2.4 时间戳对齐摘要要能跳回原视频做课程知识库摘要的价值一半在能定位到原视频的位置。所以转写时每个词、每个句子都要保留时间戳。我用的是带时间戳输出的转写模型输出形如[00:12:35] 接下来我们介绍布隆过滤器的插入操作。时间戳对齐其实有坑分段重叠会导致同一个句子出现在两个分段里时间戳不一致。我在合并分段文本时会保留第一次出现的时间戳并丢弃后面重复部分的词级时间戳。如果某个知识点的摘要需要引用多个片段我会让 LLM 输出起始时间戳再在入库时用二分查找对齐到最近的一句完整话。3. LLM 摘要与知识点提取提示词和 Schema 是核心资产3.1 朴素 Prompt 为什么效果差我最早试过最直观的 Prompt请总结这段视频课程的内容。效果非常灾难。输出是本讲介绍了若干重要概念涵盖理论与实践适合初学者快速入门这种正确的废话。问题出在三方面没有定义总结的输出粒度是 100 字还是 1000 字没有定义知识点清单的结构是列表、段落、还是 JSON上下文太长把一整节 40 分钟的视频转写全塞进去模型注意力被稀释生成的全是高频词反而丢了关键细节。改了一轮后我把任务拆成了分段落摘要和知识点抽取两条线各自用独立的 Prompt 和 Schema。3.2 分片摘要避免长上下文的信息稀释我实际使用中单次喂给 LLM 的转写文本控制在 2000 到 3000 字以内。如果是 2 小时的课先按课程内的自然章节一般是视频里的章节或 PPT 分节把转写切成若干段每段独立生成一个段落级摘要然后再把段落摘要合并生成章节级摘要。这个两级结构的好处是段落级摘要保留了具体细节章节级摘要可以做层次化归纳。如果直接从全文跳级生成某个知识点只在第 20 分钟出现过一次后续再也没有被提最后生成的摘要很可能把它漏掉。段落级输入 [片段1转写] [片段2转写] 输出 { 段落主题: 布隆过滤器的插入流程, 关键知识点: [哈希计算, 位数组置1, 冲突处理], 时间戳: 00:12:35 }3.3 知识点提取的 Schema 设计这里我再强调一次Schema 设计决定了这个流水线做出来是能用还是好用。我最终定的 Schema 长这样{ knowledge_points: [ { id: kp_001, title: 布隆过滤器的基本结构, category: 概念定义, summary: 布隆过滤器使用一个位数组和多个哈希函数表示一个集合能快速判断元素是否不在集合中。, timestamp: 00:05:20, related_terms: [false positive, hash function] }, { id: kp_002, title: 布隆过滤器的插入与查询流程, category: 操作步骤, summary: 插入时将元素经过k个哈希函数映射到k个位置并置1查询时检查这k个位置是否全部为1。, timestamp: 00:12:35, related_terms: [位数组, 查询逻辑] } ] }我要求模型必须输出严格的 JSON并且timestamp要从输入文本中的时间戳标记里找到对应句子的起始位置不准凭空编造。为什么要加category因为不同知识点的教学类型不同有的是定义有的是操作步骤有的是常见误区。把类别标出来前端可以做筛选后面做问答索引时也能更精细地匹配。3.4 Prompt 模板与约束表达下面是我在项目里稳定使用的 Prompt 结构四个要素缺一不可你是课程知识库的标注员任务是从课程转写文本中提取结构化知识点。要求只基于下面的输入文本禁止添加视频中未出现过的信息。每个知识点必须能在输入文本中找到对应句子并在 timestamp 中给出该句的时间戳。分类只允许使用概念定义操作步骤原理推导常见误区案例应用。输出为 JSON 对象不要输出其他解释。文本 {transcript_chunk}我试过用少样本few-shot的方式进一步拉高稳定性比如给一个什么是原子性的标准输出示例。但如果模型本身能力一般few-shot 容易让输出格式和内容过度贴近示例反而限制了真实抽取的广度。后来我用的是约束词表 强制 JSON 输出的方式效果更稳。4. 流水线编排、缓存与容错让任务跑得稳、花得少4.1 任务状态机每个视频都能断点续跑一开始我用的是最简单的顺序执行脚本转写 → 清洗 → 分段 → 摘要 → 入数据库。跑第一个视频时挺爽跑第十个视频时中间一次网络超时全部重新来一遍气得想砸电脑。后来我改成一个轻量状态机每个视频有五个状态pending已上传待处理transcribing正在转写cleaned清洗完成summarizingLLM 摘要中done入库完成如果某个步骤失败任务会回到对应状态等待重试已有中间结果直接复用。比如转写完成但 LLM 调用失败不需要重新转写。这个设计看着简单但对批量处理来说节省的时间是指数级的。4.2 缓存策略同一门课杜绝重复处理课程视频在内容管理后台可能被反复上传、覆盖、迁移如果每次上传都重新跑一遍全流程成本会爆炸。我在文件导入阶段计算内容 Hash按sha256 文件大小做唯一标识把 ASR 结果和最终入库的知识点都缓存起来。这样同一个视频重新上线时直接把上次的结果拉出来还可以选择是完全跳过还是只重新用当前模型做摘要纠错。如果未来 LLM 升级了我也能只升级摘要部分不用再跑一遍昂贵的 ASR。4.3 限流与重试LLM 调用不是无限故障容忍的大模型接口在实际生产环境里的表现跟本地测试完全是两回事。限流、超时、500 错误时有发生。我总结了一套自认为比较稳妥的重试策略第一次失败后等待 1 秒重试第二次失败等待 5 秒第三次失败等待 15 秒最多重试四次如果仍然失败把任务降级到本地小模型降级是个很重要的保底手段。我跑批量任务时有一种情况是云端大模型因为并发上限拒绝请求但本地也能跑出一个结果虽然质量差了 5% 到 10%但总比让任务一直卡死好。这个策略看起来笨实际很管用。我处理 50 门课的时候每门课平均要调用大模型 30 到 50 次如果不做重试大约会有 3% 的任务失败做了重试之后最终交付率是 100%。4.4 成本估算1 小时视频到底花多少钱做这个方案之前我列过一个比较细的账给大家参考。按 1 小时视频、纯中文、无大量极端噪声的情况ASR用本地 WhisperGPU 电费成本约 0.5 到 1 元按 V100 每小时电费摊算LLM 摘要按平均 1 小时转写约 1.2 万字算分成 5 到 8 个分片每个分片输出 800 字摘要加上知识点提取输出 1500 到 2500 字 JSON总体 token 消耗大概是输入 2.5 万 输出 0.5 万按当前主流价格一次约合 0.5 到 1 元人民币全流程一门 1 小时课程的总成本大约是 1.5 到 2 元其中大头反而是 GPU 折旧和人工抽查成本这个数字比很多人想得便宜。但要注意的是如果全部走 APIASR 每分钟定价通常高一个数量级一小时从几块到几十块都可能。所以做批量知识库强烈建议优先本地跑 ASR。5. 效果评估与调优别只信 ROUGE 分数5.1 人工评估的四个维度摘要和知识点提取这类生成式任务线上评估很难完全自动化。我建立了一套人工评估量表让两个实习生各评一遍交叉比对知识点覆盖率专家课件里列的 10 个核心知识点摘要里提到了几个准确性有没有事实错误、术语错误、逻辑错乱可定位性根据摘要中的时间戳能不能在原视频里找到对应片段表述可用性把摘要放在知识库里用户能不能一眼看懂、快速判断这节值不值得学覆盖率是最有意思的维度。我拿一门网络协议课测试专家课件有 10 个知识点最初版本只覆盖 6 个后来我把 Prompt 从输出要点改成先识别所有可能的主题句再逐条判断是否构成知识点之后覆盖率升到了 9 个。5.2 用问答命中率做自动化回归人工评估不能天天做我又做了一个自动化回归把提取的知识点灌入向量库然后抽取课件中的判断题和选择题让 Retrieval 去召回相关知识点如果正确率低于阈值说明提取结果的信息量不够。这个思路也是从知识提取的目标反推出来的。既然知识点清单是为了支持检索那就用检索任务来证明它有没有用。我做过一个实验把同一门课用旧版本摘要和新版本结构化知识点分别建索引然后用 30 道问答题去测试召回率。结果新版高出约 18 个百分点说明结构化抽取确实有效果而不只是让看起来更好看。5.3 对大模型幻觉的零容忍处理LLM 做摘要最大的风险是幻觉。很多时候它会把常识当作课程中的内容补进去尤其是布隆过滤器可以降低内存占用这种话虽然是对的但如果视频全程没讲出现在课程摘要里就是不合适。我做了两层防护。第一层是在 Prompt 里强制要求只基于输入文本不要外延任何未出现的行业共识。第二层是在入库前做一次事实校验对知识点里的关键实体回到转写原文里做关键词匹配如果完全找不到对应文本就标记为待人工确认。这套策略牺牲了一点自动完成率大概会有 5% 的知识点进入人工复核通道但换来的是知识库的信任度。毕竟用户一旦发现摘要里有一个错误概念整个库的可信度都会塌方。5.4 一个调优案例从概括一段话到提取可检索的知识点最后说一个我自己印象最深的迭代。最早版本知识点的标题是这种风格本章主要讲了布隆过滤器的定义和原理老师通过图示说明了插入操作的流程这种标题放在知识库里毫无检索价值。后来我把 Prompt 改成标题必须是名词短语或不超过 15 字的陈述句禁止出现本章老师主要这些引导词输出变成布隆过滤器定义与误判率上界插入操作k 次哈希与位置置 1删除问题标准布隆过滤器不支持删除前后一对比检索体验完全不一样。用户搜误判率能直接命中第一个知识点而不是在本节内容概述里捞针。这个改动不需要改任何代码只改 Prompt 里的约束表达但效果是最显著的。这个项目里最让我意外的不是 AI 有多聪明而是把工程细节抠到位之后AI 的应用效果能稳定到什么程度。ASR 负责把声音变成可信的文字LLM 负责把文字变成结构化知识流水线负责让海量课程在没有人工盯着的条件下跑完每一步都有对应的坑和标准动作。回想一下那些失败的尝试大多数都是因为太想直接拿大模型一把梭跳过了中间层的清洗、分段和 Schema 设计。按照这套流程跑通之后现在的新课程入库基本是无人值守的我从每门课 5 小时的人工整理时间降到了 10 分钟人工抽查加改错。如果手里也有大量视频课程需要治理不妨先从小批量跑通这个 ASR LLM 的流水线再根据自己课程类型微调术语表和 Prompt 约束很快就能看到效果。
返回列表