☰
腾讯云AI语音识别:从零打造会议纪要自动化小帮手
2026/10/20 18:08:53 网站建设 项目流程

每次开完一场两小时的会议,我在会后还要再花两小时整理录音、抠重点、开待办清单。时间久了我就意识到,真正占用精力的不是“开会”,而是“把会上的话变成可执行的任务”。这其实就是我做“用腾讯云 AI 语音识别打造会议小帮手”这个项目的初衷:让机器先把语音转成文字,我再把精力花在“判断哪些话重要”上,而不是“逐字听录音”。这篇文章想分享的就是我从零搭这套工具的完整过程,包括为什么选云服务而不是本地模型、音频预处理怎么做、核心 SDK 怎么调通,以及上线后踩过的一些质量坑,适合正在做会议纪要自动化、知识管理或者内容归档的同学参考。

1. 从痛点出发:会议小帮手到底要解决什么问题

1.1 会议记录真实的三大痛点

做这个项目之前,我统计了一下团队一周的开会时间:平均每人每周要开 6 到 8 场会,其中至少一半是没有结构化纪要的。所谓的“纪要”,就是散落在各人笔记本里的关键词,真到月底复盘的时候,谁也说不清当时决定的细节。

第一个痛点是整理耗时。一小时的真实会议录音,人工转写加润色至少要两小时。如果把“谁说的、什么时候说的、最后定了什么”这些附加信息也算进去,三小时打底。第二个痛点是信息丢失。开会时不可能逐字记录,大家说着说着就容易跳话题,没有录音文字稿的话,很多决策依据就丢了。第三个痛点是跟进困难。会上说了“下周给结果”,但这句话埋在二十分钟的讨论里,事后要把它挖出来当成一条待办,还得靠人肉搜索。

所以我要做的“会议小帮手”,核心就是解决三件事:把录音变文字、把文字切结构、把结构提任务。技术选型上,我选择了腾讯云 AI 语音识别作为整个转写链路的中枢,不在本地部署语音识别模型,理由会在下一节展开。

1.2 为什么选腾讯云 AI 语音识别,而不是本地开源模型

动手之前我认真对比过两条路:一是本地跑开源语音识别模型,二是直接调用云厂商的语音识别 API。开源方案的优势是数据不出内网、没有按量计费的压力,但它的隐性成本很高。

首先是准确率的差距。会议场景下有大量口语化表达、打断、重叠说话、专业术语,开源模型在这些场景的识别效果普遍不如商业云服务,尤其在中文普通话的标点预测、数字转换、常见姓名识别上差距明显。其次是部署和维护成本。跑一个像样的语音识别模型至少需要一张像样的 GPU 卡,模型迭代、音频格式适配、推理加速这些都要自己搞,我一个人维护不起。第三是工程链路。云服务把鉴权、并发调度、结果回调这些基础设施都做好了,本地方案这些全都得自己写。

腾讯云 AI 语音识别在这条链路里最适合我的点,是它同时支持实时语音识别和录音文件识别。我的场景是会后整理,所以用的是录音文件识别,也就是把完整录音丢上去,异步拿到转写结果。接口逻辑清晰,还有现成的 Python SDK,基本是一天能接通的水平。当然云服务也有它的代价:音频数据要上传到服务端,所以对敏感会议内容要做好脱敏和留存策略,这部分我在后面专门讲。

1.3 小帮手的职责边界:我只让它做这三件事

很多做会议工具的人容易犯一个毛病,就是什么都往里塞。我一开始也想过让这个工具自动生成会议评分、自动判断谁发言最多、自动跟踪每项待办闭环。后来想明白了:工具不是越智能越好,而是越可靠越好。

我最终把职责收敛成三件事。第一件事是“录完即转”:会议结束后上传录音文件,定时轮询识别状态,得到带时间戳的完整文字稿。第二件事是“按议题切分”:用转写结果里的时间戳和关键词,把一小时的长文本切成若干议题段落,方便回看。第三件事是“输出纪要草稿”:把转写全文压缩成“结论 + 待办 + 负责人 + 截止时间”的四段式纪要,再由人去确认。

