Vosk 离线语音识别编码指南:3步搞定多语言结果从乱码到干净中文
【免费下载链接】vosk-apiOffline speech recognition API for Android, iOS, Raspberry Pi and servers with Python, Java, C# and Node项目地址: https://gitcode.com/GitHub_Trending/vo/vosk-api
Windows 上跑完中文识别,输出 txt 打开全是???;Linux 上跑法语音频,结果却变成é。这是用 Vosk 离线语音识别做多语言字符编码时最常见的两种翻车现场,而且它们都跟模型本身没关系。
Vosk 怎么处理文本:乱码要查的3个编码边界
看 src/vosk_api.h 的接口签名,所有返回识别结果的函数都是const char*。也就是说:
| 环节 | 形态 | 编码归谁管 |
|---|---|---|
| 模型文件内部 | 二进制网络 + 词表文本 | 模型内文本是 UTF-8,由 libvosk 整体加载 |
| C 接口返回值(Result/PartialResult/FinalResult) | const char*原始字节 | 全链路假定 UTF-8,库只搬字节 |
| 语言绑定层(Python/Kotlin/C#) | 原生字符串对象 | 各绑定把字节转成自家字符串 |
所以 C 库从不管编码,出问题的只有两处:绑定层"字节→字符串"的解码,和你"字符串→文件/控制台"的写出。
另一个特例:ITN 后处理器
中文模型默认吐出"一六零"这种口语读法,想要"160"得走 ITN(逆文本规范化,把口语文本转回符号)后处理器。它在 C 库内部用 FST(有限状态转换器,理解成一张文本转换规则表即可)的 tagger 和 verbalizer 完成转换,输入输出依旧是 UTF-8。
🔧 第一次跑通:从下模型到拿到中文结果,三步走完
环境准备:装 vosk 并下载中文模型
这一步让 Python 绑定代你下载中文小模型,并解压进本地缓存目录。
pip install voskfrom vosk import Model model = Model(lang="zh-cn")做完这步你应该看到~/.cache/vosk(Windows 是%LOCALAPPDATA%\vosk)下多了 vosk-model-small-zh-cn-0.22 目录,Python 侧不用再做任何配置。
加载模型,一句拿到识别结果
把 wav 打开,按 4000 帧(16k 下约 0.25 秒)一块喂给识别器,返回完整句子时打印 JSON 里的text字段。
import json, wave from vosk import KaldiRecognizer wf = wave.open("chinese.wav", "rb") rec = KaldiRecognizer(model, wf.getframerate()) while True: data = wf.readframes(4000) if len(data) == 0: break if rec.AcceptWaveform(data): print(json.loads(rec.Result())["text"]) print(json.loads(rec.FinalResult())["text"])注意 Recognizer 的采样率传wf.getframerate(),跟着音频走,别手填 16000。做完这步你应该看到:Linux/macOS 终端里中文已经干净利落。
Kotlin 里正确解码 Vosk 返回结果
JVM 版走 JNA 调 libvosk,result拿到的已经是 String,唯一要防的是 JVM 进程默认编码:
java -Dfile.encoding=UTF-8 -jar vosk-demo.jar如果你在 Kotlin/Native 目标上,则自己显式解码 C 返回的字节串:
val text = String(validatingUTF8: jsonBytes)!!做完这步你应该看到:同一段 wav 两种语言的识别文本逐字一致,没有乱码。
中文乱码、法式 é?按语言族分,坑不一样
乱码的形态跟着文字体系走,咱们按语言族分,不列长清单。
| 语言族 | 典型症状 | 一行修复 |
|---|---|---|
| CJK(中日韩) | txt 打开是???或ÕäÕå | open("out.txt","w",encoding="utf-8").write(text) |
| 欧洲变音符(法/德/波兰) | é变é,典型双重编码 | sys.stdout.reconfigure(encoding="utf-8") |
| RTL(阿拉伯语等) | 顺序对但显示错位,记事本里从左边排 | open("ar.txt","w",encoding="utf-8-sig")(带 BOM 写) |
Python 绑定的模型自动下载缓存目录在 python/vosk/init.py 的 MODEL_DIRS 列表里,模型放哪儿、往哪儿找,看这一个文件就够。
Vosk UTF-8 配置与多语言切换:3 个"如果你遇到 X"判断
如果你遇到 Windows 控制台或文件里全是???,大概率是系统默认代码页 GBK 而 Vosk 输出的是 UTF-8:
set PYTHONUTF8=1 python test_simple.py如果你遇到网页里法语识别结果显示成é,大概率是响应头漏了 charset 声明:
res.setHeader("Content-Type", "text/plain; charset=utf-8");如果你遇到需要在同一进程里中英文切换,别指望换个模型再塞回同一个 Recognizer——Model 可以共享,Recognizer 是单线程的、绑定一条音频流,正确姿势是每种语言一个实例:
recs = {"zh": KaldiRecognizer(model_zh, 16000), "en": KaldiRecognizer(model_en, 16000)} print(json.loads(recs[lang].Result())["text"])上线前一张检查清单
- 音频 16000Hz 单声道 16-bit,与 Recognizer 采样率一致
- 文件写出全部显式
encoding="utf-8" - Windows 环境已设
PYTHONUTF8=1 - 每种语言独立 Recognizer,不切换模型
- 数字、单位输出已接 ITN 后处理器
现在就拿一段 16000Hz 的中文 wav,跑一遍上面第二步的代码,终端干净打出"你好"两个字,你的编码配置才算真正过关。
【免费下载链接】vosk-apiOffline speech recognition API for Android, iOS, Raspberry Pi and servers with Python, Java, C# and Node项目地址: https://gitcode.com/GitHub_Trending/vo/vosk-api
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考