资讯详情

资讯详情

基于云服务语音识别的会议纪要自动生成工具实战

1. 会议记录这件事到底难在哪开会这件事估计每个打工人都有一肚子话想说。尤其是那种一开就是两小时的跨部门对齐会开完之后领导来一句“把会议纪要整理一下发群里”那一刻的心情懂的都懂。我以前就干过这种活拿着录音文件反复拖进度条一句一句敲字两小时的会整理出三千字的纪要花了整整一个下午。后来我就琢磨语音识别技术现在这么成熟了能不能让它帮我干这个活这个项目就是在这个背景下折腾出来的——用云厂商提供的语音识别能力搭一个能自动把会议录音转成文字、再进一步整理成结构化纪要的小工具。说白了就是把“听录音打字”这个纯体力活交给机器人只负责最后的审核和润色。它解决的核心问题有三个一是转写效率两小时的录音机器几分钟就能出稿二是信息遗漏人耳听录音容易走神漏掉关键内容机器不会三是格式统一每次整理纪要的格式都不一样用模板化的方式输出会规范很多。这个内容适合谁看如果你是一个有点编程基础的后端或全栈开发者想给自己团队做个小工具提效那这篇东西可以直接抄作业。如果你是完全不懂代码的产品或运营同学也可以看看整体思路了解这类工具是怎么跑起来的至少以后跟开发提需求的时候能说到点子上。我下面会从整体设计、核心细节、实操过程到踩坑排查一步步拆开讲尽量让不同基础的人都能有所收获。2. 整体方案怎么设计才靠谱2.1 为什么选云服务而不是本地部署做语音识别摆在面前的第一条岔路就是本地跑开源模型还是调云服务接口我一开始也纠结过。本地部署的好处是数据不出内网听起来很安全但实际算一笔账就发现不划算。一个能打的语音识别模型光模型文件就好几个G要跑得动还得有像样的显卡推理速度还不一定快。更麻烦的是会议录音往往有口音、有背景噪音、有多人同时说话的情况开源模型在这种复杂场景下的准确率会明显下降后期调优的成本非常高。云服务这边就省心多了。以我用的这套方案为例它背后是大厂多年积累的语音数据和模型迭代对口音、噪音、专业术语的识别效果明显好一截。而且按量计费开一次会用一次的钱团队规模不大的话一个月成本也就几十块比自己买显卡划算太多。当然选云服务有个前提就是会议内容不涉及特别敏感的机密信息这个需要根据自己团队的实际情况来判断。如果确实敏感那就得走本地化方案这是另一个话题了。提示选云服务之前先确认一下团队对数据外发的接受度。很多公司对会议录音这类内容是有合规要求的别工具做完了才发现不能用。2.2 整个工具的功能链路拆解我把这个工具的功能拆成了四段像流水线一样一段接一段。第一段是音频预处理。会议录音的来源五花八门有手机录的、有会议软件导出的、还有直接录屏扒出来的音轨。格式不统一采样率也参差不齐。所以第一步得把音频统一转成识别接口能吃的格式通常是16k采样率、单声道的wav或者pcm。这一步用现成的音频处理库就能搞定不需要自己写编解码。第二段是语音转文字。这是核心环节把预处理好的音频丢给语音识别接口拿回带时间戳的文字结果。这里有个关键点就是要开启“说话人分离”功能不然转出来的文字是一大坨分不清谁说的后期整理会非常痛苦。第三段是文本后处理。机器转出来的文字会有一些明显的错误比如同音字、专业术语识别不准、标点符号缺失等。这一步要做的是用规则加词典的方式做一轮清洗把常见的错误修掉再补上标点。第四段是纪要结构化。把清洗后的文字按照会议的主题、决议、待办事项等维度做归类输出成一份格式统一的纪要。这一步可以用大语言模型来做也可以先用规则模板看你对智能程度的要求。2.3 技术选型背后的取舍逻辑在具体技术选型上我做了几个关键决定这里说说为什么。音频处理这块我选了业界最常用的那个音频处理库原因是它跨平台、文档全、社区活跃遇到问题一搜就有答案。没必要为了追求极致性能去用什么冷门库工具类项目稳定好用是第一位的。语音识别接口这块我对比了几家的产品。有的按分钟计费便宜但功能少有的功能全但价格高。最后选的是支持实时和离线两种模式、且说话人分离做得比较成熟的那家。因为会议场景下说话人分离是刚需这个功能做不好后面整理纪要就是灾难。文本后处理这块我一开始想全交给大语言模型后来发现不行。大语言模型有时候会“自作主张”地改写内容把原话改得面目全非这在会议纪要场景下是致命的。所以我的策略是简单的错别字和标点用规则处理复杂的归纳总结才交给大语言模型而且要在提示词里明确要求“不得改变原意”。3. 核心细节里藏着魔鬼3.1 音频预处理的关键参数怎么定音频预处理这一步看起来简单其实参数定不好后面识别准确率会大打折扣。我踩过的坑主要集中在这几个参数上。采样率语音识别接口一般要求16kHz。如果你原始录音是44.1kHz或者48kHz需要重采样。重采样的时候要注意不要直接丢帧要用专业的重采样算法否则会有混叠失真。我用的音频库里有现成的重采样函数指定目标采样率就行。声道数会议录音如果是立体声建议转成单声道。因为语音识别主要关注人声立体声的两个声道信息对识别帮助不大反而增加处理负担。转单声道的时候把两个声道做平均混合就行。音频格式推荐用wav或者pcm因为是无损格式不会有编码损失。如果原始文件是mp3这种有损格式转成wav也不会恢复损失的信息但至少不会二次损失。文件体积大点没关系反正是临时文件处理完就删。音量归一化这个容易被忽略。如果录音音量太小识别准确率会下降。我一般会把音频做一次峰值归一化把最大音量调到-1dB左右。但要注意如果录音里有突然的爆音归一化会把整体音量压得很低这时候得先做一次限幅处理。# 音频预处理的核心逻辑示意 def preprocess_audio(input_path, output_path): # 加载音频 audio load_audio(input_path) # 转单声道 if audio.channels 1: audio to_mono(audio) # 重采样到16kHz if audio.sample_rate ! 16000: audio resample(audio, 16000) # 音量归一化 audio normalize_volume(audio, target_db-1) # 导出为wav save_wav(audio, output_path)3.2 说话人分离为什么是刚需前面提过说话人分离这里展开说说为什么它这么重要。你想象一下如果转出来的文字是这样的“这个方案我觉得可以但是预算方面还需要再确认一下那就下周给答复吧”你根本分不清哪句是谁说的整理纪要的时候全靠猜。但如果有了说话人分离输出就变成了“说话人1这个方案我觉得可以。说话人2但是预算方面还需要再确认一下。说话人1那就下周给答复吧。”这样整理起来就清晰多了。说话人分离的原理简单说就是通过声音的特征比如音色、音调来判断哪些片段是同一个人说的。这里有个常见的误区很多人以为说话人分离能直接告诉你“这是张三说的、那是李四说的”其实不是的。它只能区分出“说话人1、说话人2、说话人3”具体谁是谁需要你自己根据会议内容去对应。我一般的做法是在会议开始的时候让每个人简单说一句话做个声纹登记这样后期对应起来就快了。注意说话人分离在多人同时说话的场景下效果会下降。如果会议讨论很激烈经常有人抢话那分离出来的结果可能会有错乱。这种情况建议在会议录音上做一次人工标注或者用多个麦克风分别录音。3.3 文本后处理的规则设计文本后处理这块我总结了几条实用的规则都是实际跑下来验证有效的。同音字纠错中文语音识别最常见的错误就是同音字。比如“项目”被识别成“象目”“预算”被识别成“玉算”。我的做法是维护一个领域词典把团队常用的专业术语和容易错的词都放进去识别结果出来后做一轮匹配替换。标点补全语音识别接口有的会带标点有的不带。如果不带需要自己补。简单的做法是根据停顿时间加逗号和句号停顿超过一定阈值就加句号短停顿加逗号。复杂一点可以用语言模型来判断但那个成本就高了。数字和单位规范化口语里说“三千五”转成文字最好统一成“3500”。说“百分之二十”统一成“20%”。这个用正则表达式加规则就能处理大部分情况。口语化表达精简会议里难免有“那个”“就是说”“然后然后”这种口头禅整理纪要的时候要删掉。但要注意不能删得太狠否则会改变原意。我的原则是只删明显的冗余词不影响语义的不动。3.4 纪要结构化的模板设计纪要结构化这一步我设计了一个固定的模板包含几个核心板块会议基本信息时间、地点、参会人、会议主题、讨论要点、决议事项、待办事项含负责人和截止时间。这个模板不是拍脑袋定的是参考了团队之前手工整理的纪要格式大家看着习惯。把转写文字填进这个模板有两种做法。一种是纯规则通过关键词匹配来识别哪些内容属于哪个板块。比如出现“决定”“确定”这类词就归到决议事项出现“负责”“跟进”“下周之前”这类词就归到待办事项。另一种是用大语言模型来做语义理解准确率更高但成本也更高。我目前用的是混合方案规则先跑一遍跑不准的再交给大语言模型。4. 动手实操从零搭起这个工具4.1 环境准备和依赖安装先说环境。我用的是Python版本3.9以上太老的版本有些库不支持。操作系统不限Windows、Mac、Linux都能跑我是在Mac上开发的部署在Linux服务器上。依赖库主要有这几个音频处理库用来做格式转换和重采样HTTP请求库用来调云服务接口还有一个文本处理库用来做正则匹配和字符串操作。安装命令很简单一条pip命令搞定。pip install audio-lib requests text-utils云服务的API密钥需要去控制台申请一般注册账号后就能拿到。密钥这东西要保管好不要直接写在代码里我一般用环境变量来存。export ASR_API_KEYyour_api_key_here export ASR_API_SECRETyour_api_secret_here提示API密钥建议设置权限范围只开通语音识别相关的权限不要用主账号的万能密钥。万一泄露了损失可控。4.2 音频预处理代码实现音频预处理我封装成了一个函数输入原始文件路径输出处理好的wav文件路径。核心逻辑前面已经说过了这里补充几个实操细节。第一个细节是异常处理。有些录音文件可能损坏加载的时候会报错。这时候要捕获异常给出明确的错误提示而不是让程序直接崩掉。第二个细节是临时文件管理。预处理会产生临时文件处理完要及时删除不然磁盘很快就满了。我一般用系统的临时目录程序退出时自动清理。import os import tempfile def preprocess_audio(input_path): try: audio load_audio(input_path) except Exception as e: raise ValueError(f音频文件加载失败: {e}) if audio.channels 1: audio to_mono(audio) if audio.sample_rate ! 16000: audio resample(audio, 16000) audio normalize_volume(audio, target_db-1) temp_dir tempfile.gettempdir() output_path os.path.join(temp_dir, preprocessed.wav) save_wav(audio, output_path) return output_path4.3 调用语音识别接口的完整流程调用接口这块不同云厂商的细节不一样但整体流程是相似的。我以我用的这套为例说下完整步骤。第一步是上传音频文件。有的接口支持直接传文件有的要求先上传到对象存储再传URL。我用的这套支持直接传文件省了一步。上传的时候要注意文件大小限制一般单文件不超过100MB超过的要分片。第二步是创建识别任务。这一步要指定一些参数比如音频格式、采样率、是否开启说话人分离、是否开启标点预测等。参数传对了识别效果才好。第三步是轮询任务状态。语音识别是异步的提交任务后会返回一个任务ID需要定期查询任务是否完成。轮询间隔我一般设5秒太频繁了浪费请求太慢了等得着急。第四步是获取识别结果。任务完成后接口会返回识别结果包含文字内容和时间戳。如果有说话人分离还会包含说话人标识。import time import requests def recognize_audio(audio_path, api_key, api_secret): # 上传并创建任务 task_id create_recognition_task(audio_path, api_key, api_secret) # 轮询任务状态 while True: status query_task_status(task_id, api_key, api_secret) if status completed: break elif status failed: raise RuntimeError(识别任务失败) time.sleep(5) # 获取结果 result get_recognition_result(task_id, api_key, api_secret) return result4.4 文本清洗和纪要生成的落地方法拿到识别结果后先做文本清洗。我写了一个清洗函数按顺序执行几个步骤同音字替换、标点补全、数字规范化、口语词删除。每一步都有对应的规则表规则表可以随时扩充。def clean_text(raw_text, domain_dict): # 同音字替换 for wrong, right in domain_dict.items(): raw_text raw_text.replace(wrong, right) # 标点补全简化示意 raw_text add_punctuation(raw_text) # 数字规范化 raw_text normalize_numbers(raw_text) # 口语词删除 raw_text remove_filler_words(raw_text) return raw_text纪要生成这块我用了模板加规则的方式。先把清洗后的文字按段落切分然后对每个段落做关键词匹配判断它属于哪个板块。匹配不上的段落归到“其他讨论”里。最后把各板块的内容填进模板输出成Markdown格式的纪要文件。def generate_minutes(cleaned_text, template): sections { 讨论要点: [], 决议事项: [], 待办事项: [], 其他讨论: [] } paragraphs split_paragraphs(cleaned_text) for para in paragraphs: category classify_paragraph(para) sections[category].append(para) return render_template(template, sections)4.5 参数计算与成本估算成本这块我实际跑了一个月给大家算笔账。语音识别接口一般按音频时长计费我用的这套是每小时几块钱。一个中等规模的团队一天开两小时的会一个月按22个工作日算总共44小时的音频成本大概在一百多块。如果加上说话人分离等增值功能费用会高一些但也就两百块左右。相比人工整理纪要的时间成本这个投入是非常划算的。时间成本上两小时的录音预处理大概十几秒识别大概两三分钟后处理和纪要生成大概半分钟。整体下来五分钟以内能出初稿人工审核润色大概再花二十分钟。相比以前纯手工整理要花一两个小时效率提升非常明显。环节耗时说明音频预处理10-20秒取决于文件大小和格式语音识别2-3分钟异步任务与音频时长相关文本清洗5-10秒规则处理速度很快纪要生成10-20秒模板渲染几乎瞬时人工审核15-30分钟这是最耗时的环节5. 踩过的坑和排查技巧5.1 识别准确率低的常见原因识别准确率低是最常见的问题。我排查下来原因主要有这么几类。音频质量差录音环境嘈杂、麦克风离得远、有回声这些都会严重影响识别。解决办法是尽量用好的录音设备会议时把麦克风放在桌子中间避免放在空调出风口旁边。口音问题如果参会人有比较重的口音识别准确率会下降。这个目前没有特别好的解决办法只能靠后期人工校对。不过我发现在识别接口里指定方言模型效果会好一些。专业术语多每个行业都有自己的黑话通用模型不认识。解决办法就是维护领域词典把术语加进去识别后做替换。多人同时说话这个前面说过了说话人分离会错乱。建议会议主持人控制一下节奏尽量别抢话。5.2 接口调用失败的排查思路接口调用失败排查思路是这样的先看错误码错误码是最直接的线索。常见的错误码有认证失败、参数错误、配额超限、服务不可用等。认证失败就检查密钥对不对参数错误就检查传的参数格式配额超限就去控制台看用量服务不可用就等一会儿再试。如果错误码看不出来就看请求日志。把请求的URL、参数、返回内容都打出来对比接口文档一般能发现问题。我遇到过一次是因为音频文件太大超过了接口限制但错误码没明确说后来看了日志才发现。注意接口调用一定要加超时和重试机制。网络抖动是常有的事没有重试机制的话一次失败就得重新跑整个流程很浪费时间。5.3 文本后处理的边界情况文本后处理有几个边界情况要特别注意。空结果如果音频里全是静音或者噪音识别结果可能是空的。这时候要判断一下如果是空结果直接跳过后续处理给出提示。超长文本如果会议特别长转出来的文字可能超过大语言模型的上下文限制。这时候要分段处理每段单独总结最后再合并。特殊字符识别结果里可能包含一些特殊字符比如表情符号的文本描述、乱码等。这些要在清洗阶段过滤掉不然会影响后续处理。中英文混说会议里经常中英文混着说识别结果可能中英文夹杂。这个目前处理起来比较麻烦我的做法是保留原文不做强制转换人工审核的时候再处理。5.4 常见问题速查表问题现象可能原因解决办法识别结果为空音频静音或格式不对检查音频文件确认有声音且格式正确识别准确率低音频质量差或有口音改善录音环境指定方言模型说话人分离错乱多人同时说话控制会议节奏或人工标注接口调用失败密钥错误或配额超限检查密钥查看用量文本清洗过度规则太激进调整规则保留更多原文纪要结构混乱分类规则不准优化关键词表或引入大语言模型5.5 几个让我少走弯路的实操心得最后分享几个实操心得都是踩坑踩出来的。第一个心得先跑通再优化。我一开始想一步到位把每个环节都做到完美结果卡在音频预处理上好久。后来想通了先用最简单的方案把整个流程跑通哪怕识别准确率只有70%至少流程是通的。然后再逐个环节优化这样进步最快。第二个心得日志要打全。每个环节的输入输出都打日志出问题的时候一看日志就知道是哪一步的问题。我一开始日志打得不全排查问题全靠猜效率很低。第三个心得人工审核不能省。机器再智能也会有出错的时候。会议纪要是要发给领导看的出错影响不好。所以我的流程里机器出初稿人工必须审核一遍才能发出去。审核的时候重点看人名、数字、决议事项这些关键信息。第四个心得模板要灵活。不同团队的纪要格式不一样有的喜欢按时间线有的喜欢按主题。我的做法是把模板做成可配置的换个模板文件就能换一种格式不用改代码。这个工具我用了大半年整体感觉是它不能完全替代人工但能把人工从繁琐的转写工作中解放出来让人专注于内容的理解和提炼。这才是工具该有的样子——不是取代人而是让人做更有价值的事。后续我还想加一些功能比如自动提取会议里的行动项并同步到任务管理工具或者根据历史纪要自动生成会议模板这些等有空了再折腾。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →