Vosk-api学习路径:从入门到专家的完整指南

Vosk-api学习路径:从入门到专家的完整指南

【免费下载链接】vosk-api vosk-api: Vosk是一个开源的离线语音识别工具包,支持20多种语言和方言的语音识别,适用于各种编程语言,可以用于创建字幕、转录讲座和访谈等。 【免费下载链接】vosk-api 项目地址: https://gitcode.com/GitHub_Trending/vo/vosk-api

1. 什么是Vosk-api?

Vosk-api是一个开源离线语音识别工具包,支持20多种语言和方言,适用于各种编程语言。它可以在本地设备上实现高效的语音识别,无需云端连接,保护用户隐私的同时保证识别速度。

1.1 Vosk-api核心优势

特性Vosk-api云端API其他离线方案
延迟低(毫秒级)高(网络延迟)
隐私完全本地处理数据上传云端完全本地处理
网络无需网络必须联网无需网络
模型大小50-200MB不适用通常>1GB
内存占用低(<500MB)不适用高(>2GB)
识别速度实时(甚至更快)受网络影响接近实时
自定义能力
多语言支持20+种通常10+种有限

1.2 Vosk-api架构概览

mermaid

2. 快速入门

2.1 环境准备

2.1.1 安装Vosk-api

Python:

pip install vosk

Java:

<dependency>
    <groupId>org.vosk</groupId>
    <artifactId>vosk</artifactId>
    <version>0.3.45</version>
</dependency>

Node.js:

npm install vosk

C#:

Install-Package Vosk

Go:

go get github.com/alphacep/vosk-api/go
2.1.2 获取模型
# 中文模型
wget https://alphacephei.com/vosk/models/vosk-model-cn-0.22.zip
unzip vosk-model-cn-0.22.zip -d model

# 英文模型
wget https://alphacephei.com/vosk/models/vosk-model-en-us-0.22.zip
unzip vosk-model-en-us-0.22.zip -d model

2.2 基础语音识别示例

Python (test_simple.py):

#!/usr/bin/env python3

import wave
import sys

from vosk import Model, KaldiRecognizer, SetLogLevel

# 设置日志级别,-1禁用调试消息
SetLogLevel(0)

# 打开音频文件
wf = wave.open(sys.argv[1], "rb")
if wf.getnchannels() != 1 or wf.getsampwidth() != 2 or wf.getcomptype() != "NONE":
    print("音频文件必须是WAV格式的单声道PCM")
    sys.exit(1)

# 加载模型
model = Model(lang="en-us")

# 创建识别器
rec = KaldiRecognizer(model, wf.getframerate())
rec.SetWords(True)
rec.SetPartialWords(True)

# 处理音频
while True:
    data = wf.readframes(4000)
    if len(data) == 0:
        break
    if rec.AcceptWaveform(data):
        print(rec.Result())
    else:
        print(rec.PartialResult())

# 获取最终结果
print(rec.FinalResult())

Java (DecoderDemo.java):

package org.vosk.demo;

import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

import org.vosk.LogLevel;
import org.vosk.Recognizer;
import org.vosk.LibVosk;
import org.vosk.Model;

public class DecoderDemo {

    public static void main(String[] argv) throws IOException, UnsupportedAudioFileException {
        LibVosk.setLogLevel(LogLevel.DEBUG);

        try (Model model = new Model("model");
                    InputStream ais = AudioSystem.getAudioInputStream(
                        new BufferedInputStream(new FileInputStream("test.wav")));
                    Recognizer recognizer = new Recognizer(model, 16000)) {

            int nbytes;
            byte[] b = new byte[4096];
            while ((nbytes = ais.read(b)) >= 0) {
                if (recognizer.acceptWaveForm(b, nbytes)) {
                    System.out.println(recognizer.getResult());
                } else {
                    System.out.println(recognizer.getPartialResult());
                }
            }

            System.out.println(recognizer.getFinalResult());
        }
    }
}

Node.js (test_simple.js):

const vosk = require('vosk');
const fs = require("fs");
const { Readable } = require("stream");
const wav = require("wav");

const MODEL_PATH = "model";
const FILE_NAME = "test.wav";

if (!fs.existsSync(MODEL_PATH)) {
    console.log("请下载模型并解压到" + MODEL_PATH);
    process.exit();
}

vosk.setLogLevel(0);
const model = new vosk.Model(MODEL_PATH);

const wfReader = new wav.Reader();
const wfReadable = new Readable().wrap(wfReader);

