看完一个二三十分钟的视频,你有没有过这种体验:当时觉得讲得挺好,过几天想找其中一个观点,却只记得「好像在后半段」?
为了解决这个问题,我做了一个 Chrome 插件,叫「豆包陪看助手」:打开 B 站视频,点一下页面上的豆包,它会陪着看,顺手把视频整理成摘要和带时间点的大纲。想回顾某一段时,点大纲就能跳回去,也可以展开那一段的 AI 解读。
图 1:0.2.0 扩展在真实 B 站页面上的陪看入口。
一开始,需求看起来像是拿到字幕,再把它交给模型。真做起来才发现,视频页面、字幕、语音、模型和浏览器后台各有各的问题:字幕拿不到,到底是真的没有,还是网络出了错?一个视频同时在两个标签页打开,会不会扣两次费?用户已经清空记录,晚到的模型结果会不会又把它写回来?
这篇文章记录几个实际遇到的问题,以及目前的处理方式。项目的文本模型接口由用户自行配置;开发和验收中用过豆包 Seed 模型,0.2.0 也接入了可选的豆包语音识别。这不是 B 站官方产品。0.2.0 已提交 Chrome 应用商店审核,正式上架时间和安装入口以审核结果为准。
图 2:真实 B 站页面中的摘要和分段解读,来自 0.0.1 版本的真实模型验收截图;界面以当前版本为准。
先说架构:一只豆包背后有几份工作
扩展使用 WXT、TypeScript 和 Chrome Manifest V3 开发。页面里的豆包、面板和播放器状态监听由 Content Script 负责;为了减少 B 站页面样式对插件的影响,界面放在 Shadow DOM 里。这里的隔离主要是样式和组件层面的便利,不能把它当成安全沙箱。
后台 Service Worker 负责排队、去重和状态协调;需要较长时间或 DOM 能力的音频处理、模型调用交给 Offscreen Document。观看记录、转写、摘要和任务状态通过 Dexie 存在 IndexedDB,配置和 Key 使用浏览器本地存储。B 站、文本模型和可选语音服务都是外部依赖,项目本身没有自建业务服务器。
图 3:产品架构示意图,展示浏览器内各部分的职责和外部服务边界。
这样的结构省掉了部署和维护业务服务器的成本,用户也不需要另外注册一个产品账号。代价是用户需要自己配置模型服务;本地记录也不会自动跨设备同步。对一个体量不大的插件来说,我接受这个取舍。
另一个看起来很小、实际影响费用的细节是触发时机。新安装默认需要前台有效播放达到 10 秒,才开始整理;暂停或切到后台不累计。实现时根据播放器的媒体时间增量计时,拖动进度条产生的大跳变不算有效观看。否则用户只是打开页面瞄一眼,甚至拖了一下进度条,就可能触发一轮模型调用。
第一个坑:视频有 21 分钟,大纲只写到第 7 分钟
早期验收时,有个视频时长 21 分 12 秒,插件确实生成了摘要,大纲看起来也像那么回事。但细看最后一条,大纲只到了 07:47。原始记录里其实保存了完整的 587 条字幕,最后一条结束于 1270.92 秒,问题并不是「字幕只拿到了前面」。
检查下来有两个原因:一是原来只校验大纲的结构和条数,没检查前、中、后段是否有覆盖;二是某一段解读的输入超过 6000 字时,旧实现直接截去了尾部。
这类问题很容易被「模型返回成功」掩盖。JSON 格式正确、节点数量也对,不代表用户拿到了一份能用来回顾全片的笔记。
后来我做了几件事。长字幕按带时间戳的内容分块,默认每块约 14400 个字符,块与块之间在预算允许时保留最多约 30 秒的重叠,减少语境在边界处断开。每块先提取局部要点,再把要点交给模型汇总;默认最多并发处理 3 块。对于过长的单段解读,也改成处理完整的多个分块后再合并,不再简单丢掉后半截。
模型输出回来以后,除了检查结构,还要检查时间是否有序、是否落在已有字幕的范围内,以及长视频的前、中、后是否获得足够覆盖。覆盖不足就带着错误提示重试;再次不满足时报告失败。这里的覆盖检查是工程护栏,能发现明显遗漏,但不能证明每个要点都准确,也不要求模型给没有字幕的时间编造内容。
图 4:0.0.2 阶段的真实 Chrome 验收截图,画面裁取了插件面板;该样本修复后最后一条大纲位于 20:35。
修复后,还是这个 21:12 的样本,最后一条大纲到了 20:35,末段也能展开解读。另外两个 27:44 和 41:06 的真实视频样本,大纲最后一条分别到了 26:00 和 40:30。这些是在真实 Chrome 和真实模型服务下做的样本检查,不代表任意视频都不会遗漏,也不等于摘要事实准确率有了某个百分比。
这个坑给我的提醒是:**做长内容摘要,验收不能只看开头几条和接口有没有报错。**至少要拿原视频的前、中、后段去对照,尤其要检查最后一段到底有没有被处理。
第二个坑:没拿到字幕,不代表视频没有字幕
能用现成字幕时,我优先使用字幕:先选可用的人工中文字幕,再考虑中文字幕中的 AI 字幕。字幕本身带时间信息,通常也不需要额外下载整段音频和调用语音识别服务。
但「字幕获取失败」和「确认没有可用中文字幕」是两回事。登录状态失效、网络错误、站点风控,或者接口返回结构异常,都可能让字幕没拿到。如果把这些情况统一写成一个 if (!subtitle),直接转去下载音轨,用户就可能在不知情的情况下上传音频、消耗语音额度。
图 5:字幕优先的处理流程示意图。异常与确实无字幕走不同分支。
现在的处理是:先区分「有可用字幕」「确认没有可用中文字幕」「获取过程出错」。只有确认无字幕,并且用户已经配置、授权语音服务时,才自动下载完整音轨,交给所选服务识别。网络、登录和风控错误会提示处理,不会因此自动发送音频。
为了验证这条分支,我还检查过两个真实登录态的 B 站样本:一个有人工字幕,一个有 AI 字幕;摘要模型使用本地模拟服务。监测覆盖到的扩展后台和离屏页面里,两次都没有音频下载或语音识别请求。这个结果只说明当次两个样本的行为,不等于所有网络条件都已验证。
图 6:0.2.0 扩展在真实 B 站页面上的语音服务配置界面,未填写真实密钥。
这个决定也带来了产品上的责任:音轨会发给用户选择的第三方服务,可能产生费用,也可能提前处理用户还没看过的内容。所以配置界面需要把发送范围、费用和剧透风险说清楚。生成摘要时,字幕或转写及必要的视频信息同样会发送给用户配置的文本模型;「记录保存在本地」不等于「所有数据都不会出浏览器」。Key 存在浏览器本地也不等于已经加密,配置时仍应选择信任的服务。
第三个坑:语音识别跑得快了,内存也上来了
最初的方案用接近实时播放的方式提取音频,再按实时速度发送。这个思路比较直观,但处理 13 分钟视频,光发送就可能接近 13 分钟,还没算下载、识别和摘要。
后来的豆包语音路径改成:下载完整音轨,在扩展的离屏页面解码成 16 kHz 单声道 PCM,再以受控缓冲发送给语音服务。完整转写通过时间和内容等检查后,才继续整理局部要点与全片摘要;有效转写也可以在后续摘要处理中复用。
时间戳也踩过坑。一次复用转写的诊断中,两轮生成的大纲里都出现了超过视频时长的时间点,分秒与总秒数混淆是排查出的可能原因。后来 ASR 摘要输入改用明确的整数总秒数,比如把 10:12 表示成 612 秒,并在输出端检查范围和顺序。这样可以拦住一部分明显错误,但仍需要对照原视频检查时间点和内容是否匹配。
一次受控对照用了同一段 28.448 秒的合成中文语音:按实时速度发送,从首包到最终返回约 29.384 秒;快速有界发送约 3.717 秒。这个数字只比较该次发送和返回过程,不包含音频下载、解码、摘要,也不能当作产品的端到端耗时。
速度换来的是资源压力。另一次隔离 Chrome 测试中,约 13 分钟的单声道合成音频离线解码后,观察到浏览器进程树 RSS 相对基线增加约 447 MiB;其中可能包含共享内存,不能直接套用到其他设备或双声道视频。它至少说明,不能因为「音频文件看起来不大」,就忽略解码后的内存开销。
所以目前豆包 Agent Plan 这条路径设置了项目侧边界:最长 15 分钟、音轨不超过 25 MiB、最多双声道;这些不是服务商的官方上限。超限或无法确认完整性时,宁可提示失败,也不把只处理了一部分的结果写成「全片摘要」。以后想支持更长的视频,需要继续研究分块解码、资源占用和边界对齐,不能只把时长限制改大。
第四个坑:后台可能休眠,迟到的结果还会回来
Chrome 扩展的 Service Worker 不是一直在线的后台进程。按照 Chrome 官方的生命周期说明,它在空闲等条件下可能被终止;全局变量也会随之消失。Offscreen Document 可以提供隐藏页面和 DOM 能力,但也不能代替任务恢复设计,具体限制见 Chrome Offscreen API 文档。
项目把任务和状态写入 IndexedDB,并区分等待中、运行中、完成和失败等状态。相同会话、视频、任务类型和分段的活动任务,在入队事务里检查去重,避免两个标签页同时触发重复任务。后台恢复时,再根据任务类型判断后续如何处理。
语音任务有个额外问题:请求中断,并不等于服务端一定没有处理,也不等于没有计费。因此,计费状态不明时,扩展不会静默重发音频,而是提示用户决定是否重试。普通任务和语音任务不能简单共用一个「失败就再试一次」的策略。
还有一种竞态更隐蔽:用户清空记录时,远端请求可能已经发出。即使调用了取消,也不能假定每个已经在途的操作都会立刻停下。现在任务会带执行标识 runId;ASR 链路把取消信号传给可中止的操作,结果写回时还会在数据库事务里核对任务与会话状态。任务已经失效,就拒绝写入,避免旧结果在清空后重新出现。
这套机制的目的不是保证外部服务永远稳定,而是让中断、重试和取消有明确的后果。对会消耗用户额度的 AI 功能来说,这一点和模型本身的效果一样值得认真设计。
目前验证到哪里,还有什么没做完
截至 0.2.0 的本地验收记录,672 项单元与集成测试通过,另有 16 项隔离浏览器回归通过,覆盖字幕优先、双标签去重、取消、重试等场景。后者使用模拟的 B 站、语音和摘要服务,因此不能拿来证明真实服务在各种网络环境下都稳定。
真实服务方面,此前的一个 0.2.0 开发候选在真实登录环境下,完成了约 12 分 56 秒视频的音频下载、语音识别和摘要;当次从 ASR 任务创建到完成约 286.83 秒,包含识别和后续摘要。这是单次结果,不是性能承诺。最终 0.2.0 构建没有为重复验收再次发送真实音频,长视频的资源占用、系统性的时间误差、多 P 视频,以及 Windows 和其他浏览器的表现仍需继续验证。
回过头看,这个项目最有收获的部分,是逐渐把「生成一段看起来不错的文字」变成「让用户知道这段文字从哪里来、覆盖到哪里、出错时会怎样」。接下来会先跟进商店审核和真实环境补验,再根据反馈考虑导出、视频问答等功能;这些都还没有确定发布时间。
如果你也在做类似的 AI 工具,我很建议从真实任务的失败方式倒推设计:输入会不会缺、模型会不会漏、任务会不会被打断、重试会不会让用户多付钱。把这些问题逐个回答清楚,体验通常会比再加一条漂亮的提示词更扎实。