恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
用腾讯云语音识别打造会议纪要小帮手:录音转写、说话人分离全攻略
首页
资讯中心
/
用腾讯云语音识别打造会议纪要小帮手:录音转写、说话人分离全攻略
用腾讯云语音识别打造会议纪要小帮手:录音转写、说话人分离全攻略
发布时间:2026/10/18 19:37:37
不开会不知道一开会就发现人的耳朵其实没那么靠谱。连续两小时的远程会议前半小时还精神后半小时就开始走神等反应过来重点早就过去了。更要命的是会后整理纪要这件事谁做谁知道——回放录音、逐句听写、归纳决议一份两小时的会议录音整理出三千字纪要普通人要折腾两三个小时。我就一直在想能不能让AI帮我干这个活。后来用了腾讯云的AI语音识别做了一套会议小帮手整场录音丢进去转文字、分说话人、提取要点基本都是自动化我只负责最后校对一遍。这篇文章就把我完整踩过的坑、选型思路和可复现的方案分享出来适合自己写脚本做自动化、又被会议纪要折磨得不行的开发者也适合想了解语音识别到底能不能落地的产品经理。1. 会议记录这个场景到底需要什么样的AI帮手1.1 先从最笨的需求聊起很多人一上来就问我你是不是要搞实时转写就是那种会议开着屏幕上字幕实时蹦出来的说实话最开始我也想做实时后来冷静一想真正常用的场景其实分两种。第一种是线上会议。现在腾讯会议、钉钉会议里自带的转写功能已经很好用了你根本不需要自己再造轮子。第二种是线下会议室。一堆人围着一张桌子录音笔一放或者手机往中间一丢这种时候没有字幕、没有转写会后只能靠人肉听录音。我做的这个会议小帮手核心服务的就是第二种场景你只需要把录音文件丢给它它会帮你把整段语音转成文字并且尽量区分出是谁在说话。输出结果是一份带说话人标签、带时间戳的文本文稿。有了这份文稿你再去提炼待办事项、会议决议就轻松太多了。这个需求听起来简单但真正拆开了之后你会发现有几个问题必须解决。第一个问题识别率。普通对话识别不难但是会议里全是专有名词——项目代号、客户名、技术术语甚至是一些英文缩写默认模型大概率会认错。第二个问题谁在说话。只有一段连续的文字你不知道这句话是A说的还是B说的那这份纪要的价值就大打折扣。第三个问题长音频。一场会动辄一个小时以上音频文件巨大怎么处理才能不超时、不丢失数据。这三点其实就是我选型时最核心的判断标准。1.2 技术拆解录下来、转成字、还得认得出人顺着上一节的问题往下捋一个完整的会议小帮手在技术层面无非是下面这四个环节。采集端需要一个能录音的设备。手机就行不用专门的录音笔。转录端把录音文件变成文字这一步就是整套系统的核心引擎。分离端识别出不同说话人的声音特征把每一句话归到对应的人身上。整理端输出带有说话人和时间信息的文本再根据你的需要格式化成纪要模板。前两个环节没什么好说的关键在于第三个环节——说话人分离。你可能觉得区分两个人说话有什么难的一个男声一个女声一听不就分开了但真实会议上两三个人都是同性别、音量相近、语速相近甚至同时抢话的时候区分度会急剧下降。腾讯云语音识别里有一项功能专业术语叫说话人分离也就是声纹级别的区分它会根据说话人的音色特征把音频切成不同的角色段然后标上Speaker ID。这项能力对于会议纪要而言是真正能节省人工的部分。所以我的结论是这个项目不需要过度设计核心就是一段音频进去一段分好人的文字出来。在此基础上再考虑热词、标点、数字格式化这些细节优化而不是一开始就去搞前端界面、实时流式识别那样只会让项目的复杂度飙升实用性却没有明显提升。2. 腾讯云语音识别到底怎么选这几个参数别搞错2.1 三种接口会议场景先用哪一个腾讯云语音识别并非只有一个接口。我当初打开文档的时候也愣了一下接口名字太多了什么一句话识别、实时语音识别、录音文件识别看起来都差不多实际上适配场景完全不同。一句话识别适合语音短搜索、语音输入这种极短音频一段话在60秒以内。实时语音识别适合直播字幕、实时会议转写这种需要边说边出字的场景有配套的WebSocket接口和流式音频处理。录音文件识别适合录音文件转写。音频时长可以到5小时文件大小上限是500MB支持录音文件上传后异步识别、回调结果。会议小帮手用哪个答案已经写得很清楚了录音文件识别。为什么不用实时识别因为线下会议结束之后才去整理没有实时出字的必要实时识别反而要处理音频流的分帧、发送、连接保持代码复杂很多还把服务器网络的稳定性也牵扯了进来。用录音文件识别就有个好处提交任务、等回调、拿结果整个流程可以做成完全异步的哪怕音频再长也不用担心长时间占用连接。三种接口对比一下你就能看得更清楚接口类型适合场景音频时长特点一句话识别短语音指令60秒以内低延迟同步返回实时语音识别直播字幕、实时会议不限流式分帧上传边说边识别录音文件识别会议录音、电话录音转写最长5小时异步处理回调结果我实际用的就是第三类录音文件识别。它解决了我最核心的痛点一次性丢进去一个两小时的录音然后我就可以去干别的等到它回调通知我结果出来了再去拿数据。2.2 真正决定识别效果的几个参数如果你准备调用接口会发现创建任务时有几个参数特别容易踩坑我挨个说。第一个是引擎模型。腾讯云的录音文件识别有多个引擎模型常见的有16k_zh_video、16k_zh_asr等。16k表示音频采样率16kHzzh是中文video和asr对应不同的优化场景。我实测下来电话录音用电话模型效果好普通会议录音用16k_zh_video效果要更好一些因为视频会议和线下会议的录音经过麦克风采集声音特性和电话信道完全不同。但这个参数很多人不调直接用默认结果识别率不高还找不到原因。第二个是说话人分离开关。有一个参数叫EnableSpeakerDiarization默认是不开的。你需要把它打开同时还要设置一个SpeakerNumber也就是说话人的预估人数。这里有个经验宁可把这个数字设大一点设成4、5也不要设成2。因为实际会议总有意外——某个人插了一句话、主持人偶尔客串这些额外的声音如果你预估人数太少会被强行合并到已有的Speaker里。设大一点哪怕最后实际的SpeakerID比预估人数少也不会出大问题最多就是某些角色是空的。第三个是热词表。这个我之前完全没想到后来才发现它才是提升会议识别率的隐藏神器。你可以上传一个热词表每个热词配一个权重数值越大模型就越倾向于识别成这个词。例如你们的项目代号、产品名、用户专有名词全部塞进去效果立竿见影。第四个是音频格式。录音文件识别支持wav、mp3、m4a等主流格式还支持base64数据提交。但有一点要注意声道、采样率这些信息如果你不确定建议把音频先转成wav格式、16k采样率、单声道。为什么是16k因为中文识别模型大多在16k采样率上做了优化你用48k的原始音频直接上传云端会做降采样处理理论上没问题但偶尔会引入一些不可控的失真。我自己就遇到过m4a格式传上去一直报错的情况转成wav之后一次就过了。2.3 为什么说话人分离是会议纪要的核心没有说话人分离的文字稿说到底就是一篇没有标点的大段文字看完还得猜这句话是谁说的。有了说话人分离出来的结果长这样[0] 开发者A 00:01:20 - 00:01:35 这个需求这周必须确认下来不能再拖了。 [1] 开发者B 00:01:36 - 00:01:58 我这边接口已经准备好了就差前端联调。这种格式才能直接落到会议纪要里不同的发言人在后面讨论的时候才能被区分对待。但说实话这个功能并非完美。它本质上是通过声纹聚类实现的如果会议室里两个人的声音实在太像或者背景噪音很大还是会出现错标的情况。不过至少比完全没有分开要好得多。而且这个特性一旦打开你不需要做任何额外的模型训练直接在接口参数里设置两个字段就能启用这对小成本工具来说就是白嫖福利。3. 手把手搭一个最小可用的会议小帮手3.1 整体链路图从录音文件到会议纪要我再强调一次这条链路不需要很复杂。很多教程上来就让你搭前端页面、加数据库、做用户登录我反而不建议这么做。最小可用版本就三步。第一步录音文件准备好。这一步虽然在系统外但出问题最多后面我专门写。第二步调用录音文件识别接口提交一个异步任务。第三步轮询或等待回调拿到转写结果清洗成你要的格式。整个项目从开始写代码到跑通我用了一个晚上加一个早上。如果你之前写过Python其实只花一个下午就能搞定。3.2 用Python快速调用录音文件识别说下具体的调用方式。我用的Python因为腾讯云官方有现成的SDK不用自己去拼请求签名。先安装SDKpip install tencentcloud-sdk-python然后创建一个客户端。这里要填你的SecretId和SecretKey直接在控制台的API密钥管理里创建就好。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 # 密钥建议用环境变量传入不要硬编码在代码里 SECRET_ID 你的SecretId SECRET_KEY 你的SecretKey cred credential.Credential(SECRET_ID, SECRET_KEY) http_profile HttpProfile() http_profile.endpoint asr.tencentcloudapi.com client_profile ClientProfile() client_profile.httpProfile http_profile client asr_client.AsrClient(cred, ap-guangzhou, client_profile)创建任务时关键参数如下。其中EngineModelType选16k_zh_videoEnableSpeakerDiarization打开SpeakerNumber设成你预估的人数ChannelId是声道编号。req models.CreateRecTaskRequest() req.EngineModelType 16k_zh_video req.ChannelId 1 req.SourceType 0 # 0表示URL1表示Base64 req.Url https://你的存储桶/meeting_20250101.wav req.EnableSpeakerDiarization True req.SpeakerNumber 4 req.FilterPunc False # 保留标点方便阅读 resp client.CreateRecTask(req) task_id resp.Data.TaskId print(TaskId:, task_id)这里有一个特别要注意的点SourceType。如果是0表示你传的是一个可公网访问的URL如果是1表示把音频的Base64内容直接放进请求里。Base64方式适合小文件大会录音动辄几百MB你把它编码成Base64塞进POST请求不仅让请求体巨大还容易超时。我强烈建议先把音频传到COS或者任意对象存储桶拿到URL再提交任务。我一开始用Base64方式传了一个40分钟的录音结果等了很久都拿不到结果后来才发现问题就出在请求上。排查了半天最后改成传URL几秒钟就提交成功了。3.3 等待结果处理转写数据提交任务之后有两种方式拿结果。第一种是轮询——每隔几秒去查一次任务状态。第二种是回调——创建任务时填一个回调URL处理完成之后腾讯云会往这个URL上POST结果。本地开发没有公网回调地址的话用轮询是最省事的。查询结果的代码也很简单import time req models.DescribeTaskStatusRequest() req.TaskId task_id while True: resp client.DescribeTaskStatus(req) status resp.Data.Status if status 0: print(任务正在处理中...) time.sleep(5) elif status 1: print(任务处理成功) print(resp.Data.Result) break else: print(任务处理失败) print(resp.Data.ErrorMsg) break这里的状态值要记住0是排队中或处理中1是成功2是失败。成功之后Resp.Data.Result就是一个JSON字符串里面包含了完整的转写结果和说话人信息。我一般会把这个JSON里的数据整理一下变成更容易阅读的格式。核心的数据结构大概是这样的Result里有一个Utterances数组每一个Utterance包含StartTime、EndTime、SpeakerId、Text。你只需要遍历一遍拼成说话人ID加文本的形式就OK。import json result json.loads(resp.Data.Result) utterances result.get(Utterances, []) for u in utterances: speaker u[SpeakerId] start u[StartTime] text u[Text] print(f[说话人{speaker}] ({start}s) {text})就这么简单。把这份文本往纪要模板里一贴一份初稿就出来了。4. 实测中的典型坑和排查思路4.1 识别结果乱码、丢字先别急着骂模型我第一次拿到识别结果的时候发现里面有一句莫名其妙的乱码。后来仔细对比音频发现是演讲者突然切换成英文单词模型把它识别成了看似乱码的中文近似音。这类问题第一排查方向是引擎模型有没有选对第二是音频本身是否有严重压缩。我有个朋友用微信语音转存下来的录音格式是sicp的加密格式转成mp3之后音质很差识别率直接掉了三成。后来我把语音编码重新转一遍码率拉到128kbps以上情况才好转。这个经验很重要音频源的质量决定了识别的上限。你模型参数调得再花哨源文件一团糊结果也救不回来。4.2 说话人分离不准SpeakerID错乱出现这种问题多半是SpeakerNumber设定了不合适的值。例如实际只有两个人开会你把预估人数设成了8模型就会把同一个人的不同句强行拆成两个甚至三个角色。解决办法是通过观察结果动态调整。先设一个相对合理的值跑一遍数一下最终输出里出现了几个SpeakerID。如果发现同一句话被拆给不同角色下一次就调大人数阈值如果发现两个人被合并成一个人就调小阈值。这个参数没有绝对正确只能在你的具体场景里试。这里有个小技巧提前把每个人的发言片段截出来单独提交到一句话识别看能不能稳定识别出同一人声纹这样可以在正式跑之前做一些检验。4.3 音频太长、任务失败、回调超时录音文件识别单任务最大能接受5小时的音频听起来很长但真要传一个3小时的会议还是会遇到文件体积过大的问题。有一个隐藏的限制URL方式上传的音频文件大小不能超过500MB。有一段时间我的录音全是48kHz、双声道、无损格式的wav两小时的会议跑到800多MB死活过不去。后来我把音频批量转成16kHz、单声道wav大小直接缩到原来的五分之一。还有一个细节如果你把音频放在自己的服务器上做URL提交要确保这个URL能被腾讯云的服务器访问到。我自己本地开发时用内网IP生成的URL控制台一直提示下载音频失败后来才知道必须用公网可访问的URL。处理办法很简单把文件丢到COS上生成一个临时链接填进去。4.4 标点和数字格式问题腾讯云识别返回的文字默认带标点数字默认转换成阿拉伯数字。但如果你用的是某些特定模型或者关了标点符号选项结果就会变成一坨连续的文字。这种文本直接拿去排版根本没法看。处理方式有两个一是创建任务时设置FilterPunc为False让它保留标点二是用一些文本处理脚本把常见的中文标点统一格式化。这个不算技术难点但到了输出环节特别影响观感需要提前规划好。另外要注意会议中出现的专业术语比如CQRSK8sDevOps模型经常把大小写搞错。我最后是写了一个简单的字典替换脚本把这些词在输出之前强制统一成标准写法。这个属于锦上添花但确实让结果看起来专业很多。5. 成本、效果以及这套小帮手还能怎么扩展5.1 钱真没花多少学会按量计费很多人以为AI语音识别很贵其实用起来我算过一笔账录音文件识别是按录音时长计费的一场一小时的会议花费在几块钱这个量级也就是一杯饮料钱还不到。当然具体价格要按官方定价页为准不同区域和模型会有一点差异。而且这个服务是按量付费的每个月用几次就付几次的钱不需要预付费也不用担心闲置成本。我自己是平时不开月底统一把积累的录音文件跑一遍一个月的会议纪要成本摊下来非常低。相比的人工整理的时间成本这个投入很值。省钱还有个土方法会议中途如果有明显地长时间没说话的片段比如中场休息、大家各自看手机先手动把这段时间剪掉再提交任务。音频短了钱就省了识别速度还快。5.2 提升识别效果的几个土办法如果你的录音环境比较复杂有几个偏门技巧值得一试。第一给录音做预处理。很多录音有底噪、有轻微的电流声。我在上传之前会先用音频处理工具做一遍降噪把静音部分压缩掉识别率会肉眼可见地提升。第二准备一份针对项目的高频词表。我之前提到过热词表这个一定要用起来。会议里老板最喜欢说战略、复盘、OKR还有项目代号你把这些都加权模型就会乖乖听你的。权重不是越高越好我一般设5到10之间太高的权重反而会强制匹配把本该识别成其他词的地方强行替换掉。第三长音频可以考虑分段提交。虽然录音文件识别支持长音频但单次任务识别时间越长等待时间也越长出错时排查难度也更大。我遇到过一次整段音频只有一个地方识别有误但整个任务失败重新跑一遍要等很久。改成按篇章分段提交之后哪段有问题就重跑哪段效率立刻上来。5.3 后面还能怎么扩展这套系统当前这套方案只能做到转出来如果你想让会议小帮手更完整有几个方向可以做。一是自动生成会议纪要摘要。转写出来的是全文我们真正需要的是结论。可以接一个大语言模型把带说话人的转写结果投喂进去让它自动提炼出参会人、讨论事项、结论、待办事项。这一步我在后续版本里接上了效果很不错。二是自动把录音内容归档到知识库。会议转写稿是一种很有价值的资料可以按日期、项目打好标签放进企业内部的知识库以后谁忘了什么事一搜就能搜到当时谁说的。三是和日历系统打通会议结束两小时后自动给参会人推送一份纪要邮件。这一步做出来之后这个工具才真正算得上是一个帮手。但这些都是后话如果你是从零开始建议先把最核心的录音转文字、分说话人这一步跑通其他的锦上添花功能等到实际使用有需求了再慢慢加。我在实际使用中发现整个项目最让我意外的并不是识别准确率而是异步处理这个设计给工作流带来的改变。提交完录音之后我完全可以先去干别的等结果好了再回来看。这种体验比实时转写更符合会议纪要整理的实际节奏。如果你也被会议纪要折磨过不妨照着这个方法搭一个试试几个小时就能搞定成本也很低。