wfReader.on('format', async ({ audioFormat, sampleRate, channels }) => {
    if (audioFormat != 1 || channels != 1) {
        console.error("音频文件必须是WAV格式的单声道PCM");
        process.exit(1);
    }
    
    const rec = new vosk.Recognizer({model: model, sampleRate: sampleRate});
    rec.setMaxAlternatives(10);
    rec.setWords(true);
    
    for await (const data of wfReadable) {
        const end_of_speech = rec.acceptWaveform(data);
        if (end_of_speech) {
            console.log(JSON.stringify(rec.result(), null, 4));
        }
    }
    
    console.log(JSON.stringify(rec.finalResult(), null, 4));
    rec.free();
});

fs.createReadStream(FILE_NAME).pipe(wfReader).on('finish', 
    function (err) {
        model.free();
});

2.3 音频要求与格式转换

Vosk对输入音频有特定要求:

  • 采样率:通常为16000Hz(部分模型支持8000Hz)
  • 格式:16位单声道PCM(WAV格式最常用)
  • 声道:单声道(Mono)

使用FFmpeg转换音频格式:

# 将MP3转换为符合要求的WAV
ffmpeg -i input.mp3 -ar 16000 -ac 1 -f s16le output.wav

# 查看音频文件信息
ffmpeg -i output.wav

3. 核心概念与API详解

3.1 模型(Model)

模型是Vosk的核心组件,包含了语音识别所需的所有数据和算法。

// 模型创建与释放
VoskModel *model = vosk_model_new("model_path");
vosk_model_free(model);

// 检查词汇表中是否包含某个词
int word_id = vosk_model_find_word(model, "hello");

模型文件结构:

model/
├── am/              # 声学模型
├── ivector/         # 说话人识别模型
├── conf/            # 配置文件
├── graph/           # 解码图
│   ├── HCLG.fst     # 解码网络
│   ├── words.txt    # 词汇表
│   └── phones.txt   # 音素表
└── README           # 模型说明

3.2 识别器(Recognizer)

识别器是处理音频流并生成文本的核心组件。

3.2.1 识别器工作流程

mermaid

3.2.2 识别器配置选项
# 设置日志级别
SetLogLevel(0)  # 0=正常, -1=禁用, >0=调试

# 创建识别器
rec = KaldiRecognizer(model, sample_rate)

# 启用词级时间戳
rec.SetWords(True)

# 启用部分结果中的词级信息
rec.SetPartialWords(True)

# 设置最大候选结果数量
rec.SetMaxAlternatives(5)

# 启用NLSML格式输出
rec.SetNLSML(True)

# 设置端点检测模式
rec.SetEndpointerMode(1)  # 0=默认, 1=短, 2=长, 3=很长

# 设置端点检测延迟
rec.SetEndpointerDelays(5.0, 0.5, 20.0)  # t_start_max, t_end, t_max
3.2.3 结果格式解析

完整结果(Result):

{
  "result": [
    {
      "conf": 1.000000,
      "end": 1.110000,
      "start": 0.870000,
      "word": "你好"
    },
    {
      "conf": 1.000000,
      "end": 1.530000,
      "start": 1.110000,
      "word": "世界"
    }
  ],
  "text": "你好世界"
}

部分结果(PartialResult):

{
  "partial": "你好"
}

最终结果(FinalResult):

{
  "result": [
    {
      "conf": 1.000000,
      "end": 1.110000,
      "start": 0.870000,
      "word": "你好"
    },
    {
      "conf": 1.000000,
      "end": 1.530000,
      "start": 1.110000,
      "word": "世界"
    }
  ],
  "text": "你好世界"
}

3.3 说话人识别模型(SpkModel)

Vosk支持说话人识别功能,可以识别不同的说话人。

from vosk import Model, SpkModel, KaldiRecognizer

# 加载语音识别模型和说话人模型
model = Model("model")
spk_model = SpkModel("model-spk")

# 创建识别器并关联说话人模型
rec = KaldiRecognizer(model, sample_rate)
rec.SetSpkModel(spk_model)

# 处理音频...
# 结果中将包含说话人特征向量"spk"

说话人识别结果示例:

{
  "result": [...],
  "text": "你好世界",
  "spk": [0.123, -0.456, 0.789, ...],
  "spk_frames": 120
}

4. 高级功能

4.1 麦克风实时识别

Python (test_microphone.py):

#!/usr/bin/env python3

import argparse
import queue
import sys
import sounddevice as sd

from vosk import Model, KaldiRecognizer

q = queue.Queue()

def int_or_str(text):
    """参数解析辅助函数"""
    try:
        return int(text)
    except ValueError:
        return text

def callback(indata, frames, time, status):
    """音频块回调函数(在单独线程中调用)"""
    if status:
        print(status, file=sys.stderr)
    q.put(bytes(indata))

