首页
看点啥
插画图片
首页 看点啥 会议发言人如何自动标注 CAM++ 声纹识别接入AI会议助手实践

会议发言人如何自动标注 CAM++ 声纹识别接入AI会议助手实践

2026-07-11 0

会议发言人如何自动标注?CAM++ 声纹识别接入AI会议助手实践

{"type":"doc","content":[{"type":"heading","attrs":{"id":"737f9337-e548-42c8-bd6c-abef9d6ab672","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"一、引言:会议转写之后,为什么还要标注发言人?"}]},{"type":"paragraph","attrs":{"id":"e5024ba2-ad97-4fcd-957e-e17e9a5f28b0","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"在会议转写系统中,ASR 解决的是“说了什么”的问题。但在真实会议场景里,用户往往还会继续追问:"}]},{"type":"paragraph","attrs":{"id":"8ac3b713-0d89-48d5-a1ae-618eed6f490a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这句话是谁说的?"}]},{"type":"paragraph","attrs":{"id":"c90f6c3c-7b70-4f7e-83f5-0084375a592c","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"如果只有一整段连续转写文本,后续整理纪要时仍然需要人工反复回听。尤其是多人会议、项目评审、访谈记录、专家讨论、远程协作会议中,“谁在什么时候说了什么”往往和会议内容本身同样重要。"}]},{"type":"paragraph","attrs":{"id":"13f5390c-bf76-499c-a7ef-54139d7ae9e2","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这就需要在 ASR 之外加入说话人标注能力。"}]},{"type":"paragraph","attrs":{"id":"423fdb71-5059-4466-87b6-d961ab1de1f5","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"CAM 的作用,正是在会议音频中提取说话人声纹特征,并辅助系统判断不同语音片段是否来自同一个人。结合 ASR、VAD 和标点恢复后,系统可以把原始录音整理成更接近会议记录的结构:"}]},{"type":"codeBlock","attrs":{"id":"0aaa1c31-4105-4952-9e80-50135641c442","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"Speaker 0:本次会议先确认部署计划。nSpeaker 1:我补充一下,接口联调需要提前完成。nSpeaker 2:后续待办由运维侧跟进。n"}]},{"type":"paragraph","attrs":{"id":"5670adb7-2ae5-44d9-9f1e-37d971edbc94","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"如果再接入声纹注册信息,还可以进一步把 "},{"type":"text","marks":[{"type":"code"}],"text":"Speaker 0"},{"type":"text","text":"、"},{"type":"text","marks":[{"type":"code"}],"text":"Speaker 1"},{"type":"text","text":" 映射为具体参会人姓名。"}]},{"type":"paragraph","attrs":{"id":"99878e4e-23d0-419e-9b35-99519d6f46c6","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"本文以 CAM 和 FunASR 为基础,梳理一条从会议录音到发言人自动标注的技术链路。在本文的后处理层中,熙瑾会悟负责接收带说话人信息的转写结果,并继续生成会议纪要、待办事项和归档资料。"}]},{"type":"heading","attrs":{"id":"47f14604-020b-4d82-9949-050b473c1272","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"二、整体链路:从音频到“谁说了什么”"}]},{"type":"paragraph","attrs":{"id":"9930eb53-fe08-437a-87fb-0109cca2e5a3","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"会议发言人标注不是单独一个模型就能完成的任务。它通常需要多个模块协同:"}]},{"type":"paragraph","attrs":{"id":"bbe2eaed-1c0f-4680-a36f-b65207ec0bf1","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"ASR 负责识别文字。"}]},{"type":"paragraph","attrs":{"id":"0263617b-082d-404b-9759-f200c22b2300","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"VAD 负责检测有效语音区间。"}]},{"type":"paragraph","attrs":{"id":"4412d406-1b92-449d-b732-31fc2af7c365","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"CAM 负责提取说话人声纹特征。"}]},{"type":"paragraph","attrs":{"id":"bbb2dfe2-f69b-4857-8bcb-77ed6b897a4d","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"说话人聚类负责把同一人的片段归到一起。"}]},{"type":"paragraph","attrs":{"id":"dc44b574-ef15-40c4-a28b-c16137bc4ef8","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"标点模型负责恢复句子边界。"}]},{"type":"paragraph","attrs":{"id":"5bcdb692-f477-4e90-bde4-329457966677","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"会议处理模块负责生成纪要、待办和归档资料。"}]},{"type":"paragraph","attrs":{"id":"8388c7aa-1f4a-4754-8035-eb84d156c616","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"一个较完整的链路可以表示为:"}]},{"type":"codeBlock","attrs":{"id":"98780e14-2ca7-440a-a681-3dc59df12bd5","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"会议录音n↓n音频预处理:格式转换、采样率统一、单声道处理n↓nVAD:检测有效语音片段n↓nASR:识别每段语音内容n↓nCAM :提取声纹特征,辅助说话人聚类n↓n标点恢复:形成句级文本n↓n句级结构化:speaker_id start_time end_time textn↓n熙瑾会悟:会议纪要、待办事项、资料归档n"}]},{"type":"paragraph","attrs":{"id":"74b5bc39-ee80-4939-baae-1a45177e262a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这条链路的重点不是单纯“识别出几个人”,而是把语音识别结果变成可被会议系统继续处理的结构化数据。"}]},{"type":"paragraph","attrs":{"id":"a32cab45-a93d-484f-89e7-08cb4a72977e","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"原始 ASR 文本可能是这样的:"}]},{"type":"codeBlock","attrs":{"id":"30ef754b-4d62-4192-9537-998c5a92918e","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"今天我们先确认部署时间接口联调这边需要提前完成后续由运维侧跟进。n"}]},{"type":"paragraph","attrs":{"id":"126af7dd-12bb-46e7-985f-00934b2752b6","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"加入说话人标注后,可以变成:"}]},{"type":"codeBlock","attrs":{"id":"d17bc064-578c-4b05-91b9-d919277eb09b","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"Speaker 0:[00:00:01 - 00:00:04] 今天我们先确认部署时间。nSpeaker 1:[00:00:05 - 00:00:09] 接口联调这边需要提前完成。nSpeaker 2:[00:00:10 - 00:00:13] 后续由运维侧跟进。n"}]},{"type":"paragraph","attrs":{"id":"f6045275-bc49-4e29-a154-5d38411d7b02","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"后一种结果更适合继续生成纪要、任务清单和责任人记录。"}]},{"type":"heading","attrs":{"id":"5fb13538-43ea-4981-9ed8-dc3ea2f861d3","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"三、环境准备:搭建 FunASR CAM 推理环境"}]},{"type":"paragraph","attrs":{"id":"da2657d6-5dd4-40ed-b44a-2fb4d5f0e8df","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这里从本地环境开始搭建,便于后续接入内部会议系统。"}]},{"type":"paragraph","attrs":{"id":"0cb89299-2521-45b3-94bb-df429a6de2e8","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"推荐环境如下:"}]},{"type":"table","attrs":{"id":"16c14c03-2ead-4054-a416-29956bd1dbac","isHoverDragHandle":false},"content":[{"type":"tableRow","content":[{"type":"tableHeader","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"29b76e81-f3c1-4646-8eed-5881e6d146d1","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"配置项"}]}]},{"type":"tableHeader","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"e71af796-89b3-49ec-86b0-95bcf7247e6c","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"建议配置"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"2a127f8c-537e-44cb-90d4-d0877e1a1011","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"操作系统"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"cc0b9b87-c747-44b8-8f49-14e290b6a6f2","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Ubuntu 20.04 / 22.04 或其他 Linux 服务器环境"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"2c061603-47f4-47ab-8958-2822ddbbaa95","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Python"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"b287e23f-90dc-4957-b9f5-9656f1db38a0","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"Python 3.10 "}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"8511ba9d-f261-4abd-8dfe-e369dba57716","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"GPU"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"3024592a-0535-4a76-961b-9c726bf867f9","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"建议使用 NVIDIA GPU,测试环境可先用 CPU"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"aa14cee9-764b-47c7-af0c-7625280a396a","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"音频工具"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"73fb2414-2683-4f5b-846b-b1f078b64fbc","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"ffmpeg"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"b934030a-a5fd-4577-86ce-377c38b0e065","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"语音工具链"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"bc4df5ec-f18c-48ac-b721-4bc8da4d6ed3","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"FunASR"}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"f01d0e09-00ac-4a96-84fe-71f5b3e37bfb","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"说话人模型"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"080f90a6-35e0-49f4-b45c-f78df5472fc0","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"CAM "}]}]}]},{"type":"tableRow","content":[{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"23c2c0b3-1e13-44cc-98a5-cd520ffc17c1","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"服务框架"}]}]},{"type":"tableCell","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"background":null,"color":null,"textAlign":null,"style":null},"content":[{"type":"paragraph","attrs":{"id":"4f228691-dc48-4f7c-a93b-e8803fe39905","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"FastAPI / Uvicorn"}]}]}]}]},{"type":"paragraph","attrs":{"id":"5616849f-15b2-4908-a1a6-f2fe1b373ca5","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"创建环境:"}]},{"type":"codeBlock","attrs":{"id":"a3a478b7-f542-46c9-990c-fb0bb71bdcfd","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"conda create -n meeting-spk python=3.10 -ynconda activate meeting-spknnpip install -U funasrnpip install modelscopenpip install fastapi uvicorn python-multipart requests pydubn"}]},{"type":"paragraph","attrs":{"id":"2d341d46-ecca-4692-a1ca-1caa06cf2062","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"如果部署环境无法访问外网,可以提前下载相关模型,再拷贝到内网服务器。常见链路中会用到 ASR、VAD、标点和说话人模型:"}]},{"type":"codeBlock","attrs":{"id":"6032ef44-2634-4f61-a3ff-3b46837ee4a1","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"modelscope download --model iic/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch --local_dir ./models/paraformernmodelscope download --model iic/speech_fsmn_vad_zh-cn-16k-common-pytorch --local_dir ./models/fsmn-vadnmodelscope download --model iic/punc_ct-transformer_zh-cn-common-vocab272727-pytorch --local_dir ./models/ct-puncnmodelscope download --model iic/speech_campplus_sv_zh-cn_16k-common --local_dir ./models/campplusn"}]},{"type":"paragraph","attrs":{"id":"97103c65-0851-486a-969d-1a5f9bd093f4","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"正式部署时,建议把模型、代码、依赖包、启动脚本和配置文件放在同一套交付目录中。这样可以避免现场临时下载模型,也便于版本回退和问题定位。"}]},{"type":"heading","attrs":{"id":"6fd9f20d-21a6-439d-b3c1-a4fd9f1ba693","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"四、第一次测试:输出带 speaker 标签的会议转写"}]},{"type":"paragraph","attrs":{"id":"26424762-0ea0-4268-9671-805437597ff7","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"先准备一段测试会议音频:"}]},{"type":"codeBlock","attrs":{"id":"9b8d1c1c-0339-43f5-96d9-70bb3da67312","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"./samples/meeting_two_speakers.wavn"}]},{"type":"paragraph","attrs":{"id":"33a7e437-4182-4711-af25-6ecac046c51b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这段音频最好包含两到三个人轮流发言,便于观察说话人标注效果。"}]},{"type":"paragraph","attrs":{"id":"84c3aba4-906e-4ce2-a25d-d0dd149e2bf2","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"新建 "},{"type":"text","marks":[{"type":"code"}],"text":"test_campplus_diarization.py"},{"type":"text","text":":"}]},{"type":"codeBlock","attrs":{"id":"28261c4c-da5e-44a7-82cd-820ab5f425d0","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"from funasr import AutoModelnnmodel = AutoModel(nmodel="paraformer-zh",nvad_model="fsmn-vad",npunc_model="ct-punc",nspk_model="cam ",ndevice="cuda:0",n)nnresult = model.generate(ninput="./samples/meeting_two_speakers.wav",nbatch_size_s=60,n)nnfor sentence in result[0].get("sentence_info", []):nspeaker = sentence.get("spk", "unknown")nstart = sentence.get("start", 0)nend = sentence.get("end", 0)ntext = sentence.get("text", "")nnprint(f"Speaker {speaker}: [{start}ms - {end}ms] {text}")n"}]},{"type":"paragraph","attrs":{"id":"bf6fbc51-6966-4266-8aaf-661c76f4c68d","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"执行:"}]},{"type":"codeBlock","attrs":{"id":"a440cf75-3cf8-411b-b471-8bc71d9e672c","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"python test_campplus_diarization.pyn"}]},{"type":"paragraph","attrs":{"id":"33c52fca-a289-4017-beb6-00aaf0a483d5","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"输出可能类似:"}]},{"type":"codeBlock","attrs":{"id":"ecc49ec2-f8dd-4b2f-8ea7-306793ffb39a","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"Speaker 0: [680ms - 3620ms] 今天我们先确认部署时间。nSpeaker 1: [4050ms - 8120ms] 接口联调需要提前完成,否则会影响后续测试。nSpeaker 0: [8560ms - 11900ms] 那这个事项就先由运维侧跟进。n"}]},{"type":"paragraph","attrs":{"id":"92750e32-27b2-4f24-b1d3-c2ce21b3d801","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这一步说明基本链路已经打通:系统不仅识别出了文本,还给每一句话附加了说话人标签。"}]},{"type":"paragraph","attrs":{"id":"3956a9cf-3c33-4543-b0f5-f209f2bdc71c","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"需要注意的是,"},{"type":"text","marks":[{"type":"code"}],"text":"Speaker 0"},{"type":"text","text":"、"},{"type":"text","marks":[{"type":"code"}],"text":"Speaker 1"},{"type":"text","text":" 只是聚类结果,不等同于真实姓名。要进一步变成“张总”“李工”“王主任”,还需要声纹注册和身份映射。"}]},{"type":"heading","attrs":{"id":"cce9cbe6-f8db-41b9-8374-9cda8ea598fa","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"五、音频预处理:先保证输入质量"}]},{"type":"paragraph","attrs":{"id":"e38a9bee-1304-48ad-9885-d2a037a6d706","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"说话人标注对音频质量比较敏感。会议室回声、多人同时说话、远距离拾音、麦克风音量不均衡,都会影响聚类效果。"}]},{"type":"paragraph","attrs":{"id":"7629c376-91a5-4dfc-af56-31fee48e5e5b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"进入模型前,建议先统一音频格式:"}]},{"type":"codeBlock","attrs":{"id":"33642618-d5a5-4c85-a729-ba30d945ee2b","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"ffmpeg -y -i input.m4a -ar 16000 -ac 1 output.wavn"}]},{"type":"paragraph","attrs":{"id":"d52b570d-d489-4f9f-b17d-de56d425ae3b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"批量转换目录:"}]},{"type":"codeBlock","attrs":{"id":"4e47a99a-11a2-42c4-9fd7-957c235e7f50","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"mkdir -p ./wav_meetingsnnfor file in ./raw_meetings/*; donname=$(basename "$file")nbase="${name%.*}"nffmpeg -y -i "$file" -ar 16000 -ac 1 "./wav_meetings/${base}.wav"ndonen"}]},{"type":"paragraph","attrs":{"id":"4795081b-da87-4f2f-8d25-63b6733d9a53","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"也可以封装成 Python 函数:"}]},{"type":"codeBlock","attrs":{"id":"4a5ac6fb-79d5-47a6-b698-11a56b5e55c2","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"from pathlib import Pathnfrom pydub import AudioSegmentnndef normalize_audio(input_path: str, output_dir: str = "./normalized") -> str:n"""n将会议录音统一转为 16kHz、单声道 WAV。n"""ninput_path = Path(input_path)noutput_dir = Path(output_dir)noutput_dir.mkdir(parents=True, exist_ok=True)nnoutput_path = output_dir / f"{input_path.stem}.wav"nnaudio = AudioSegment.from_file(input_path)naudio = audio.set_frame_rate(16000).set_channels(1)naudio.export(output_path, format="wav")nnreturn str(output_path)n"}]},{"type":"paragraph","attrs":{"id":"400400d9-820b-4b33-8e88-aa5dc9a7fa36","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"对于发言人标注而言,音频预处理不是可有可无的步骤。输入质量越稳定,后续说话人聚类、声纹比对和时间轴对齐就越可靠。"}]},{"type":"heading","attrs":{"id":"dc13e1f1-f7d1-48f3-83ad-db47d1e47f38","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"六、从 speaker_id 到真实姓名:增加声纹注册表"}]},{"type":"paragraph","attrs":{"id":"f16b2ba5-f2a8-44ab-9790-9ee3e8bc19ca","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"CAM 可以帮助系统判断不同音频片段是否属于同一个说话人,但它本身不会知道这个人是谁。"}]},{"type":"paragraph","attrs":{"id":"25a5eb6b-a6e2-44a3-b3fc-ce87913431b7","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"要从 "},{"type":"text","marks":[{"type":"code"}],"text":"Speaker 0"},{"type":"text","text":" 进一步映射到真实姓名,需要建立声纹注册表。"}]},{"type":"paragraph","attrs":{"id":"c4cb9e69-6749-460d-9501-fdc0d9cc2bed","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"基本思路如下:"}]},{"type":"codeBlock","attrs":{"id":"59611adc-8cee-43de-b34a-f058ad651c0c","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"参会人预先录入一段注册音频n↓nCAM 提取注册音频的声纹向量n↓n会议中提取每个 speaker_id 的声纹向量n↓n计算相似度n↓n匹配到已注册人员n↓n输出真实姓名 发言内容n"}]},{"type":"paragraph","attrs":{"id":"c6f23f86-3099-4be4-a1a6-31484a027843","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"可以先设计一个简单的注册信息结构:"}]},{"type":"codeBlock","attrs":{"id":"69233e07-e43e-4c02-ba9c-b8dacf9701ce","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"{n"speaker_profiles": [n{n"user_id": "u001",n"name": "张主任",n"voice_sample": "./profiles/zhang.wav"n},n{n"user_id": "u002",n"name": "李工",n"voice_sample": "./profiles/li.wav"n},n{n"user_id": "u003",n"name": "王经理",n"voice_sample": "./profiles/wang.wav"n}n]n}n"}]},{"type":"paragraph","attrs":{"id":"9370d2c1-eccf-4179-ad82-8cb2e98c0006","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"实际系统中,声纹注册不建议放在普通文件里长期保存。更稳妥的做法是保存声纹特征向量,并结合权限、加密和审计策略管理。"}]},{"type":"paragraph","attrs":{"id":"edf7df86-159b-493e-9cfc-68c19ecb4b9b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"身份映射后的会议片段可以变成:"}]},{"type":"codeBlock","attrs":{"id":"d4e5d80d-f0f1-47a7-8ecd-aa41bd69c6ce","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"[n{n"speaker_id": "Speaker 0",n"speaker_name": "张主任",n"start_ms": 680,n"end_ms": 3620,n"text": "今天我们先确认部署时间。"n},n{n"speaker_id": "Speaker 1",n"speaker_name": "李工",n"start_ms": 4050,n"end_ms": 8120,n"text": "接口联调需要提前完成,否则会影响后续测试。"n}n]n"}]},{"type":"paragraph","attrs":{"id":"78590505-a88c-455d-b26b-88d82c760385","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这一步完成后,会议记录就不再只是“发言人 1 / 发言人 2”,而是可以进入更明确的责任归属和事项追踪。"}]},{"type":"heading","attrs":{"id":"ea501d5f-f5b4-4244-bf2c-77d75ead8dd2","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"七、封装接口:把发言人标注变成内部服务"}]},{"type":"paragraph","attrs":{"id":"0a1ea018-f687-4462-9db4-5e1f42e4c633","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"脚本推理适合验证,不适合长期作为业务系统接口。更稳妥的方式是把发言人标注封装成一个 HTTP 服务。"}]},{"type":"paragraph","attrs":{"id":"a191746f-b719-4cd5-9720-ec9a34bc7fbd","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"新建 "},{"type":"text","marks":[{"type":"code"}],"text":"speaker_server.py"},{"type":"text","text":":"}]},{"type":"codeBlock","attrs":{"id":"9d8b5bb0-1c15-4e44-ab08-2df5decf0c10","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"import timenimport tempfilenfrom pathlib import Pathnfrom typing import Optionalnnfrom fastapi import FastAPI, UploadFile, File, Formnfrom pydantic import BaseModelnfrom funasr import AutoModelnnapp = FastAPI(title="Meeting Speaker Label Service", version="1.0.0")nnmodel = AutoModel(nmodel="paraformer-zh",nvad_model="fsmn-vad",npunc_model="ct-punc",nspk_model="cam ",ndevice="cuda:0",n)nnclass SpeakerSegment(BaseModel):nspeaker_id: strnstart_ms: intnend_ms: intntext: strnnclass SpeakerResponse(BaseModel):ntext: strnprocess_sec: floatnsegments: list[SpeakerSegment][email protected]("/health")ndef health_check():nreturn {n"status": "ok",n"asr": "paraformer-zh",n"spk_model": "cam "n}[email protected]("/speaker-label", response_model=SpeakerResponse)nasync def speaker_label(naudio_file: UploadFile = File(...),nlanguage: Optional[str] = Form(default="zh"),n):nsuffix = Path(audio_file.filename).suffix or ".wav"nnwith tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:ntmp.write(await audio_file.read())ntmp_path = tmp.namennstart_time = time.time()nnresult = model.generate(ninput=tmp_path,nbatch_size_s=60,n)nnprocess_sec = time.time() - start_timennall_text = result[0].get("text", "")nsegments = []nnfor sentence in result[0].get("sentence_info", []):nsegments.append({n"speaker_id": str(sentence.get("spk", "unknown")),n"start_ms": int(sentence.get("start", 0)),n"end_ms": int(sentence.get("end", 0)),n"text": sentence.get("text", ""),n})nnreturn {n"text": all_text,n"process_sec": round(process_sec, 3),n"segments": segments,n}n"}]},{"type":"paragraph","attrs":{"id":"3f048dbd-7242-402e-97ee-b6a56ad46599","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"启动服务:"}]},{"type":"codeBlock","attrs":{"id":"7513fe2c-19c5-48cc-8a0b-fe59ca38ea2e","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"uvicorn speaker_server:app --host 0.0.0.0 --port 7863n"}]},{"type":"paragraph","attrs":{"id":"c65b2e26-c7c4-4034-a62b-2bb3bb453879","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"测试健康检查:"}]},{"type":"codeBlock","attrs":{"id":"f10bbe65-7d0b-4ed3-b154-dc0441b12cb4","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"curl http://127.0.0.1:7863/healthn"}]},{"type":"paragraph","attrs":{"id":"d561489b-c75a-4d76-a911-843ec17d543e","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"上传会议录音测试:"}]},{"type":"codeBlock","attrs":{"id":"22100d27-5780-4ebf-8203-a3117b3b7e90","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"curl -X POST "http://127.0.0.1:7863/speaker-label" n-F "audio_file=@./samples/meeting_two_speakers.wav"n"}]},{"type":"paragraph","attrs":{"id":"92bd8d73-a8bb-4b52-adde-505812d893eb","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"返回结果可以设计为:"}]},{"type":"codeBlock","attrs":{"id":"98a4e52e-af9d-4b3e-baf1-e180f7cf58d4","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"{n"text": "今天我们先确认部署时间。接口联调需要提前完成,否则会影响后续测试。那这个事项就先由运维侧跟进。",n"process_sec": 4.315,n"segments": [n{n"speaker_id": "0",n"start_ms": 680,n"end_ms": 3620,n"text": "今天我们先确认部署时间。"n},n{n"speaker_id": "1",n"start_ms": 4050,n"end_ms": 8120,n"text": "接口联调需要提前完成,否则会影响后续测试。"n},n{n"speaker_id": "0",n"start_ms": 8560,n"end_ms": 11900,n"text": "那这个事项就先由运维侧跟进。"n}n]n}n"}]},{"type":"paragraph","attrs":{"id":"507af83e-dc7b-4893-aa10-da65e43a12ac","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"到这里,CAM 相关能力就从脚本验证变成了可被会议系统调用的内部服务。"}]},{"type":"heading","attrs":{"id":"fb0b78ac-bddd-48da-b4d6-aed2c45fbf13","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"八、接入会议助手:发言人信息如何进入纪要生成"}]},{"type":"paragraph","attrs":{"id":"09e23ba2-729a-46f7-b50d-b8007ea02029","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"带说话人标签的转写结果,不能只停留在接口返回层。真正有用的是让它进入会议纪要和任务提取流程。"}]},{"type":"paragraph","attrs":{"id":"25fa0ede-d270-4c3d-97e5-b42911e33faa","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"在熙瑾会悟的处理链路中,"},{"type":"text","marks":[{"type":"code"}],"text":"segments"},{"type":"text","text":" 可以作为会议文本结构化输入。系统可以基于每个片段的 "},{"type":"text","marks":[{"type":"code"}],"text":"speaker_id"},{"type":"text","text":"、时间范围和文本内容继续整理会议摘要、议题、决策和待办事项。"}]},{"type":"paragraph","attrs":{"id":"3f243d6c-5c5c-4e7b-941b-152fa988e99b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"提交给后处理接口的数据可以设计为:"}]},{"type":"codeBlock","attrs":{"id":"4456bf1d-ff9f-44b7-8ac3-ebe486f3d043","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"import requestsnfrom datetime import datetimennMEETING_API = "http://127.0.0.1:18080/api/meeting/minutes/generate"nndef submit_to_meeting_system(speaker_result: dict):npayload = {n"meeting_title": "项目部署评审会",n"meeting_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),n"source": "campplus_speaker_label",n"speaker_label": True,n"transcript": speaker_result["text"],n"segments": speaker_result["segments"],n"output_format": {n"summary": True,n"topics": True,n"decisions": True,n"todos": True,n"speaker_view": Truen}n}nnresp = requests.post(MEETING_API, json=payload, timeout=300)nresp.raise_for_status()nreturn resp.json()n"}]},{"type":"paragraph","attrs":{"id":"ed9adee7-8466-4df2-97f2-95353fddabab","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"后续输出可以是:"}]},{"type":"codeBlock","attrs":{"id":"41cabaa9-2e3e-4667-92e6-e2659700874e","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"{n"summary": "本次会议主要讨论项目部署时间、接口联调计划和后续运维跟进安排。",n"topics": [n"部署时间确认",n"接口联调风险",n"运维跟进安排"n],n"decisions": [n"接口联调需要提前完成",n"部署事项由运维侧继续跟进"n],n"todos": [n{n"speaker": "Speaker 1",n"task": "提前完成接口联调",n"deadline": "本周五"n},n{n"speaker": "Speaker 0",n"task": "确认部署时间并同步参会人员",n"deadline": "本周内"n}n],n"speaker_view": [n{n"speaker": "Speaker 0",n"summary": "主要负责确认部署时间和后续安排。"n},n{n"speaker": "Speaker 1",n"summary": "主要补充接口联调风险和前置条件。"n}n]n}n"}]},{"type":"paragraph","attrs":{"id":"99523362-54b0-47a4-8f95-125001021c1f","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这类结构的价值在于,会议纪要不再只是一段摘要,而是可以保留“发言来源”。当后续需要复核某个结论或待办时,可以回到对应发言片段和时间范围。"}]},{"type":"heading","attrs":{"id":"69fe85fa-1faf-4f72-8571-c2c7b999377a","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"九、身份映射后的会议纪要效果"}]},{"type":"paragraph","attrs":{"id":"4c97b679-66ea-4d31-8ebb-d7eccf44ea23","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"如果已经建立参会人声纹库,并且完成了 "},{"type":"text","marks":[{"type":"code"}],"text":"speaker_id"},{"type":"text","text":" 到真实姓名的映射,会议纪要可以进一步变成:"}]},{"type":"codeBlock","attrs":{"id":"af67f6c8-9ae3-4a43-82d8-564550b46239","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"会议主题:项目部署评审会nn一、会议摘要n本次会议主要确认项目部署时间、接口联调计划和后续运维安排。nn二、主要发言n张主任:今天我们先确认部署时间。n李工:接口联调需要提前完成,否则会影响后续测试。n张主任:那这个事项就先由运维侧跟进。nn三、会议决策n1. 接口联调需要提前完成。n2. 运维侧负责跟进部署相关事项。nn四、待办事项n1. 李工:完成接口联调,截止时间本周五。n2. 运维侧:确认部署时间并同步项目组,截止时间本周内。n"}]},{"type":"paragraph","attrs":{"id":"b6e50799-e462-4fc6-acc2-20c4db0bea15","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这时,系统已经从“会议转写”进入“会议责任追踪”。"}]},{"type":"paragraph","attrs":{"id":"ebb5f84b-c28e-44c7-95fd-ea7c660fdb52","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"声纹识别不是为了把会议做得更复杂,而是为了减少会后整理成本:谁提出、谁确认、谁负责,能够在纪要生成时被保留下来。"}]},{"type":"heading","attrs":{"id":"9cb3f45c-efc3-4039-98a0-3cfc2afbb668","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"十、长会议场景:说话人标注要注意分段策略"}]},{"type":"paragraph","attrs":{"id":"636cbd5a-bd17-4189-8e1d-65d6897a70c3","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"长会议录音不建议一次性完整送入模型。更稳妥的方式是先进行分段,再进行识别和说话人标注。"}]},{"type":"paragraph","attrs":{"id":"7783b642-1b24-4ce2-8e7d-e3f60059ceec","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"简单的固定时长分段方式如下:"}]},{"type":"codeBlock","attrs":{"id":"8432a87f-b63e-46c4-9b70-4ab971750357","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"from pydub import AudioSegmentnfrom pathlib import Pathnndef split_audio_fixed(nwav_path: str,noutput_dir: str = "./segments",nchunk_ms: int = 180_000,noverlap_ms: int = 3_000,n):n"""n将长会议录音切成多个片段。nchunk_ms: 每段长度,默认 180 秒noverlap_ms: 相邻片段重叠,默认 3 秒n"""nwav_path = Path(wav_path)noutput_dir = Path(output_dir) / wav_path.stemnoutput_dir.mkdir(parents=True, exist_ok=True)nnaudio = AudioSegment.from_wav(wav_path)nsegments = []nnstart = 0nindex = 1nnwhile start < len(audio):nend = min(start chunk_ms, len(audio))nsegment = audio[start:end]nnsegment_path = output_dir / f"{wav_path.stem}_{index:04d}.wav"nsegment.export(segment_path, format="wav")nnsegments.append(str(segment_path))nnif end >= len(audio):nbreaknnstart = end - overlap_msnindex = 1nnreturn segmentsn"}]},{"type":"paragraph","attrs":{"id":"e8624dfd-3d46-4c88-9483-23a6c639047d","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"需要注意的是,分段会带来一个问题:不同片段里的 "},{"type":"text","marks":[{"type":"code"}],"text":"Speaker 0"},{"type":"text","text":" 不一定代表同一个人。"}]},{"type":"paragraph","attrs":{"id":"fc7b8e8d-c458-4fc9-b615-62a6b52b7185","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"因此,在长会议场景中,如果希望跨片段保持发言人一致,需要进一步做声纹向量级别的合并,而不能只依赖每个片段内部的 speaker 编号。"}]},{"type":"paragraph","attrs":{"id":"4b648ea5-b342-4865-a859-429deaa2bd45","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"更完整的长会议处理方式可以是:"}]},{"type":"codeBlock","attrs":{"id":"698aa0ce-b5bc-4a3e-94d8-455f7cb6fb6d","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"长会议录音n↓nVAD 或固定时长切分n↓n每段 ASR CAM 说话人标注n↓n提取每个 speaker_id 的声纹向量n↓n跨片段聚类或与注册声纹库比对n↓n统一 speaker_idn↓n生成全局会议发言记录n"}]},{"type":"paragraph","attrs":{"id":"2a8361a5-cc2b-45cf-bb41-db1238471124","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这一步对长会议尤其重要。否则,同一个人在第 1 段里是 "},{"type":"text","marks":[{"type":"code"}],"text":"Speaker 0"},{"type":"text","text":",在第 2 段里可能变成 "},{"type":"text","marks":[{"type":"code"}],"text":"Speaker 2"},{"type":"text","text":",后续纪要就会出现发言人混乱。"}]},{"type":"heading","attrs":{"id":"bb4ca728-d0a4-4f94-804f-a53b6638c529","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"十一、本地部署建议:声纹能力应与 ASR 服务解耦"}]},{"type":"paragraph","attrs":{"id":"ab8a6504-2a8f-4741-baed-d8f49876ecd7","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"在本地部署中,不建议把 ASR、声纹识别、会议后端、总结模型全部塞进一个服务里。更稳妥的方式是拆分部署,便于独立升级和排障。"}]},{"type":"paragraph","attrs":{"id":"a898bc4e-d01a-42f6-b7b3-14bcd735350f","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"一个较清晰的结构如下:"}]},{"type":"codeBlock","attrs":{"id":"c4431baa-63f1-46a6-98de-bc2ab3ca7983","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"Nginx / 网关n├── 会议系统前端n├── 会议系统业务后端n├── 文件服务:会议录音、附件、纪要文件n├── ASR 服务n├── 说话人标注服务:CAM n├── 会议总结模型服务n├── Redis / MySQL / Elasticsearchn└── 日志与监控n"}]},{"type":"paragraph","attrs":{"id":"84117fc6-2940-40bc-a5d9-aa2dec6774c8","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"说话人标注服务可以独立容器化:"}]},{"type":"codeBlock","attrs":{"id":"fe93031c-7758-4b63-aac1-0f43f690af59","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"version: "3.8"nnservices:nmeeting-speaker-label:nimage: meeting/speaker-label:campplusncontainer_name: meeting-speaker-labelnrestart: alwaysnports:n- "7863:7863"nvolumes:n- ./models:/app/modelsn- ./logs:/app/logsn- ./tmp:/app/tmpnenvironment:n- SPK_MODEL=cam n- ASR_MODEL=paraformer-zhn- VAD_MODEL=fsmn-vadn- PUNC_MODEL=ct-puncn- DEVICE=cuda:0ncommand: >nuvicorn speaker_server:appn--host 0.0.0.0n--port 7863n"}]},{"type":"paragraph","attrs":{"id":"75e936b6-cd38-4559-a51d-c1991fba0ef8","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"业务系统只需要配置说话人标注服务地址:"}]},{"type":"codeBlock","attrs":{"id":"3f331f20-8941-485b-abf9-61c49e55d179","language":"javascript","theme":"atom-one-dark","runtimes":0,"isHoverDragHandle":false,"key":"","languageByAi":"javascript"},"content":[{"type":"text","text":"SPEAKER_LABEL_PROVIDER=campplusnSPEAKER_LABEL_BASE_URL=http://meeting-speaker-label:7863nSPEAKER_LABEL_PATH=/speaker-labeln"}]},{"type":"paragraph","attrs":{"id":"ab4ac12f-ccaa-44e7-8f96-d7905e40fd3d","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"这样做的好处是:"}]},{"type":"paragraph","attrs":{"id":"50a69603-927d-405f-aaf3-5153b5ebb977","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"第一,ASR 模型和说话人模型可以独立升级。"}]},{"type":"paragraph","attrs":{"id":"193a1771-17ea-4bba-b500-cffe74fbb229","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"第二,说话人标注服务可以单独扩容 GPU 节点。"}]},{"type":"paragraph","attrs":{"id":"515b1904-069f-4d3e-9784-0f3e9ff1406e","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"第三,长会议场景下可以单独优化分段、聚类和声纹比对策略。"}]},{"type":"paragraph","attrs":{"id":"2165fe8e-9eb9-41ce-ad57-ca889eba48ba","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"第四,后续切换其他声纹模型时,不需要大改会议后端。"}]},{"type":"heading","attrs":{"id":"7c322986-b73c-4d72-ac65-399872e89c3e","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"十二、常见问题:CAM 接入会议系统容易踩的坑"}]},{"type":"heading","attrs":{"id":"6ac2a3fc-aa63-4401-926b-e3744ebe7f0d","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"1. Speaker 编号不等于真实姓名"}]},{"type":"paragraph","attrs":{"id":"3935e7d4-771d-42ee-99d1-46552a4fdc5e","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","marks":[{"type":"code"}],"text":"Speaker 0"},{"type":"text","text":"、"},{"type":"text","marks":[{"type":"code"}],"text":"Speaker 1"},{"type":"text","text":" 只是聚类编号。如果要映射成真实姓名,需要提前建立声纹注册库,并进行相似度匹配。"}]},{"type":"heading","attrs":{"id":"36d8ef1e-fe0d-4985-8c42-6e5ed47af4ce","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"2. 多人抢话会影响标注效果"}]},{"type":"paragraph","attrs":{"id":"e647bb2e-6a02-499d-b6da-df1ea3b02cfd","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"说话人分离更适合轮流发言。如果多人同时说话、抢话严重,模型可能难以准确判断发言边界。"}]},{"type":"heading","attrs":{"id":"b847a5e3-61e9-421f-b0ac-593f2626cfdb","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"3. 远距离拾音会影响声纹特征"}]},{"type":"paragraph","attrs":{"id":"ef544166-4764-4bc2-b961-d89b9220455b","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"会议室麦克风离发言人太远时,混响和噪声会影响声纹特征提取。条件允许时,应优先使用稳定的会议麦克风阵列。"}]},{"type":"heading","attrs":{"id":"b81713ea-4294-44aa-873d-b42c0facca05","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"4. 长会议需要跨片段统一 speaker"}]},{"type":"paragraph","attrs":{"id":"45d68e5e-3329-4244-b6d7-6d7379ca1bb9","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"分段处理后,同一个人在不同片段里的编号可能不一致。要解决这个问题,需要对声纹向量做跨片段聚类或注册库匹配。"}]},{"type":"heading","attrs":{"id":"9b048813-d31f-47d2-bb5b-193e8e84c74d","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"5. 声纹数据需要权限控制"}]},{"type":"paragraph","attrs":{"id":"54a6454b-906c-43b9-a8c1-5d347966c603","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"声纹属于敏感生物特征信息。正式系统中应避免随意保存原始注册音频,建议保存特征向量,并结合加密、权限控制、审计日志和数据生命周期策略管理。"}]},{"type":"heading","attrs":{"id":"9efbcf7e-a5dd-4f2a-8dc9-b716e1e1802c","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"十三、适用场景:哪些会议更需要自动标注发言人"}]},{"type":"heading","attrs":{"id":"a83dde38-9bd6-486e-9802-949c62daf733","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"1. 项目评审会"}]},{"type":"paragraph","attrs":{"id":"90c6623a-ae43-4d74-bc72-c9a2bd137f7c","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"项目评审中经常涉及风险、结论和待办。发言人标注可以帮助追溯决策来源。"}]},{"type":"heading","attrs":{"id":"0bbf1796-ab8e-47a9-845a-11b7eff0dcf3","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"2. 访谈和谈话记录"}]},{"type":"paragraph","attrs":{"id":"61068cb7-a5a8-4d3f-8bc5-61ba8e85e708","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"访谈场景中,提问者和回答者的边界很重要。说话人标注可以减少人工整理成本。"}]},{"type":"heading","attrs":{"id":"8f1a215f-df1c-4c45-8f1f-bca34bc2f70a","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"3. 专家研讨会"}]},{"type":"paragraph","attrs":{"id":"115ff474-4d3f-4828-a40a-39c9eabb8f60","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"多人围绕同一议题讨论时,系统可以保留不同专家的观点和发言顺序。"}]},{"type":"heading","attrs":{"id":"7b55036f-50b7-43ef-831e-b8c897a8204e","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"4. 医疗会诊和教学讨论"}]},{"type":"paragraph","attrs":{"id":"413e9c1f-2c61-49f5-90bc-18a81b8cfde7","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"多角色参与的讨论中,发言人标注有助于后续整理不同角色的意见。"}]},{"type":"heading","attrs":{"id":"933af0ef-5bbb-4d30-a3d8-c8c30dda2ee6","textAlign":"inherit","indent":0,"level":3,"isHoverDragHandle":false},"content":[{"type":"text","text":"5. 远程协作会议"}]},{"type":"paragraph","attrs":{"id":"3fe710fc-7c6c-4d80-989b-91bfdf8e0da7","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"线上会议中参会人较多,转写文本如果没有发言人标注,阅读成本会明显升高。"}]},{"type":"heading","attrs":{"id":"6c9b30bd-60b2-48f6-a0b9-397b0d38cdc2","textAlign":"inherit","indent":0,"level":2,"isHoverDragHandle":false},"content":[{"type":"text","text":"十四、总结:发言人标注让会议纪要更可追溯"}]},{"type":"paragraph","attrs":{"id":"5eff9f01-b46a-4a5d-85d8-cf459d37768e","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"从这次实践可以看到,CAM 解决的不是“识别文字”,而是帮助系统判断“这些话是谁说的”。"}]},{"type":"paragraph","attrs":{"id":"e806d393-a00b-4155-975a-e4674265cff8","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"ASR 负责把语音转成文本。"}]},{"type":"paragraph","attrs":{"id":"56bd5aea-2976-47da-b7af-0d51bf276f15","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"VAD 负责找到有效语音片段。"}]},{"type":"paragraph","attrs":{"id":"e9a7d130-cc81-48b3-a629-8ad6e6214595","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"CAM 负责提取声纹特征并辅助说话人标注。"}]},{"type":"paragraph","attrs":{"id":"f73c3b5b-909f-4697-9476-5ed904bc8f9f","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"标点模型负责恢复句子边界。"}]},{"type":"paragraph","attrs":{"id":"29551254-480a-4a57-af17-1ff1569a7ede","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"会议助手负责把这些结构化结果整理成纪要、待办和归档资料。"}]},{"type":"paragraph","attrs":{"id":"88bb40a7-a54f-4608-b428-0266c19c7dbb","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"在这条链路中,熙瑾会悟位于 ASR 和声纹识别之后的会议内容处理层。它接收带 speaker 信息的转写结果,再继续完成会议摘要、议题归纳、待办提取和资料检索。"}]},{"type":"paragraph","attrs":{"id":"d805063f-3204-4417-9d8a-9d423142b121","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"对于会议系统来说,发言人自动标注的价值不只是让文本更好看,而是让会议结论更容易追溯,让责任事项更容易确认,让历史资料更容易复用。"}]},{"type":"paragraph","attrs":{"id":"dc388394-030b-436d-b6d6-6846d6914c7d","textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false},"content":[{"type":"text","text":"当“说了什么”和“谁说的”能够同时进入会议纪要,AI 会议助手才真正从单纯转写工具,进入可管理、可追踪、可沉淀的会议内容处理阶段。"}]},{"type":"paragraph","attrs":{"id":null,"textAlign":"inherit","indent":0,"color":null,"background":null,"isHoverDragHandle":false}}]}","createTime":1783502033,"ext":{"closeTextLink":0,"comment_ban":0,"description":"","focusRead":0},"favNum":0,"html":"","isOriginal":0,"likeNum":0,
喜欢(0)

上一篇

后勤人手不够怎么管好变电所?安科瑞校园电力监控一站式方案

后勤人手不够怎么管好变电所?安科瑞校园电力监控一站式方案

下一篇

企业级知识工程与本体建模——系统的边界并非语义的边界

企业级知识工程与本体建模——系统的边界并非语义的边界
猜你喜欢