Vosk 语音识别

vosk 是一个开源的语音识别工具,支持离线识别,支持多种语言,支持多种平台,支持多种语言模型,支持多种语言的语音数据训练。官方网站

本文我们将介绍如何在 Windows 平台上使用 nodejs 搭建一个 vosk 语音识别服务。

前置准备

  1. 下载微软的 Visual Studio 并选择安装c++桌面开发模块;
  2. 需要安装 python3.8 以上环境;
  3. 卸载 Windows-build-tools;
  4. 全局安装 node-gyp;
  5. node版本不能太低,需要支持esm,推荐版本18+;
  6. 去官网下载语言模型 下载地址

开始

首先创建一个项目。

bash 复制代码
npm init -y

然后安装项目依赖。

bash 复制代码
npm install vosk koa koa-bodyparser koa-router busboy

语音识别服务实现

1. Vosk 语音识别方法

首先我们先基于vosk实现一个识别语音方法,代码如下:

js 复制代码
import { existsSync } from 'node:fs';
import vosk from 'vosk';
import { Readable } from 'node:stream';
import wav from 'wav';

// 语言模型路径
const MODEL_PATH = './model/vosk-model-small-cn';

if (!existsSync(MODEL_PATH)) {
  console.log('模型不存在,请确认路径是否正确');
  process.exit();
}

/**
 * 语音识别
 * @param {stream} audioStream
 */
const identifyVoice = async (audioStream) => {
  return new Promise((resolve, reject) => {
    const wfReader = new wav.Reader();
    const wfReadable = new Readable().wrap(wfReader);

    wfReader.on('format', async ({ audioFormat, sampleRate, channels }) => {
      if (audioFormat !== 1 || channels !== 1) {
        reject('只支持单声道wav格式的音频文件');
        return;
      }

      try {
        const model = new vosk.Model(MODEL_PATH);
        const rec = new vosk.Recognizer({
          model: model,
          sampleRate: sampleRate
        });
        for await (const data of wfReadable) {
          rec.acceptWaveform(data);
        }

        const result = rec.result();
        rec.free();
        resolve(result.text);
      } catch (ex) {
        reject('语音识别失败');
      }
    });

    wfReadable.on('error', (err) => {
      reject('文件读取失败');
    });

    audioStream.pipe(wfReader);
  });
};

export default identifyVoice;

2. 搭建 http 服务

使用koa搭建一个http服务并添加一个识别语音接口,代码如下:

js 复制代码
import Koa from 'koa';
import Router from 'koa-router';
import bodyParser from 'koa-bodyparser';
import busboy from 'busboy';
import identifyVoice from './vosk.js';

const app = new Koa();
const router = new Router();
app.use(bodyParser());

router.post('/transcribe', async (ctx) => {
  /**
   * 将上传的音频流转换为文本
   * @returns {Promise<{code: number, text: string, msg: string}>}
   */
  const audioStreamToText = () => {
    const bb = busboy({ headers: ctx.req.headers });

    return new Promise((resolve, reject) => {
      bb.on('file', async (fieldname, stream, fileInfo) => {
        const { mimeType } = fileInfo;
        if (mimeType !== 'audio/wave') {
          reject({ code: 400, text: '', msg: '只支持wav格式的音频文件' });
          return;
        }

        const result = await identifyVoice(stream).catch((err) => {
          reject({ code: 500, text: '', msg: err });
        });

        resolve({ code: 200, text: result, msg: 'success' });
      });

      ctx.req.pipe(bb);
    });
  };

  const result = await audioStreamToText().catch((err) => {
    return err;
  });
  ctx.body = result;
});

app.use(router.routes()).use(router.allowedMethods());
app.listen(3000);

3. 测试

启动项目,然后使用postman类似工具,向你的服务发送post请求,参数为一个音频文件,最后查看返回结果。

仓库地址

相关推荐
窝子面7 小时前
手搓最简前后端协作-node
javascript·数据库
kyriewen8 小时前
我让AI给前端项目做了一次完整的Code Review——它和人类的差距,比我想的大得多
前端·javascript·ai编程
এ慕ོ冬℘゜9 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
hoLzwEge9 小时前
拯救低效调试!code-inspector-plugin 让代码定位如虎添翼
前端·前端框架·node.js
sugar__salt10 小时前
Vue3 表单双向绑定与响应式核心 API 技术详解
前端·javascript·vue.js
SmartBoyW10 小时前
CSS弹性布局(Flexbox)学习笔记:从零开始搞懂弹性布局
前端·javascript
用户9385156350710 小时前
写了这么久 useState,你真的知道它在干什么吗?
前端·javascript
烬羽11 小时前
递归老写崩?一个"退回"公式,把回溯题变成填空题
javascript·深度学习·算法
浮江雾12 小时前
Flutter第十七节-----路由管理(3)
android·开发语言·前端·javascript·flutter·入门
那些年丶ny13 小时前
颜色扩展库
前端·javascript·数据可视化