parser = argparse.ArgumentParser(add_help=False)
parser.add_argument(
    "-l", "--list-devices", action="store_true",
    help="显示音频设备列表并退出")
args, remaining = parser.parse_known_args()
if args.list_devices:
    print(sd.query_devices())
    parser.exit(0)
    
parser = argparse.ArgumentParser(
    description=__doc__,
    formatter_class=argparse.RawDescriptionHelpFormatter,
    parents=[parser])
parser.add_argument(
    "-d", "--device", type=int_or_str,
    help="输入设备(数字ID或子串)")
parser.add_argument(
    "-r", "--samplerate", type=int, help="采样率")
parser.add_argument(
    "-m", "--model", type=str, help="语言模型; 如 en-us, fr, nl; 默认是 en-us")
args = parser.parse_args(remaining)

try:
    if args.samplerate is None:
        device_info = sd.query_devices(args.device, "input")
        # soundfile需要整数采样率,sounddevice提供浮点数
        args.samplerate = int(device_info["default_samplerate"])
        
    if args.model is None:
        model = Model(lang="en-us")
    else:
        model = Model(lang=args.model)

    with sd.RawInputStream(samplerate=args.samplerate, blocksize = 8000, 
                           device=args.device, dtype="int16", channels=1, 
                           callback=callback):
        print("#" * 80)
        print("按Ctrl+C停止录音")
        print("#" * 80)

        rec = KaldiRecognizer(model, args.samplerate)
        while True:
            data = q.get()
            if rec.AcceptWaveform(data):
                print(rec.Result())
            else:
                print(rec.PartialResult())
                
except KeyboardInterrupt:
    print("\n完成")
    parser.exit(0)
except Exception as e:
    parser.exit(type(e).__name__ + ": " + str(e))

4.2 多候选结果

启用多候选结果可以获取识别的多个可能文本及其置信度:

# 启用多候选结果
rec.SetMaxAlternatives(3)

# 处理音频...

# 解析结果
result = json.loads(rec.Result())
if "alternatives" in result:
    for i, alt in enumerate(result["alternatives"]):
        print(f"候选 {i+1}: {alt['text']} (置信度: {alt['confidence']:.2f})")

结果示例:

{
  "text": "你好世界",
  "alternatives": [
    { "text": "你好世界", "confidence": 0.97 },
    { "text": "你好是界", "confidence": 0.02 },
    { "text": "你好时间", "confidence": 0.01 }
  ]
}

4.3 自定义语法识别

对于特定场景,可以使用自定义语法来提高识别准确率:

# 创建带语法的识别器
grammar = '["你好", "再见", "谢谢", "不客气", "请", "对不起"]'
rec = KaldiRecognizer(model, sample_rate, grammar)

# 或者在运行时修改语法
rec.SetGrm('["打开灯", "关闭灯", "打开空调", "关闭空调"]')

语法格式支持多种模式:

// 简单列表
["是", "否", "不知道"]

// 带权重的选项
[{"command": "打开", "weight": 1.0}, {"command": "关闭", "weight": 0.5}]

// 更复杂的语法规则
{
  "rules": {
    "greeting": ["你好", "早上好", "下午好"],
    "farewell": ["再见", "拜拜", "下次见"],
    "command": ["打开 {device}", "关闭 {device}"],
    "device": ["灯", "电视", "空调"]
  },
  "start": ["greeting", "farewell", "command"]
}

4.4 逆文本规范化(ITN)

逆文本规范化可以将口语化表达转换为标准化格式:

from vosk import Processor

# 创建文本处理器
proc = Processor("itn_tagger.fst", "itn_verbalizer.fst")

# 处理文本
print(proc.process("我明天八点十五分出发"))  # 我明天8:15出发
print(proc.process("这个物品价值一千二百三十元"))  # 这个物品价值1230元
print(proc.process("他的电话号码是一二三三四五六七八九零"))  # 他的电话号码是1234567890

4.5 生成字幕(WebVTT)

Vosk可以生成带时间戳的字幕,适用于视频内容:

import sys
import subprocess
import json
import textwrap

from webvtt import WebVTT, Caption
from vosk import Model, KaldiRecognizer, SetLogLevel

SAMPLE_RATE = 16000
WORDS_PER_LINE = 7

SetLogLevel(-

【免费下载链接】vosk-api vosk-api: Vosk是一个开源的离线语音识别工具包,支持20多种语言和方言的语音识别,适用于各种编程语言,可以用于创建字幕、转录讲座和访谈等。 【免费下载链接】vosk-api 项目地址: https://gitcode.com/GitHub_Trending/vo/vosk-api

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值