Vosk实战指南:打造你的离线语音识别系统

在智能语音时代,语音识别不再是大厂的专属。你是否也想打造一个无需联网、实时高效、支持中文的语音识别系统?本文将带你从零上手开源神器 Vosk ,实现本地语音转文字,即使在树莓派等设备上也能运行顺畅。

一、什么是Vosk?

Vosk 是一个轻量级的离线语音识别引擎,支持多种语言,拥有跨平台的优势,能在低资源设备上实现实时识别。最棒的是,它完全开源,适合个人开发者、教育科研、边缘AI等场景使用。

Vosk 的核心优势包括:

  • 离线运行,无需联网,保障隐私

  • 支持中文等多种语言

  • 可运行于 Windows、Linux、macOS、Android、树莓派等平台

  • 资源占用低,适配低功耗设备

  • Python、C++、Java、Node.js等多语言接口支持

二、Vosk 适合用来做什么?

你可以用 Vosk 构建各种本地语音识别应用,例如:

  • 桌面语音笔记工具

  • 车载语音助手

  • 儿童教育类语音交互玩具

  • 语音触发报警系统

  • 面向听障人群的语音字幕提示器

如果你正在做AI自媒体内容、边缘AI设备开发、或者是语音UI设计,Vosk是一个值得深入了解的方案。

三、安装与环境准备

我们以 Python 环境为例进行快速上手,我测试的系统是Windows系统。

安装依赖

bash 复制代码
pip install vosk sounddevice

# sounddevice 用于从麦克风获取音频流。

下载中文模型

前往 https://alphacephei.com/vosk/models 下载中文模型,推荐从 vosk-model-small-cn-0.22 开始入手,解压到当前目录,我这里使用默认命名vosk-model-small-cn-0.22。

四、实战演示:实时中文语音转文字

下面是一个实时麦克风识别的完整Python示例。

python 复制代码
import sounddevice as sd
import queue
import json
from vosk import Model, KaldiRecognizer

q = queue.Queue()

def callback(indata, frames, time, status):
    q.put(bytes(indata))

# 加载模型
model = Model("vosk-model-small-cn-0.22") # 使用自己下载好的模型路径
recognizer = KaldiRecognizer(model, 16000)

# 打开麦克风输入
with sd.RawInputStream(samplerate=16000, blocksize=8000, dtype='int16',
                       channels=1, callback=callback):
    print("请开始说话(Ctrl+C 结束)")
    while True:
        data = q.get()
        if recognizer.AcceptWaveform(data):
            result = json.loads(recognizer.Result())
            print("识别结果:", result.get("text"))

只需几行代码,就能实现语音实时转文字,而且完全离线 ,无需联网。

五、其他相关用法

  • 识别结果延迟调整

尝试减小 blocksize 或优化麦克风质量。

  • 指定关键词识别

Vosk 支持关键词语法,例如限制识别词汇为 ["打开灯", "关闭灯"]:

python 复制代码
KaldiRecognizer(model, 16000, '["打开灯", "关闭灯"]')
  • 音频文件识别,这里只能是wav文件格式

可以用 wave 模块读取 .wav 文件输入到 recognizer 中。

六、总结

Vosk 是一个实用、可靠、开源的语音识别工具。如果你:

  • 想做语音类自媒体项目

  • 想开发边缘设备语音UI

  • 想离线转写会议记录

  • 想构建自己的语音助手

那么 Vosk 完全值得尝试。无论你是AI开发者,还是正在寻找语音识别解决方案的产品人,Vosk 都可能成为你项目中的关键一环。

七、延伸阅读推荐

附语音与音频文件语音识别工程代码(完整详细版):

python 复制代码
import os
import sys
import json
import queue
import re
import wave
import argparse
import subprocess
import tempfile
import sounddevice as sd
from typing import Optional, List
from vosk import Model, KaldiRecognizer

# 常量定义
AUDIO_SAMPLE_RATE = 16000
AUDIO_CHANNELS = 1
AUDIO_SAMPLE_WIDTH = 2  # 16位
FRAMES_PER_CHUNK = 4000

