腾讯云AI语音识别实战:会议记录自动化与说话人分离方案

发布时间:2026/10/20 9:07:40
腾讯云AI语音识别实战:会议记录自动化与说话人分离方案
1. 从一场两小时的会议录音说起上周帮一个做企业培训的朋友处理了一批会议录音六场会每场平均一个半小时录完往硬盘里一扔就没人管了。他跟我说每次开完会都想着整理纪要但一看到那堆音频文件就犯怵手动听打至少要花三倍的时间。这个场景我太熟悉了——会议记录这件事几乎每个团队都在做但真正做得好的没几个。要么是没人愿意记要么是记了但信息遗漏严重要么是记完就躺在共享盘里再也没人翻。后来我用腾讯云的AI语音识别服务搭了一套自动化流程从音频上传到输出带时间戳和说话人区分的文字稿整个过程压缩到几分钟。这篇文章就把这套方案完整拆开讲一遍包括为什么选这个服务、怎么配置参数、实际跑下来哪些地方容易翻车、以及怎么把识别结果进一步加工成可用的会议纪要。如果你也在被会议记录折磨或者想找一个靠谱的语音转文字方案这篇内容应该能帮你省不少时间。核心关键词就几个腾讯云AI语音识别、会议记录自动化、语音转文字、说话人分离、实时识别与录音文件识别。整套方案不复杂但细节很多我会把每个环节的坑都标出来。2. 为什么是腾讯云AI语音识别而不是其他方案2.1 先搞清楚会议场景对语音识别的真实需求很多人一上来就问哪个语音识别准确率最高这个问题其实问偏了。会议场景的需求跟通用语音转文字完全不一样你得先把自己的场景拆清楚。我总结下来会议记录对语音识别有五个硬性要求长音频支持一场会动辄一两个小时很多免费或轻量级方案对音频时长有限制超过就截断或者直接失败。说话人分离会议是多个人交替发言如果转出来的文字分不清谁说的那基本没法用。专业术语识别每个行业都有自己的黑话通用模型很容易把日活听成日活这个还好把转化率听成转花率就麻烦了。时间戳做纪要的时候需要定位到具体时间点方便回溯原音。批量处理能力不是一场会是每周好几场得能批量跑。腾讯云的录音文件识别服务在这几个维度上覆盖得比较完整。它支持最长5小时的音频文件自带说话人分离功能可以上传自定义词表来提升专业术语的识别率输出结果带逐句时间戳。这些能力组合起来刚好匹配会议记录的核心诉求。2.2 录音文件识别和实时语音识别到底选哪个腾讯云AI语音识别下面有两个主要产品线实时语音识别和录音文件识别。很多人搞不清楚该用哪个我一开始也纠结过。实时语音识别的逻辑是音频流一边传输一边出结果延迟很低适合直播字幕、实时会议字幕这种场景。但它的缺点是说话人分离能力弱而且对网络稳定性要求高一旦断流就得重来。录音文件识别的逻辑是先把音频文件传到对象存储然后提交识别任务异步等待结果。它的优势是支持说话人分离、支持更大的音频文件、识别准确率在长音频上更稳定。缺点是没法实时出结果得等。对于会议记录这个场景我的建议很明确用录音文件识别。原因很简单——会议记录不是要实时看字幕而是要事后整理出一份准确的纪要。准确率和说话人分离比实时性重要得多。而且录音文件识别可以批量提交任务你周五下班前把一周的会议录音全部提交周一早上来收结果就行。注意如果你的场景是线上会议需要实时字幕辅助那实时语音识别更合适。但如果是会后整理纪要录音文件识别是更优解。两者可以结合使用实时识别做辅助录音文件识别做最终稿。2.3 成本账要算清楚说到成本腾讯云语音识别的计费方式是按音频时长计费。录音文件识别的价格大概在每小时几块钱的量级具体价格以官网为准不同套餐有差异。一场一小时的会议识别成本大概就是一杯奶茶的钱。但这里有个容易被忽略的点音频预处理会直接影响成本。如果你上传的是双声道音频每个声道分别识别那计费时长会翻倍。所以在上传之前最好先把音频转成单声道能省一半的钱。这个细节后面讲实操的时候会详细说。另外腾讯云经常有新用户免费额度刚开始试的时候可以先薅一波免费额度跑通流程再正式付费。对于小团队来说一个月的会议识别成本可能也就几十块钱比请人专门做会议记录划算太多了。3. 从音频到文字稿的完整链路拆解3.1 整体架构四个环节串起来这套方案的整体链路不复杂但每个环节都有讲究。我把它拆成四步音频采集与预处理把会议录音整理成符合要求的格式上传到对象存储腾讯云语音识别需要音频文件有一个可访问的URL提交识别任务调用API提交任务配置识别参数获取与后处理结果拉取识别结果做进一步加工这四步里面第一步和第四步是最容易被低估的。很多人以为调个API就完事了实际上音频预处理和结果后处理才是决定最终可用性的关键。3.2 音频预处理别小看这一步腾讯云录音文件识别对音频格式有明确要求支持的格式包括wav、mp3、m4a、aac等采样率建议16kHz位深16bit。但实际拿到的会议录音往往五花八门——有的是手机录的m4a有的是会议系统导出的wav还有的是从视频里提取的音频。我一般会用ffmpeg做统一预处理核心命令如下# 转成16kHz单声道wav格式 ffmpeg -i input.m4a -ar 16000 -ac 1 -acodec pcm_s16le output.wav这条命令做了三件事把采样率统一到16000Hz把声道数强制为1单声道把编码格式转成PCM 16位小端。为什么要这么做采样率16kHz这是语音识别的标准采样率再高对识别准确率提升有限反而增加文件体积和上传时间。单声道前面说了双声道会按两倍时长计费而且会议录音通常不需要立体声。PCM编码无损格式识别引擎处理起来最稳定不会因为压缩算法引入的失真影响识别效果。如果原始音频噪音比较大还可以加一步降噪# 使用ffmpeg的降噪滤镜 ffmpeg -i input.wav -af afftdnnf-25 -ar 16000 -ac 1 output_denoised.wavafftdn是FFT降噪滤镜nf-25表示噪声底限设为-25dB。这个参数需要根据实际录音环境调整如果会议室空调声大可以适当调高。实操心得降噪不是越强越好。过度降噪会把人声的细节也抹掉反而降低识别准确率。我的经验是如果原始录音信噪比还可以直接跳过降噪如果背景噪音明显用轻度降噪即可不要追求干净得像录音棚。3.3 上传到对象存储URL是必须的腾讯云录音文件识别要求音频文件必须有一个可访问的URL所以你需要先把文件上传到对象存储COS。这一步看起来简单但有几个细节要注意存储桶权限识别服务需要能读取到这个文件所以存储桶的权限设置要允许读取。但也不要设成公开读写那样有安全风险。建议用临时签名URL或者给识别服务授权。文件命名建议用有意义的命名规则比如meeting_20240115_产品评审.wav方便后续管理和追溯。区域选择存储桶的区域最好和语音识别服务的区域一致这样内网传输速度快也不会有跨区费用。上传的代码示例Pythonfrom qcloud_cos import CosConfig, CosS3Client secret_id 你的SecretId secret_key 你的SecretKey region ap-shanghai token None scheme https config CosConfig(Regionregion, SecretIdsecret_id, SecretKeysecret_key, Tokentoken, Schemescheme) client CosS3Client(config) # 上传文件 response client.upload_file( Bucketyour-bucket-125xxxxxxx, LocalFilePathmeeting_audio.wav, Keymeetings/20240115_product_review.wav, PartSize1, MAXThread10, EnableMD5False ) print(response[ETag])上传完成后你需要生成一个可访问的URL。如果存储桶是私有读可以用get_presigned_url生成带签名的临时URLurl client.get_presigned_url( MethodGET, Bucketyour-bucket-125xxxxxxx, Keymeetings/20240115_product_review.wav, Expired3600 # URL有效期1小时 )3.4 提交识别任务参数配置是核心这是整个流程最关键的一步。腾讯云录音文件识别的API叫CreateRecTask核心参数包括参数名说明推荐值EngineModelType引擎模型类型16k_zh中文通用ChannelNum声道数1ResTextFormat结果文本格式0基础格式或2带时间戳和说话人SpeakerDiarization是否开启说话人分离1开启SpeakerNumber说话人数量根据实际人数填不填则自动判断FilterDirty是否过滤脏词1过滤FilterModal是否过滤语气词1过滤HotwordId热词表ID提前创建好的热词表ResTextFormat这个参数特别重要。如果你只需要纯文本填0就行但如果要做会议纪要强烈建议填2这样返回的结果会包含每个句子的开始时间、结束时间和说话人ID。SpeakerDiarization开启后识别结果会把不同说话人标记为说话人0说话人1这样的ID。但要注意它只能区分不同的人不能告诉你具体是谁。所以会后还需要人工把说话人ID映射到具体人名这个后面会讲怎么高效处理。热词表是提升专业术语识别率的关键。你可以在控制台创建一个热词表把团队常用的专业术语、产品名、人名都加进去。比如日活跃用户转化漏斗OKR对齐这些词通用模型可能会识别错但加到热词表里就能显著改善。# 提交识别任务的示例代码 import json from tencentcloud.common import credential from tencentcloud.asr.v20190614 import asr_client, models cred credential.Credential(你的SecretId, 你的SecretKey) client asr_client.AsrClient(cred, ap-shanghai) req models.CreateRecTaskRequest() req.EngineModelType 16k_zh req.ChannelNum 1 req.ResTextFormat 2 req.SourceType 0 req.Url 你的音频文件URL req.SpeakerDiarization 1 req.SpeakerNumber 0 req.FilterDirty 1 req.FilterModal 1 req.HotwordId 你的热词表ID resp client.CreateRecTask(req) print(resp.TaskId)提交成功后会返回一个TaskId后续用这个ID去查询识别结果。3.5 拉取结果异步等待与轮询录音文件识别是异步任务提交后需要轮询查询状态。腾讯云提供了DescribeTaskStatus接口传入TaskId即可查询。# 轮询查询任务状态 import time req models.DescribeTaskStatusRequest() req.TaskId 你的TaskId while True: resp client.DescribeTaskStatus(req) status resp.Data.Status if status 2: # 2表示识别完成 print(resp.Data.Result) break elif status 3: # 3表示识别失败 print(识别失败:, resp.Data.ErrorMsg) break else: print(识别中等待10秒...) time.sleep(10)状态码的含义0是等待中1是识别中2是识别完成3是识别失败。一般一小时的音频识别时间在几分钟左右具体取决于排队情况。返回的结果是一个JSON字符串里面包含了逐句的识别文本、时间戳和说话人ID。拿到这个结果之后就可以进入后处理环节了。4. 识别结果的后处理从文字稿到可用纪要4.1 说话人ID映射把说话人0变成具体人名识别结果里的说话人ID是说话人0说话人1这样的匿名标识直接看根本不知道谁是谁。这一步没有自动化的捷径但可以做得高效一些。我的做法是先让识别结果按说话人分组把每个说话人的所有发言片段提取出来然后快速浏览一遍根据发言内容判断是谁。比如提到我们技术这边的大概率是技术负责人提到预算的大概率是财务或管理层。具体操作上可以用Python把结果按说话人聚合import json result json.loads(resp.Data.Result) sentences result[ResultDetail] # 按说话人分组 speaker_segments {} for sent in sentences: speaker sent[SpeakerId] if speaker not in speaker_segments: speaker_segments[speaker] [] speaker_segments[speaker].append({ start: sent[StartTime], end: sent[EndTime], text: sent[FinalSentence] }) # 输出每个说话人的发言摘要 for speaker, segments in speaker_segments.items(): print(f 说话人{speaker} ) for seg in segments[:5]: # 只看前5句 print(f[{seg[start]}ms] {seg[text]})看完每个说话人的前几句话基本就能判断出身份了。然后建一个映射字典把ID替换成人名。4.2 时间戳对齐快速定位原音时间戳的价值在于回溯。当纪要有疑问的时候可以根据时间戳快速定位到原音的具体位置。我一般会在最终的文字稿里保留时间戳格式是[HH:MM:SS]。def format_time(ms): seconds ms // 1000 hours seconds // 3600 minutes (seconds % 3600) // 60 secs seconds % 60 return f{hours:02d}:{minutes:02d}:{secs:02d} for sent in sentences: time_str format_time(sent[StartTime]) speaker_name speaker_map.get(sent[SpeakerId], f说话人{sent[SpeakerId]}) print(f[{time_str}] {speaker_name}: {sent[FinalSentence]})这样输出的文字稿每一句都有时间戳和说话人看起来就很清晰了。4.3 自动摘要用大模型做二次加工文字稿有了但一份一小时的会议文字稿可能有上万字没人愿意从头读到尾。这时候可以用大语言模型做自动摘要。我的做法是把文字稿按议题切分然后让模型对每个议题生成摘要和待办事项。提示词大概是这样以下是一场会议的记录请帮我 1. 按讨论的议题分段 2. 每个议题提炼3-5个关键结论 3. 提取所有待办事项标注负责人如果提到的话 4. 标记有争议或未达成一致的点 会议记录 {文字稿内容}这样处理之后一份可读性很强的会议纪要就出来了。当然自动摘要的结果需要人工复核但至少省去了从零开始整理的时间。实操心得自动摘要的提示词里一定要强调只基于原文内容不要自行推断。否则模型很容易脑补出一些会上根本没说的内容那就麻烦了。5. 实际跑下来容易翻车的几个地方5.1 音频质量问题导致的识别错误这是最常见的问题。会议录音如果是在大会议室用单麦克风录的离得远的人说话声音小识别准确率会明显下降。我遇到过最夸张的情况是坐在角落的同事发言被识别成了嗯嗯啊啊一堆无意义的字。解决办法有两个一是尽量用每个人的独立麦克风比如线上会议每个人用自己的电脑麦克风二是如果只能用一个麦克风尽量放在桌子中间并且开会前测试一下录音效果。另外如果会议中有大量重叠发言几个人同时说话说话人分离的效果会大打折扣。这种情况下识别结果可能会出现说话人ID跳来跳去的情况。我的建议是如果会议讨论很激烈可以在会后结合录音人工校对关键部分。5.2 热词表不是万能的热词表能提升专业术语的识别率但也不是加了就万事大吉。我测试下来热词表对词的识别提升明显但对短语和句子的提升有限。而且热词表有数量限制不能无限加。我的策略是只加最高频、最容易识别错的词。比如产品名称、核心技术术语、团队成员的姓名。那些偶尔出现的词加了反而可能干扰其他词的识别。还有一个坑热词表创建后需要一定时间生效不是立即就能用的。如果你刚创建完就提交识别任务可能热词还没加载进去。建议创建后等几分钟再提交任务。5.3 长音频的断句问题一小时的音频识别结果可能会有几百个句子。有时候断句会不太合理比如把一句话拆成两半或者把两句话合并成一句。这会影响后续的摘要质量。腾讯云的识别结果里有一个FinalSentence字段是经过断句处理的。如果对断句要求高可以在后处理阶段用标点符号和语义做二次断句。不过大多数情况下原生的断句已经够用了。5.4 并发限制和排队腾讯云录音文件识别有并发任务数限制具体数量取决于你的套餐。如果你一次性提交太多任务后面的任务会排队等待。对于小团队来说一般不会碰到这个限制但如果是大规模批量处理需要提前规划好提交节奏。我的做法是分批提交每批不超过并发上限等前一批完成后再提交下一批。这样虽然总时间长了点但不会因为超限导致任务失败。6. 把这套流程串起来一个可复用的脚本框架6.1 目录结构设计为了让这套流程可复用我把它整理成了一个Python脚本目录结构如下meeting-asr/ ├── config.py # 配置文件密钥、存储桶信息等 ├── preprocess.py # 音频预处理 ├── upload.py # 上传到COS ├── recognize.py # 提交识别任务并轮询结果 ├── postprocess.py # 结果后处理说话人映射、时间戳格式化 ├── summarize.py # 自动摘要 └── main.py # 主流程入口6.2 主流程代码框架# main.py import os from preprocess import preprocess_audio from upload import upload_to_cos from recognize import submit_task, poll_result from postprocess import format_result from summarize import generate_summary def process_meeting(audio_path, meeting_title): # 1. 预处理 processed_path preprocess_audio(audio_path) # 2. 上传 url upload_to_cos(processed_path) # 3. 提交识别 task_id submit_task(url) # 4. 轮询结果 raw_result poll_result(task_id) # 5. 后处理 formatted_text format_result(raw_result) # 6. 保存文字稿 output_path foutput/{meeting_title}_transcript.txt with open(output_path, w, encodingutf-8) as f: f.write(formatted_text) # 7. 生成摘要 summary generate_summary(formatted_text) summary_path foutput/{meeting_title}_summary.md with open(summary_path, w, encodingutf-8) as f: f.write(summary) print(f处理完成{output_path}) return output_path, summary_path if __name__ __main__: process_meeting(raw_audio/meeting_0115.m4a, 产品评审会)这个框架跑通之后每周的会议录音只需要把文件丢到raw_audio目录改一下文件名运行脚本就行。整个过程从原来的几小时压缩到十几分钟。6.3 批量处理的优化如果一周有好几场会可以写一个批量处理的脚本import os from main import process_meeting audio_dir raw_audio/ for filename in os.listdir(audio_dir): if filename.endswith((.wav, .mp3, .m4a)): audio_path os.path.join(audio_dir, filename) meeting_title os.path.splitext(filename)[0] try: process_meeting(audio_path, meeting_title) except Exception as e: print(f处理 {filename} 失败: {e})这样一次性把所有会议录音都处理完省时省力。7. 一些关于准确率和效率的实测数据7.1 不同音频条件下的识别准确率我用自己的几场会议录音做了对比测试结果如下音频条件大致准确率主要问题单人麦克风安静环境95%以上偶尔专业术语错误会议室单麦克风正常讨论85%-90%远场发言识别率下降会议室单麦克风激烈讨论75%-85%重叠发言导致说话人混乱手机录音有背景噪音70%-80%噪音干扰明显这个数据只是我个人的测试结果实际准确率会因会议内容、口音、语速等因素有较大差异。但整体趋势是明确的音频质量决定识别上限。7.2 时间成本对比处理方式一小时会议的处理时间人工听打3-4小时人工听打校对4-5小时本方案自动识别5-10分钟本方案人工校对30-40分钟自动识别把时间压缩了90%以上即使加上人工校对效率提升也非常明显。7.3 成本对比以一小时会议为例项目成本人工听打按市场价100-200元本方案识别费用几元本方案人工校对几十元对于需要频繁整理会议记录的团队来说这套方案的性价比很高。8. 后续可以继续优化的方向8.1 实时字幕与录音识别的结合目前这套方案是会后处理如果线上会议需要实时字幕可以接入腾讯云的实时语音识别。实时识别出初步结果会后用录音文件识别出精校版两者互补。8.2 与会议系统的深度集成如果团队用的是固定的线上会议系统可以研究一下是否有API可以自动获取会议录音省去手动上传的步骤。不过这个取决于会议系统是否开放接口。8.3 知识库沉淀识别出来的会议纪要可以进一步结构化比如按项目、按议题、按决策类型分类沉淀到团队的知识库里。这样以后回溯某个决策的时候可以直接搜索到相关的会议记录。8.4 多语言支持腾讯云语音识别支持多种语言和方言。如果团队有跨语言沟通的需求可以在提交任务时指定不同的EngineModelType。比如英语会议用16k_en粤语会议用16k_yue。这套方案我自己跑了大半年从最初的每次手动处理到现在基本全自动化省下来的时间相当可观。最关键的体会是音频预处理和热词表这两个环节投入产出比最高。花十分钟把音频转成标准格式花五分钟配置热词表能让识别准确率提升一大截。至于后处理和摘要可以根据团队的实际需求逐步完善不用一开始就追求大而全。