这三件事有一个共同特点:都是确定性的、可验证的。我不需要它理解语义里的微妙情绪,只需要它把语音变成准确文字,再把文字按规则整理好。后面的开发也都是围绕这三件事展开的。

2. 开工前的准备工作:账号、密钥与音频规范

2.1 开通语音识别服务与密钥管理

腾讯云语音识别服务的开通流程不算复杂,但如果你想直接复用我的经验,有几个细节值得先说。

第一步是在控制台找到语音识别产品页,开通“录音文件识别”服务。开通后需要一对 API 密钥,也就是 SecretId 和 SecretKey,SDK 鉴权全靠它们。这里有个我踩过的坑:一开始图省事,我直接用了主账号的密钥写在代码里,后来发现团队其他人接手脚本时不方便做权限回收。建议在访问管理里单独建一个子账号,只授予语音识别相关的权限,密钥单独下发。这样即使密钥泄露,影响范围也可控。

密钥配置我建议放在环境变量里,而不是写死在代码仓库。我当时的做法是建一个.env文件,脚本启动时自动读取,同时把.env加入 git 忽略列表。密钥本身不复杂,但养成这个习惯能省掉后面很多麻烦。

2.2 音频规格比想象的更讲究

接通 API 之前,最容易出问题的环节其实是音频文件本身。会议录音来源五花八门:手机录音笔、在线会议软件导出、电话会议录音,格式和编码参差不齐。而语音识别服务对音频格式、采样率、编码方式、声道数都有明确要求,不满足就会报错或者识别率骤降。

我总结出一套“音频三大纪律”:

第一,格式统一。最好统一转成 wav 或者 pcm,这两种格式在服务端解析时最不容易出幺蛾子。mp3、m4a、amr 这些压缩格式虽然部分接口支持,但远不如 wav 稳。第二,采样率对齐。会议语音识别一般要求 16kHz 或 8kHz 采样率,其中 16kHz 的识别效果最好。如果原始录音是 44.1kHz 的,建议重采样到 16kHz,既能保证识别率,也能降低传输带宽。第三,声道合并。多声道文件要先合并成单声道。道理很简单:识别接口按单声道处理语音,双声道数据如果不合并,会出现声音叠混、时间戳错乱的问题。

我平时处理音频的流程是:拿到录音文件,先用工具看它的编码信息,再统一转成 16kHz 单声道 wav,最后才交给识别接口。这不是多余动作,是保证转写质量的第一道防线。

2.3 ffmpeg 转码实操

音频预处理我用的工具是 ffmpeg,基本是处理音频视频的标配了。常用的几个命令我给一个参考版本:

# 查看音频详细信息 ffprobe meeting.mp3 # 统一转成 16kHz 单声道 wav ffmpeg -i meeting.mp3 -ar 16000 -ac 1 -codec pcm_s16le meeting.wav # 如果音频太长,按 30 分钟一段切割 ffmpeg -i meeting.wav -f segment -segment_time 1800 -c copy meeting_part_%03d.wav

几个参数的含义说一下:-ar 16000表示输出采样率 16kHz,-ac 1表示单声道,-codec pcm_s16le表示 16 位小端 PCM 编码,这是最常见的 wav 编码格式。分段切割是因为单次识别任务对音频时长有上限,超长录音切段处理更稳。

转码之后建议抽查几段音频,确认没有变成“沙沙声”或者音量过低的情况。会议录音往往人声动态范围很大,有人说话声音小,有人爱吼,统一转码后如果发现某段声音太小,还得做一次音量归一化,命令是:

ffmpeg -i meeting.wav -af loudnorm=I=-16:TP=-1.5:LRA=11 meeting_norm.wav

这个归一化不会改变内容,但能让人声部分的响度更均匀,后面识别时不容易出现整段漏识别。

3. 核心开发链路:上传录音、异步识别与结果回捞

3.1 SDK 初始化与鉴权方式