class AudioProcessor:
    @staticmethod
    def clean_spaces(text: str) -> str:
        """清理文本中的多余空格"""
        text = re.sub(r'([\u4e00-\u9fa5])\s+([a-zA-Z0-9])', r'\1\2', text)
        text = re.sub(r'([a-zA-Z0-9])\s+([\u4e00-\u9fa5])', r'\1\2', text)
        text = re.sub(r'\s+', ' ', text)
        return text.strip()

    @staticmethod
    def convert_audio(input_file: str, output_file: str) -> bool:
        """转换音频为Vosk兼容格式"""
        print(f"正在转换音频: {input_file} -> {output_file}")
        try:
            subprocess.run([
                "ffmpeg", "-y", "-i", input_file,
                "-ar", str(AUDIO_SAMPLE_RATE),
                "-ac", str(AUDIO_CHANNELS),
                "-sample_fmt", "s16",
                output_file
            ], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            return True
        except (subprocess.CalledProcessError, FileNotFoundError) as e:
            print(f"音频转换失败: {e}")
            return False

class VoskRecognizer:
    def __init__(self, model_path: str):
        if not os.path.exists(model_path):
            raise FileNotFoundError(f"模型目录不存在: {model_path}")
        self.model = Model(model_path)

    def recognize_file(self, filename: str) -> Optional[str]:
        """识别音频文件内容"""
        try:
            # 尝试打开音频文件
            try:
                wf = wave.open(filename, "rb")
            except wave.Error:
                # 创建resources/temp目录如果不存在
                temp_dir = os.path.join(os.path.dirname(__file__), "resources", "temp")
                os.makedirs(temp_dir, exist_ok=True)
            
                # 生成临时文件路径
                temp_path = os.path.join(temp_dir, "converted_temp.wav")

                
                if not AudioProcessor.convert_audio(filename, temp_path):
                    return None
                
                filename = temp_path
                wf = wave.open(filename, "rb")
                print("音频转换成功,开始识别...")

            # 检查音频格式
            if not self._check_audio_format(wf):
                print("音频格式不符合要求")
                return None

            # 开始识别
            rec = KaldiRecognizer(self.model, wf.getframerate())
            results = []

            while True:
                data = wf.readframes(FRAMES_PER_CHUNK)
                if not data:
                    break
                if rec.AcceptWaveform(data):
                    res = json.loads(rec.Result())
                    results.append(res.get("text", ""))

            final_text = " ".join(results)
            return AudioProcessor.clean_spaces(final_text)

        except Exception as e:
            print(f"识别过程中出错: {e}")
            return None
        finally:
            if 'wf' in locals():
                wf.close()
            if 'temp_path' in locals() and os.path.exists(temp_path):
                os.unlink(temp_path)

    def recognize_mic(self) -> None:
        """从麦克风实时识别"""
        q = queue.Queue()

        def callback(indata, frames, time, status):
            q.put(bytes(indata))

        rec = KaldiRecognizer(self.model, AUDIO_SAMPLE_RATE)
        print("请开始说话,按 Ctrl+C 退出:")

        try:
            with sd.RawInputStream(
                samplerate=AUDIO_SAMPLE_RATE,
                blocksize=8000,
                dtype='int16',
                channels=AUDIO_CHANNELS,
                callback=callback
            ):
                while True:
                    data = q.get()
                    if rec.AcceptWaveform(data):
                        res = json.loads(rec.Result())
                        text = res.get("text", "")
                        cleaned = AudioProcessor.clean_spaces(text)
                        print(f"识别结果: {cleaned}")
        except KeyboardInterrupt:
            print("\n录音识别已终止。")
        except Exception as e:
            print(f"麦克风识别出错: {e}")

    def _check_audio_format(self, wf: wave.Wave_read) -> bool:
        """检查音频格式是否符合要求"""
        return (
            wf.getnchannels() == AUDIO_CHANNELS and
            wf.getsampwidth() == AUDIO_SAMPLE_WIDTH and
            wf.getframerate() == AUDIO_SAMPLE_RATE
        )

def main():
    parser = argparse.ArgumentParser(description="Vosk 语音识别工具", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("--mode", choices=["mic", "file"], required=True, help="选择识别模式")
    parser.add_argument("--file", help="音频文件路径(file模式需要)")
    parser.add_argument("--model", default="models/vosk-model-small-cn-0.22", help="模型目录路径")
    
    args = parser.parse_args()

    try:
        recognizer = VoskRecognizer(args.model)
        
        if args.mode == "mic":
            recognizer.recognize_mic()
        elif args.mode == "file":
            if not args.file:
                print("错误: file模式需要指定--file参数")
                return
                
            if not os.path.isfile(args.file):
                print(f"错误: 文件不存在 - {args.file}")
                return
                
            result = recognizer.recognize_file(args.file)
            if result:
                print(f"\n最终识别结果:\n{result}")
    except Exception as e:
        print(f"程序运行出错: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()
相关推荐
IT_陈寒17 小时前
深入理解SpringBoot:核心原理与最佳实践
前端·人工智能·后端
wdf808817 小时前
重型车辆、矿山装备、汽车研发、CAE、自动驾驶和沃尔沃重型车辆研发工作站配置与本地AI部署指南
人工智能·自动驾驶·cfd·creo机械设计
Jsundoku17 小时前
第四章 机器学习 -- 马尔可夫决策过程
人工智能·机器学习·马尔可夫决策过程
江苏久众新视17 小时前
SOP流程AI视觉检测实战案例:基于安防相机与本地AI的产线防错防漏方案落地分享
人工智能·数码相机·视觉检测
东离与糖宝17 小时前
LLM基础学习笔记:看懂BLEU、ROUGE、PPL与三大模型架构
人工智能
IT研究室17 小时前
最新大数据毕业设计选题推荐-基于大数据的AI助手系统性软件缺陷评论挖掘与可视化-大数据-Spark-Hadoop-Bigdata
大数据·人工智能·课程设计
u13013017 小时前
GitHub 热榜项目:日榜(2026-10-30)
人工智能·github
超级架构师17 小时前
让 Fortran 模型自己调用 Agent:原生 Fortran 2008 实现深度剖析
人工智能·python·架构·机器人·开源·fortran
fly-iot17 小时前
【FDE知识库】(1):AI 编程时代开发语言选型分析,云使用go,企业用java,算法python,底层c
开发语言·人工智能·golang
郝学胜-神的一滴17 小时前
游戏设计:原型与开发 17:数字化系统里的思维体操
人工智能·游戏·游戏程序·游戏策划·游戏设计