3.1 离线转写:传完文件等结果的用法
为什么先做离线,而不是实时
工具刚立项时老板的期望是“开会时大屏实时出字幕”,被我拦下来了。理由很简单:我们每周三次例会,没有哪次是必须当场看到文字的,纪要的核心需求是会后发给大家。而实时转写对网络、对会议室设备、对开发复杂度的要求都高得多——离线转写(录音文件识别)只要把文件传上去,等结果回来就行,先把主流程跑通,实时那一路等业务真的需要再说。
离线转写的调用链路其实非常简单:提交一个音频文件,服务异步识别,完成后返回带时间戳的全文文本。我们用的是腾讯云语音识别 ASR 的录音文件识别能力,配合云函数串流程,主链路没写多少代码,绝大部分时间花在调音频参数和等回调上。
离线转写的完整流程
我把整条链路整理成一张表,当时是照着这张表给老板讲的:
| 步骤 | 涉及产品 | 输入 | 输出 | 耗时量级 |
|---|---|---|---|---|
| 1. 上传录音 | COS | 本地或会议室采集的音频 | 存储桶里的音频对象 | 秒级到十几秒(视文件大小) |
| 2. 触发转写 | 云函数 SCF | COS 上传完成的事件 | 提交给 ASR 的转写请求 | 毫秒级 |
| 3. 异步识别 | 语音识别 ASR | 音频对象地址 | 识别任务记录(含任务 ID) | 提交即返回,任务排队等待 |
| 4. 等待并查询 | 云函数 SCF | 任务 ID | 识别完成的通知 | 通常为音频时长的零点几倍 |
| 5. 取回结果 | 云函数 SCF | 任务 ID 的查询请求 | 带时间戳的全文文本 | 秒级 |
| 6. 落盘存储 | COS | 结构化文本 | 转写结果对象、纪要草稿 | 秒级 |
第 4 步的耗时是最常被问到的:一段一小时的会议录音,通常几分钟就能出结果,不用干等到纪要截止那一刻。我们周五例会,录音传完我去倒杯水,回来结果已经躺好了。
提交转写请求时有几个参数值得抠一下。识别语言我们固定选中文普通话,另外开两个开关:一个是要返回句子级时间戳(纪要定位靠它),一个是开启标点恢复(不然拿到的是一串没标点的字,后处理要多写不少正则)。音频格式那栏填的是预处理后的统一格式(2.4 节),格式和采样率必须和实际文件一致,不然识别质量会莫名其妙掉一档。
还有一个小细节值得提:提交任务时的音频地址,我们传的是对象在 COS 里的可访问地址,而不是把文件二进制塞进请求里——后者对一小时的大文件完全不现实,前者让识别服务自己去拉。地址有效期要注意,用带临时鉴权的地址时,过期了任务会提交失败或拉取失败,所以我们一律给足够长的有效期或用稳定地址。这一步看着不起眼,却是首跑失败记录里“任务提交被拒”那行的根源。
哪些会议适合离线
不是所有会都值得实时。反面例子是我们有次头脑风暴会开了实时转写,大家盯着屏幕看字幕,发言节奏完全被打乱。三种典型场景:
| 场景 | 特点 | 为何适合离线 |
|---|---|---|
| 周例会 | 固定节奏、议题明确、纪要会后发 | 不需要当场看字,会后几分钟出结果足够 |
| 跨部门评审 | 时长两三小时、发言人数多 | 长录音离线更稳,不用一直占着长连接 |
| 培训分享 | 内容偏讲授、需要逐字稿存档 | 离线结果完整度更高,还能反复回查 |
| 客户访谈 | 只想留下文字记录、不便现场投屏 | 事后整理成纪要,现场不分心 |
而像全员大会这种需要当场在大屏确认决议的场子,我们后来才补上实时(3.2 节)。
一份录音的完整时间线
抽象表格说完了,给一个具体案例。上周一次 52 分钟的周例会,录音文件 48 兆字节,全链路各环节实际耗时:
| 环节 | 实际耗时 | 备注 |
|---|---|---|
| 客户端直传上传 | 11 秒 | 走 COS 直传(2.2 节),内网上行约 4 兆每秒 |
| 触发云函数 | 不到 1 秒 | 上传完成事件几乎即时 |
| 任务排队 | 约 20 秒 | 白天提交多,晚间基本不排队 |
| 异步识别 | 3 分 40 秒 | 约为音频时长的零点几倍 |
| 取回并写入结果桶 | 2 秒 | 全文 9000 多字,加时间戳约 40 千字节 |
也就是说,从会议结束到逐字稿躺在存储桶里,总共四分钟出头。我们给纪要的承诺是“会后 15 分钟内收到短信链接”,中间留给纪要提取和人工校对,时间一直很充裕。
超长录音怎么处理
有个坑差点漏掉:单次识别任务对音频时长有上限。我们平时的会一小时封顶,但年初一次全天战略会录了将近四个小时,直接提交被拒了。解法不复杂:上传后按静音段把长录音切成多份,每份单独提交识别任务,全部回来后按时间戳顺序拼接。注意每份返回的是相对该片段开始的时间戳,拼接前要加上各片段在原文件中的起始偏移做一次校正,不然纪要里的时间点会全错。校正之后按时间排序合并,逐字稿几乎无痕。
切片这步有个偷懒技巧:别等转写阶段才切,预处理(2.4 节)做音量归一时就可以顺便按静音切。静音阈值要调,会议室背景噪声不小,阈值设太高会把正常停顿也切了,把一句话切成两半再拼回来,断句会变得很怪。
回调设计:上传→触发→取结果
用 COS 直传(2.2 节)之后,转写串联是我写的第一个完整云函数流程,整体思路是事件驱动而不是定时轮询:
- 客户端把录音直传到 COS 的原始音频桶。
- COS 的上传完成事件触发云函数,函数拿到对象键和存储桶地址。
- 函数用音频对象地址调 ASR 提交识别任务,拿到任务 ID,写进一张待办表(我们存在数据库里,量小的话写文件也行)。
- 我用了轮询而不是等服务端回调——回调需要外网可访问的接收地址,内部小工具不想再开一个入口:第二个函数每分钟扫一次待办表,查询任务状态,完成了就把全文文本拉回来,写进转写结果桶,再接着触发后面的纪要提取。
这套结构的好处是每一步都可重跑:转写失败就任务重试,不影响已上传的音频;纪要提取失败也不影响转写结果。重试也做了分层:任务查询失败重试三次就告警,识别任务本身失败则记录原因并通知我,不无限重试——识别失败往往是音频本身有问题,重试一百次也一样。云函数的事件触发和超时重试细节,在 腾讯云实战手记 里有更系统的讲法,我第一次写 SCF 就是照着那本调通的。
首跑失败的排查记录
第一次跑通整条链路那天我记得很清楚,因为返回的是一串乱码似的文本,重复音节特别多。前后排查了两个小时,最后定位到两个问题,都和音频参数有关:
| 症状 | 原因 | 排查动作 | 修法 |
|---|---|---|---|
| 文本全是重叠的重复音节 | 录音是双声道,识别按单声道处理 | 查文件属性,声道数对不上 | 预处理统一转单声道 |
| 整段识别质量断崖式下跌 | 采样率是 44.1k,按 16k 处理 | 对比预处理前后的采样率 | 上传前强制重采样到 16k |
| 录音被截成两半才成功 | 分片续传没合并完整文件 | 比对源文件和上传后文件大小 | 修分片合并逻辑(2.3 节) |
| 偶发任务提交被拒 | 音频对象地址带了临时鉴权参数且已过期 | 单独试该地址访问 | 用稳定地址或刷新鉴权 |
排查这类问题的顺序我总结为三条:先看输入参数(声道、采样率、格式),再看链路是否完整(文件有没有传全),最后才怀疑识别服务本身。前两步能解释绝大多数莫名其妙的失败,真正识别服务挂了的次数,我们一年里一只手数得过来。
预处理环节(2.4 节)统一强制转成单声道 16k 之后,我又加了一道硬校验:上传前检查文件的声道数和采样率,不符合就自动转,转不了就告警。这道校验上线后,识别异常的告警基本消失了。
转写结果的字段含义、时间戳怎么用在纪要里,接着看 3.3 节。如果音频归档想留在本地而非云端,可以参考 NAS 家庭服务器实战里的方案。
离线转写常见报错速查
跑了一年多,离线转写遇到的报错我归了一张速查表,新来的同事照着这张表就能处理大部分告警:
| 报错现象 | 八成是 | 处理动作 |
|---|---|---|
| 提交任务被拒 | 音频时长超单任务上限 | 走切片流程分段提交(见上文) |
| 提交被拒但时长没超 | 音频格式参数和实际文件不符 | 核对声道、采样率、格式三件套 |
| 任务长时间不返回 | 任务排队或内部异常 | 待办表超过阈值未完成就告警人工看 |
| 返回文本为空 | 音频几乎全是静音或文件损坏 | 播放原文件确认,重新采集 |
| 文本含大量重复音节 | 声道不对 | 重新走预处理 |
这张表的价值不在技术多深,在于新人不依赖我也能值班。小团队工具想活下来,关键是流程不绑在一个人身上。
转写结果交给谁
离线转写的结果落盘之后,工具的活才刚开始:逐字稿要交给大模型做纪要提取(第四篇),时间戳要挂进纪要的每一条决议,低置信度句子要进校对清单。分段交给后面的环节是基于一个设计原则——转写这一步只干转写的事,不做任何业务判断:不删句子、不改措辞、不挑重点。识别引擎给什么,原样存什么,所有润色都在下游。这样做的好处是转写结果可以反复用:这次提取纪要,下次做培训剪辑,再下次做季度归档检索,都不用重跑识别。
延伸阅读
- 腾讯云实战手记:云函数事件触发与 COS 回调的系统性写法。
- AI 智能体开发实战:转写文本之后怎么用大模型提取待办。
- DeepSeek 工具链:纪要文本处理的模型与工具选型。