腾讯云语音识别的 Python SDK 安装比较简单,用 pip 装对应的包即可,具体的包名以官方文档为准。初始化客户端的核心逻辑是先创建凭证对象,再创建语音识别客户端。下面是我当时写的一个参考代码:

import os from tencentcloud.common import credential from tencentcloud.asr.v20200623 import asr_client, models # 从环境变量读取密钥,避免硬编码 secret_id = os.environ.get("TENCENTCLOUD_SECRET_ID") secret_key = os.environ.get("TENCENTCLOUD_SECRET_KEY") cred = credential.Credential(secret_id, secret_key) # 这里的地域参数要换成你实际开通服务的地域 client = asr_client.AsrClient(cred, "ap-guangzhou")

这段代码看起来简单,但有一个值得注意的地方:SDK 的请求和响应都是通过 models 模块里的 XxxRequest 和 XxxResponse 对象封装的,所以后面每一步都要先构造 Request 对象,再调用客户端方法。记得在写代码前先确认当前 SDK 版本里主要的接口字段名,不同版本字段略有出入,以官方文档为准。

3.2 创建识别任务:参数选择背后的小心思

录音文件识别的调用逻辑是异步的:第一步创建任务,拿到 TaskId;第二步拿着 TaskId 去查询识别状态;第三步从结果里拉文本。创建任务这一步的参数非常关键,直接影响识别质量。我当时最关心的几个参数是引擎模型类型、声道数、是否开启说话人分离、是否需要时间戳。

引擎模型类型要选匹配会议场景的中文普通话模型。这个参数选错,识别率会有肉眼可见的下降:比如拿通用短句模型去跑长会议,断句和标点会乱。声道数必须写 1,因为我们预处理时已经合并成单声道了。说话人分离功能开启后,返回结果里会区分不同说话人编号,对会议纪要有用,但它也有代价——会增加处理时间,而且说话人数如果配置不对会切分混乱。时间戳必须开,没有时间戳,后面切议题、定位关键内容都是空谈。

创建识别请求的代码大致是这样的:

def create_task(client, audio_url): req = models.CreateRecTaskRequest() req.EngineModelType = "16k_zh" # 中文普通话,16k 采样率模型 req.ChannelNum = 1 # 单声道 req.ResTextFormat = 1 # 返回带词级别时间戳的文本 req.SourceType = 0 # 音频来自 URL 方式 req.Url = audio_url # 音频所在的完整 URL req.ConvertNumMode = 1 # 数字转换为阿拉伯数字 req.SpeakerNumber = 0 # 不限制说话人数 resp = client.CreateRecTask(req) return resp.TaskId

创建任务成功后会返回 TaskId,这个 ID 是后续查询状态的唯一凭证。记得把 TaskId 落到日志里,一旦任务失败还能用接口查到失败原因。

3.3 任务状态轮询:节奏、超时与断点续查

任务创建之后不会立刻出结果,音频越长等待越久,所以需要一个轮询机制。我采用的策略是每 5 秒查一次状态,连续查到一个成功态之后停止,失败态则立刻拉取错误信息。

查询与轮询的参考实现:

import time def wait_for_task(client, task_id, timeout=600): start = time.time() while time.time() - start < timeout: req = models.DescribeTaskStatusRequest() req.TaskId = task_id resp = client.DescribeTaskStatus(req) if resp.Status == 2: # 识别完成 return resp.Result if resp.Status == 4: # 任务失败 raise RuntimeError(f"识别失败: {resp.ErrorMsg}") time.sleep(5) raise TimeoutError("轮询超时")

这里有一个我在实际运维中总结的经验:轮询的超时时间不要写死,最好根据音频时长动态计算。我的做法是按“音频分钟数 x 2 + 60 秒”作为超时基线,因为识别耗时和音频长度是强相关的,否则一个半小时的会议录音很容易因为固定超时 600 秒而误报失败。

如果进程在中途挂了,不要慌,TaskId 是唯一标识,重新起一个脚本拿同一个 TaskId 继续查询即可,整个流程天然支持断点续查。这也是异步任务的好处。

