腾讯云AI语音识别实战:录音转文字自动生成会议纪要

发布时间:2026/10/18 23:14:13
腾讯云AI语音识别实战:录音转文字自动生成会议纪要 1. 从一场开完就忘的评审会说起先说个真实场景。上周三下午我们团队开了一场产品评审会从两点开到快五点三小时的会信息量极其密集新版本的功能范围、三个待定的技术方案、两个需要下周验证的风险点、还有运营那边催着要的排期承诺。我坐在会议室里前半程还在认真记后半程手已经跟不上了。散会之后看自己的笔记字迹潦草到只有我自己能勉强认出来关键决策散落在各种箭头和涂改之间想复盘的时候脑子里只剩下“好像讨论过但具体结论是什么”的模糊印象。这种事情发生一次两次还能忍每周都来一次就真的受不了。于是我决定动手做个工具核心思路就是把腾讯云 AI 语音识别接进会议场景让录音自动变成文字存档再从文字里提炼出决策和待办。这个“会议小帮手”没有做得特别复杂但用到现在我的会议记录质量和复盘效率都明显上了一个台阶。这篇文章就把我这个项目的完整过程写出来包括为什么选腾讯云、核心流程怎么设计、代码怎么落地、以及我实际跑了几十场会之后踩过的一些坑。如果你是那种每周要开好几个会、记笔记永远跟不上语速、或者开完会总得靠回忆才能写纪要给同事的人这篇内容应该能直接帮你省下不少时间。不需要你有多深的编程基础我会把每一步的原理和注意事项都讲清楚你照着抄作业也能跑通。2. 选型对比为什么把目光停在腾讯云 AI 语音识别上要做会议语音转写市面上能走的方案其实不少但每个方案的适用场景差别很大。我先说结论在“长音频、中文为主、要求省心”这三个条件下腾讯云的录音文件识别接口是目前我认为性价比最稳的选择。2.1 主流语音识别方案我把能跑的试了一圈先说开源离线方案。本地部署语音识别模型这条路我之前在实验室折腾过一段时间优点是不用联网、数据不出本地但缺点是硬件门槛明显。一套识别效果过得去的模型光加载就吃掉不少GPU显存在普通办公电脑上基本跑不动。而且中文会议场景里有大量口语化表达、专有名词和多说话人重叠开源模型的默认效果说难听点就是“每个字都认识连在一起不知道在说什么”要调到能用的程度需要准备大量领域语料做微调。对于我只是想解决会议记录这件事来说投入产出比太低。再说其他云厂商的做法。市面上确实有几家提供类似的语音转写服务坦白讲基础功能都大差不差我试用下来真正拉开差距的主要是三件事长音频任务的管理方式、中文场景下的标点补齐和数字转化专业程度、以及周边生态的配合度。有些平台把长音频识别做成同步接口音频稍微长一点就超时必须自己切段再拼接拼接处还经常丢字有些平台虽然支持异步任务但中文标点恢复做得一般转写出来一整段没有断句读起来相当费劲。腾讯云这边是我最后测试的反而是最贴合我需求的。它的录音文件识别接口专门为长音频设计一次能提交最长几百分钟的任务异步处理不用我自己操心超时问题。中文引擎在标点恢复、数字转化这类细节上做得比较成熟比如“预算从两百万增加到三百万”这种口语数字转写出来直接是阿拉伯数字省掉大量后处理功夫。关键是我把一段含大量产品名和同事昵称的录音丢进去试准确率明显比另外几家高一个档位。2.2 录音文件识别接口的硬指标我特意去翻了接口文档把和自己这个场景最相关的几个参数整理了一下。这个接口提交任务时主要有几个字段需要关注参数含义我的推荐值备注EngineModelType引擎模型类型16k_zh16k采样率中文普通话模型ChannelNum音频声道数1单声道转写更稳定ResTextFormat返回结果格式1返回带句子列表和时间戳的JSONSourceType音频来源0 或 10表示URL1表示Base64上传VadSilenceTime语音活动检测静音时长1800-3000控制句子切分的力度HotwordId热词表ID按需配置用于提升专有名词识别率SpeakerDiarization说话人分离开关按会议人数开启配合SpeakerNumber使用这些参数里最有价值的是HotwordId和SpeakerDiarization前者能通过热词表大幅提升产品名、术语的识别准确率后者能把不同发言人的内容分开返回。这两个功能我在后面的踩坑章节会展开说因为它们是“能转写”和“转写好用”之间的分水岭。2.3 成本怎么算一场会到底花多少钱费用这块我刚开始也担心毕竟会开得多要是按分钟计费很贵项目就做不下去。查了计费方式之后发现录音文件识别是按音频时长计费不是按返回文字量计费折算下来一场一小时的会议成本基本就是一次音频识别的费用完全在可接受范围内。对比一下请一个速记员或者买一套商用转写软件的订阅费这个方案便宜太多了。我还特意算过一笔账假设一个团队每周开5个小时的会议一个月下来大约20小时音频折算成费用几乎可以忽略不计。但省下来的时间非常客观——过去我开完会至少花半小时整理纪要现在自动转写加后处理五分钟内就能拿到一份带时间戳的完整文档。这种投入产出比我觉得值得给每个人都安利一下。3. 完整流程拆解一段录音如何变成一篇会议纪要整个会议小帮手的核心链路可以拆成四步拾音、预处理、识别、后处理。前面两步很多人会忽略但它们恰恰决定了最终识别率的上限。录音质量如果不行后面调用再好的识别接口也会打折扣。3.1 拾音端设备与摆放直接影响识别率我最早直接用手机放在会议桌中间录音效果说实话一般。圆桌会议还好要是长条桌坐在远端的人声音会被严重衰减转写出来经常缺句子。后来换了带麦克风阵列的录音笔放在桌子中央情况好了很多。我的经验是如果条件允许尽量用带多麦克风阵列的设备它对远场声音的收集能力是普通手机麦克风比不了的。设备摆放位置也有讲究。会议室如果有投影仪或空气净化器这种持续噪声源录音设备要尽量远离它们。另外提醒一句如果会议中有人频繁翻纸质材料或者敲键盘声音会被一并收进去VAD阶段有可能会把这些声音当成有效语音切出来。这种情况不用太焦虑毕竟我们做的是会议纪要辅助工具不是录音笔质检杂音只要不影响主要语音路径就问题不大。3.2 音频预处理采样率、编码和分段录音文件不是拿来就能直接丢给API的预处理这步不能跳。音频格式上我一般都用ffmpeg转成16kHz采样率、单声道、WAV或MP3格式。语音识别接口对采样率有明确要求16k中文模型就得配16k采样率的音频拿44.1kHz的高品质音乐采样率去提交反而是浪费接口内部也会做重采样不如我们在本地一步到位。转码命令很简单我自己是这样用的ffmpeg -i meeting_original.m4a -ar 16000 -ac 1 -f wav meeting_16k.wav这个命令的意思是把输入文件强制转换为16k采样率、单声道输出WAV格式。中间那个-ac 1很容易漏如果忘记设置转出来的音频还是双声道ChannelNum参数就得跟着调成2不然识别时声道对不上结果会乱。分段则要看场景。腾讯云的录音文件识别本身支持长音频异步处理我一般不动它让它自己处理整段音频。但如果是现场会议想边开边出文字那就得走实时语音识别接口那是另一套调用逻辑。我的项目是会后整理所以用异步长音频方案就够了处理起来也稳。3.3 异步识别任务的生命周期提交、轮询与拉取录音文件识别接口的调用模型是异步的这个设计一开始容易让新手懵提交任务后拿到的不是识别结果而是一个TaskId然后你得不停去查这个任务的执行状态直到它成功或失败。生命周期大概是这样的提交任务后返回TaskId这时任务进入排队或处理中状态处理完成后状态变为成功此时响应体里会带一份JSON格式的识别结果如果处理中失败也会有明确的状态码返回。整个过程对一小时音频来说一般两三分钟能出结果长音频可能需要更久。我的轮询间隔设的是10秒不要太频繁避免无谓的请求。这里说个我个人的习惯轮询逻辑一定要写超时和最大等待时间不然遇到网络抖动或者服务端任务堆积客户端可能无限等下去。我在核心代码里设了900秒上限超出就主动报错宁可重新提交一次任务也不让脚本挂在那里。4. 核心代码落地把链路变成能跑的工具原理讲清楚了动手写代码的过程相对就顺了。我用Python来写这个会议小帮手因为腾讯云官方有Python SDK调用起来最省事而且后处理文本的时候Python处理JSON也方便。整个项目不需要很复杂的架构一个脚本文件加一个依赖清单就够了。4.1 环境准备与依赖安装先装SDK这一步没啥花头。pip install tencentcloud-sdk-python-common pip install tencentcloud-sdk-python-asrSDK安装好之后还需要在环境变量里配置访问密钥。这几个密钥值在腾讯云控制台的访问管理里可以生成。我强烈建议不要把它们硬编码在脚本里而是通过环境变量传入免得代码不小心泄露出去。export TENCENTCLOUD_SECRET_ID你的ID export TENCENTCLOUD_SECRET_KEY你的KEY4.2 会议小帮手的核心类识别任务封装核心逻辑就是提交任务、轮询状态、拉取结果。我封装了一个类把创建任务和等待结果串起来。下面这段代码是整个工具的主干线我加了比较详细的注释。import os import json import time from tencentcloud.common import credential from tencentcloud.common.profile.client_profile import ClientProfile from tencentcloud.common.profile.http_profile import HttpProfile from tencentcloud.asr.v20190614 import asr_client, models class MeetingHelper: def __init__(self, regionap-shanghai): cred credential.Credential( os.environ.get(TENCENTCLOUD_SECRET_ID), os.environ.get(TENCENTCLOUD_SECRET_KEY), ) http_profile HttpProfile() http_profile.endpoint asr.tencentcloudapi.com client_profile ClientProfile() client_profile.httpProfile http_profile self.client asr_client.AsrClient(cred, region, client_profile) self.hotword_id os.environ.get(MEETING_HOTWORD_ID, ) def create_task(self, audio_url): req models.CreateRecTaskRequest() req.EngineModelType 16k_zh req.ChannelNum 1 req.ResTextFormat 1 req.SourceType 0 req.Url audio_url req.ConvertNumMode 1 req.FilterPunc 0 if self.hotword_id: req.HotwordId self.hotword_id resp self.client.CreateRecTask(req) return resp.Data.TaskId def wait_result(self, task_id, max_wait900): req models.DescribeTaskStatusRequest() req.TaskId task_id deadline time.time() max_wait while time.time() deadline: resp self.client.DescribeTaskStatus(req) status resp.Data.Status if status 2: return json.loads(resp.Data.Result) if status 3: raise RuntimeError(f识别任务失败: {resp.Data.ErrorMsg}) time.sleep(10) raise TimeoutError(等待识别结果超时) def recognize(self, audio_url): task_id self.create_task(audio_url) print(f识别任务已提交: {task_id}) return self.wait_result(task_id)这段代码里有两个容易被忽略的地方。一个是FilterPunc 0我故意不过滤标点因为标点符号对后续做摘要断句有帮助另一个是ConvertNumMode 1这个参数会把口语数字转成阿拉伯数字比如“三百万”变成“300万”后续做数据统计分析会方便很多。4.3 从流水文本到结构化纪要的后处理接口返回的JSON在ResTextFormat1时包含一个SentenceList里面是每个句子的开始时间、结束时间、说话人ID如果开说话人分离的话和文本内容。我的后处理脚本会把句子按时间顺序拼成完整文本同时按说话人ID分桶再按60秒一个区间切块生成带时间戳的分段纪要素材。def post_process(result): sentences result.get(SentenceList, []) full_text .join(s[Text] for s in sentences) speakers {} for s in sentences: sid s.get(SpeakerId, 0) speakers.setdefault(sid, []).append(s[Text]) timeline [] current_start 0 current_end 0 current_text [] for s in sentences: if not current_text: current_start s[BeginTime] current_end s[EndTime] current_text.append(s[Text]) if current_end - current_start 60000: timeline.append({ start: current_start, end: current_end, text: .join(current_text), }) current_text [] if current_text: timeline.append({ start: current_start, end: current_end, text: .join(current_text), }) return { full_text: full_text, speaker_texts: speakers, timeline: timeline, }这样处理的输出已经可以直接作为会议纪要的底稿了。我在实际使用中会再根据发言片段的时间戳快速定位某段讨论比如“这个结论大概是在第28分钟左右出现的”回听录音确认的时候非常方便。5. 实测踩坑VAD、热词表和说话人分离代码能跑通只是第一步真正让它“好用”还差得很远。我连续用这个工具处理了几十场会议录音识别质量参差不齐后面复盘才发现问题大多出在三个地方。5.1 VadSilenceTime 到底要不要调VAD参数控制的是“间隔多久没人说话就认为这句话结束了”。默认值是几百毫秒到一两秒这个量级短对话场景很好用但放到会议场景就容易出问题。我第一版直接用默认值结果是一个人连续讲很长一段时中间偶尔停顿一下换口气VAD就把这段切成了好几个短句返回的句子列表碎得不行后处理拼接虽然能拼回去但每个句子的时间戳变得没有参考价值。后来我把VadSilenceTime调到了2000到3000毫秒断句明显更接近“一个人完整表达一个意思”的粒度。但这个值也不是越大越好如果两位参会者对话节奏紧凑A刚说完B马上接上过大的静音阈值可能把两个人的话合并成一句说话人分离的判断也会出错。我的建议是先用默认值识别一版看看句子粒度是否符合预期再根据会议风格微调。这里有一个经验常规的“快问快答”式评审会建议用1500毫秒左右偏演讲、报告式的会议可以放宽到3000毫秒。没有绝对正确的参数只有和场景匹配的参数。5.2 热词表让产品名、术语不再被“写错”最让我头疼的是专有名词。我们的项目里有个功能模块叫“X-Bridge”这个英文词在默认模型下经常被识别成各种莫名其妙的中文组合而且每次错的还都不一样。产品名这种词错了可能还能根据上下文猜出来但如果是数字ID或者代码命名错了就真的找不回来了。解决办法是热词表。在控制台的语音识别产品里可以创建热词表把项目里常见的产品名、同事昵称、技术术语都填进去每种词可以配一个权重权重越高识别时越优先按这个词匹配。热词表创建完成会生成一个ID把这个ID填到HotwordId参数里就行。我总结的填表经验是中文词条效果比英文词条好短词条效果比长词条好。太长的一句话需求描述建议拆成几个词组分开填尽量避免填整句。热词表不是一次性的事每开几次会发现某个词被写错了就追加进去它是可以持续迭代的。5.3 说话人分离多人会议的角色归属没那么简单会议纪要只到“谁说了什么”还不够最好能知道是哪位同事说的。腾讯云的接口支持说话人分离开启SpeakerDiarization并设置SpeakerNumber后返回的句子里会带SpeakerId字段。我刚开始天真的以为它会自动识别出每个人叫什么名字实际用下来发现它只做声纹聚类——也就是说它能把不同的音色区分开但并不知道谁是谁。比如一场会有5个人说话它可能会返回5个SpeakerId但具体哪个ID对应会议室里的哪个人需要自己建立一个映射。我的做法是会议前半段录音里请每个人轮流说一句话作为“注册样本”然后根据时间顺序把SpeakerId和发言人对应上。这个方法听起来土但非常管用。还有个坑就是SpeakerNumber这个参数人多的会议如果设置的人数比实际说话人数少声纹聚类容易把不同的人合并成一个ID设置多了又会把同一个人在不同时段的音色差异拆成两个人所以这个值要稍微留点余量宁可多不可少。6. 让工具真正进入日常会议三个改造方向目前这个会议小帮手已经能稳定输出带时间戳、带说话人分组的转写文档但离“小帮手”这个定位还有距离。把它从“语音转写工具”升级成“会议记录助理”我觉得有三个改造方向很值得做。6.1 与日历联动会议结束三分钟收到纪要最实用的一步是接入日历和通知渠道。我的方案是写了一个定时任务每天会议开始前检查日历中的会议列表会议结束时间一到就自动去拉取云存储里的录音文件跑一轮识别和后处理最后把生成的纪要文本推送到团队聊天工具。这部分没有用太复杂的框架就是基础的定时任务加文件监听。录音文件的获取我做了个约定会议室的录音笔连上电脑后会自动把文件传到指定的COS路径命名格式包含会议ID这样定时任务扫目录就能精准知道要处理哪个文件。自动化程度高了之后最直接的改变是参会人不用再开口问“纪要什么时候出”纪要自己会出现在每个人面前。6.2 二次提炼从转写文本里挖出决策和待办纯转写文本不等于会议纪要它只是材料。真正值钱的信息是决策和待办而这些信息淹没在大量的对话里。我在后处理环节加了一个轻量级的提炼逻辑用规则去匹配常见决策句式比如“那就定了”“我们确认一下”“下周三之前完成”同时结合时间戳上下文把这些句子单独拎出来放在纪要最前面。这个方案比单纯的关键词匹配稍微聪明一点因为它是按句子的上下文位置和说话人分组的不会把闲聊里的“好像定了”误判成决策。如果以后需要更高质量的结构化信息还有一个思路是把完整转写文本丢给大模型做二次归纳让模型帮忙输出“讨论主题、主要分歧、最终结论、行动项”四个板块。我在部分非敏感的内部会议上试过效果确实好但要注意数据隐私的边界。6.3 隐私与安全录音数据的边界这一点必须单独说。会议录音属于敏感数据整理完纪要之后录音文件的保存和销毁策略要提前想清楚。我的做法是转写完成且纪要确认无误后原始音频默认在七天后自动清理只有在需要回溯细节时才选择保留。开会前也会提前告知参会者有录音和自动转写让大家知情。如果是涉密程度更高的会议更稳妥的方案是把服务部署在私有化环境音频文件不走公网对象存储直接用Base64上传给识别接口。接口本身返回的结果也可以加密存储。别看这些都是“额外工作量”在这个场景里安全和便捷同等重要少了这一层我不敢把这个工具推广给全团队用。最后再分享一个小技巧项目跑了一段时间之后我发现自己对“会议小帮手”最大的依赖反而不是转写本身而是它的回看功能。以前开会开完就完了很多细节当时没注意之后也没法翻回去查现在每次生成纪要时都会自动带一条时间戳索引哪句话是哪位同事在什么时间点说的一目了然。如果你也要做类似工具我的建议是不要一上来就追求大而全。先用最简单的链路把录音转写跑通用一个月左右积累真实会议数据你会发现哪些参数需要调、哪些后处理规则值得加都会自己冒出来。等基础功能稳定了再按我的三个方向逐步迭代。工具是给自己用的顺手比花哨重要得多。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询