Files
kefu/deploy/review-voice-20260918/asr-implementation-report.md
T
2026-09-21 10:34:06 +08:00

47 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 本机离线语音转写实施与验证
2026-09-18。范围是客户端收到语音后的本机转写基础设施;聊天读取、未回复批次选择以及向模型传递由主线程集成。没有识别真实客户语音、发送消息或修改客户配置。
## 实现与文件
`C:/wechat_rpa` 和 `C:/kefu/wechat_rpa` 已同步以下内容:
- `voice_transcription.py`:绝对路径及账号根目录约束、SILK/AMR/WAV 解码、CPU int8 离线识别、单工作线程、有界队列、消息与音频 SHA256 隔离、失败退避和停止清理。
- `test_voice_transcription.py`:26 项合成回归;真实解码使用人工生成音频,模型对象边界使用替身。
- `packaging_asr.py`:明确收集模型文件、VAD 模型、CTranslate2 DLL、PyAV DLL、Python 模块及包元数据。
- `requirements.txt`、`wechat_rpa.spec`:只追加 ASR 依赖与打包输入,保留两目录原有打包差异。
- `assets/asr/faster-whisper-base/`:固定 revision 的公开模型及逐文件摘要、许可证。
原有 requirements/spec 备份在 `before-asr/`。依赖只安装到 `C:/wechat_rpa/.build-venv`,没有改全局 Python。
## 调用契约
`VoiceTranscriptionService(model_dir=None, allowed_roots=(), max_pending=32, retry_seconds=30.0, recognizer=None, max_cache=128)`。
`request(account, conv_id, server_id, audio_path)` 只校验文件元数据并排队,返回 `status=pending|ready|error`、`text`、`error_code`、`message`、`retry_at`、`audio_sha256`。成功另外返回 `duration_seconds` 和 `source=local_asr`。调用者重复查询相同消息即可读取完成结果;`close()` 停止新任务并清空结果。
缓存键同时包含账号、会话、服务端消息 ID 和音频 SHA256;文件内容变化会让旧结果失效。转写文本仅在进程内暂存,不写回企微数据库,不记录音频正文或转写日志。服务允许的音频上限是 8 MiB、120 秒;不支持的格式、空音频、低置信度或空识别均明确失败,不生成猜测文字。
## 已执行验证
1. Python 3.12 原生 `unittest test_voice_transcription -v`:26/26 通过,包含并发快速排队、账号/会话边界、关闭时不复活缓存、文件变化、失败退避、格式/大小/时长和低置信度边界。
2. `verify_real_offline_asr.py`:系统语音合成器生成同一段非客户中文语音,再转换为 SILK 和 AMR;实际本机模型全部转写成功。整个识别过程拦截 socket 与 DNS,网络尝试为 0。详情在 `real-offline-asr.json`。
3. WAV/SILK/AMR 语音约 9.5 秒;实测转写耗时分别约 4.27/2.19/2.30 秒,均保留“下午三点”“预约流程”的核心意思。这只是该机器该合成样本的耗时,不承诺一般性能。
4. 三种格式都把合成语音中的“识别”识为同音“时别”,证明输出并非逐字完全准确;保留原模型结果,不做编造性修正。未验证真实客户口音、背景噪声或业务术语准确率。
5. 实际本地缓存只做元数据及 16 字节文件头审计:5 条语音的引用均唯一映射到本账号缓存中的 `.silk` 文件,5/5 文件头为 SILK,没有对这些文件解码或转写。详情 `voice-reference-counts.json`。
6. 打包输入检查确认模型/VAD 与 CTranslate2、PyAV 原生库已被收集;完整安装包运行仍以冻结验证结果为准。
## 冻结包验证已完成
`verify_frozen_offline_asr.py` 已在最终 v1.4.27 dist 执行并通过(exit 0),总耗时 6.14 秒。脚本以构建 Python `-I -S` 启动,归档读取结束后去除构建环境 site-packages 和归档辅助模块;voice_transcription、NumPy、PyAV、pysilk、CTranslate2、faster-whisper、ONNX Runtime、tokenizers 全部确认从该 EXE 的 PYZ 导入。原生扩展、实际加载的 CTranslate2/AV/NumPy/ONNX DLL 和固定模型均来自目标 `_internal`,开发环境依赖泄漏、越界 DLL、网络及外部动作计数均为 0。
三个约 9.5 秒的人工语音样本均 `ready`,预约和三点语义检查通过:WAV 2.625 秒,SILK 1.485 秒,AMR 1.703 秒。详情是 `frozen-offline-asr.json/.log`。测试只覆盖人工语音,不代表真实客户音频准确率。
该次验证对应 EXE SHA256:`a1387fbd74ba38ee86bba7204d8d05124376c6dc7912e8243e7f0b4622ac28d7`。早前 `frozen-asr-build-blocked.json` 仅记录首次构建磁盘不足的历史阻塞,本次最终构建和识别验证已成功。
## 依赖依据
采用 [SYSTRAN/faster-whisper 官方项目](https://github.com/SYSTRAN/faster-whisper) 的 CPU int8 和本地模型方式;额外要求完整 tokenizer 文件存在,以防缺文件时触发在线 tokenizer 获取。模型来自 [固定公开模型 revision](https://huggingface.co/Systran/faster-whisper-base/tree/5ff83050b029cf4730c8c89ce0c835b2ea15c6f9),不是首次启动联网下载。
SILK 解码用 [silk-python 0.2.7](https://pypi.org/project/silk-python/0.2.7/) 的 CPython 3.12 Windows wheel,导入名为 `pysilk`。AMR/WAV 由 PyAV 在内存字节流中解码,不运行外部 ffmpeg,也不把文件路径或 URL 传给解码器。