3.4 把转写结果加工成会议纪要草稿

拿到识别结果后,返回的 JSON 结构里包含全文文本和每一句话的时间戳信息。我这步的逻辑是先把原文按时间戳分段,再基于正则和关键词提取“结论、待办、负责人、截止时间”四类信息。

具体的加工思路是这样的:先把全文按“发言人 + 时间戳 + 文本”的格式整理成结构化列表;然后扫描文本中的动作词,例如“跟进、负责、确认、下周三之前、明天内”,把这些句子单独标记成候补待办;最后以这些候选句子为锚点,往前和往后各捞上下文,组装成一条带出处的纪要条目。

这一步不需要太复杂,用规则和正则就够了。这时候你会发现之前开时间戳的好处:每条纪要都能回溯到原始录音的某个时间点,确认细节时直接跳转,而不是满篇搜关键词。

4. 真实会议里的质量调优:这几件事比调参数更管用

4.1 录音环境与麦克风摆位对识别率的隐形影响

接通接口之后你会很快发现一个事实:识别准确率的瓶颈往往不在算法,而在录音。腾讯云 AI 语音识别即使模型再好,也扛不住会议室里的混响和多人同时说话。

有一次我用手机放在桌面中央录团队例会,三米外的人说话内容经常识别成乱码。后来换了个领夹麦克风给发言人佩戴,同样的环境和接口,转写错误率锐减。麦克风摆位对识别率的影响可以用一个直观类比来理解:把会议室的十个人想象成合唱团,如果麦克风放在舞台边缘,你只能听清主唱;放在舞台中央,每个人都能兼顾到。

如果你的会议场景是多人围坐,建议优先采用“全向麦克风”加“靠近中间位置”的方案。如果条件限制只能用手机,就把它放在会议桌的正中央,周围不要有坚硬光滑的反射面,也尽量不要靠近窗户和空调出风口。

4.2 说话人分离:开了不等于能用,输出要二次加工

刚开始我用录音文件识别的时候,对“说话人分离”功能期待很高:自动分好谁说了哪句,纪要不就能直接标发言人了吗?实测发现,自动分离的结果只到“说话人编号”的粒度,不会告诉你编号对应的是哪个真人。

比如结果里会出现“说话人 1 说:这个需求我来跟进”“说话人 3 说:好”,但“说话人 1”到底是谁,需要你自己通过上下文去推断。我的做法是:在会议开场阶段预设一段自我介绍,然后根据音色特征的先后顺序把编号映射到人名,实际上就是半手工的标注。如果你的会议经常有大量外部人员参加,这一步逃不掉。

另外,如果会议里有两个人经常同时开口,说话人分离会把这段内容切得很碎,甚至误判成第三个人。这种情况我建议在设置说话人上限时留一点余量,同时后期合并相邻编号的短片段,规则是“同一编号连续出现间隔不超过 5 秒就合并”。

4.3 热词和自定义词库:把“黑话”和“人名”救回来

这是整个调优里投入产出比最高的一步。会议场景里一定会出现产品代号、人名、英文缩写,而这些内容语音识别默认不熟。比如我们项目内部常说的“小扳手流程”,第一次转写成了“小班手”,这就是没有热词时的典型结果。

腾讯云 AI 语音识别支持配置热词表,把高频人名、系统名、产品专有名词加进去之后,识别结果会明显向这些词汇倾斜。使用热词表有一个技巧:热词要写你“实际念出来的发音”,而不是书面拼写。比如系统名是“TP-3000”,大家开会都会念成“TP三千”,热词表里两个都不放的效果是不一样的,我实测写“TP三千”比写“TP-3000”更有效。

自定义词库和热词表是两个层面的东西:热词表偏识别倾向,词库偏结果替换。我会把容易出现同音误判的词放进词库里,例如把“前端”和“全端”这类同音词绑定到正确的业务语境。调参之外,这大概是对准确率提升最直接的方法。

4.4 一次两小时管理例会的转写复盘

调优前后我专门做了一次对照测试,选了一段两小时的管理层例会录音,内容涉及季度目标、人员分工、跨部门协作,说话人总共七个,中间有打断和争论。同样的录音,分别用“默认参数”和“完整调优方案”跑了一遍,结果差异非常明显。

指标默认参数完整调优方案
整体准确率大约 82%大约 93%
人名识别误判7 处1 处
数字识别错误5 处1 处
打断段落丢失明显轻微
转写后人工修正时间约 50 分钟约 15 分钟

需要说明的是,这个数据只代表我的录音环境和会议类型,不能算普适标准。但它验证了一个规律:音频端处理、热词表配置、说话人合并规则这三件事,对可用性的提升要远远大于模型参数本身的微调。我后来再处理新的会议录音,基本都是按照这套固定流程来走:转码、归一化、传 URL、配热词、识别、后处理。

5. 上线半年后,我重新思考的几个问题

5.1 成本与用量:计费时长和“测试和正式混跑”的教训

语音识别按量计费,看的是音频时长,不是任务数。也就是说,一次“测试识别”和一次“正式识别”花的是同样的钱。上线初期我为了调接口,把同一段录音反复提交了十几次,月底账单出来之后,才发现测试费用占了将近三分之一。

合理做法是准备两段固定音频:一段 10 秒的极短录音用于链路连通性测试,一段 3 分钟的完整会议录音用于质量验证。链路没变的情况下,不要反复提交大数据量的音频。我在项目根目录放了一个test_audio/文件夹,里面固定那两段测试音,脚本也默认读取它们,正式使用时才通过参数指定新的音频文件。

另一个成本细节是音频的时长统计口径。因为预处理阶段我做了一次归一化,输出文件体积会变大,但计费按实际识别时长走,不会按文件体积走。不过还是要避免把一个小时的会议按两段 30 分钟提交两次,因为分段之间如果有重叠,重叠部分会重复计费。切割时用无缝切割,不保留 overlap 就不会有这个问题。

5.2 录音与转写文件的隐私存储策略

会议录音天然包含大量敏感信息,这个工具的便利性建立在“音频上云”这个前提上,所以隐私策略必须想清楚。

我的处理方式是分层隔离:原始录音文件放在只有我能访问的私有存储桶里,访问链接设置有效期,默认 24 小时失效;转写得到的文本结果在本地数据库保存,并且按会议日期和人名做脱敏占位。对外分享纪要草稿时,先跑一遍正则,把疑似手机号、邮箱地址、内部系统路径等匹配出来,替换成占位符。

留存周期上,我设置了一个 90 天自动清理脚本。超过 90 天的原始录音自动删除,只保留转写文本和结构化纪要。这样做有几个考虑:一是降低存储泄露风险,二是会议纪要的活跃参考期通常不会超过一个季度,三是真到需要回听原声的时候,90 天的窗口也足够及时处理。

5.3 从“转写工具”到“会议小帮手”:摘要、待办与归档的下一步

上线半年后,这个工具已经稳定在跑,但我对它的定位也发生了一些变化:它不是一个“语音转文字工具”,而是一个“会议信息管线”。转写只是管线的起点,真正有价值的是后面那套结构化整理和归档流程。

现在我在尝试做的一件事,是把每次会议的纪要草稿自动汇入团队知识库,按项目名、参与人、决策项打标签。这样月底复盘时,不是去翻十几个分散的文档,而是打开知识库按项目维度拉出所有相关决策。另一个尝试是摘要生成:利用转写全文的标题段落,提取每个议题段落的开头句和结束句,拼成“议题 + 结论”的迷你摘要,人工确认后直接进周报。

这些功能都不算复杂,但它们让“会议小帮手”从一个只能听写的工具,慢慢变成了一个能帮着回忆、帮着追踪、帮着归档的信息助理。如果你也要做类似的系统,我的建议是先跑通转写链路,再逐周加一个结构化处理环节,贪多容易做成一锅粥,小步迭代反而稳定。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询