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请求,参数为一个音频文件,最后查看返回结果。

仓库地址

相关推荐
小约翰仓鼠2 小时前
vue3子组件获取并修改父组件的值
前端·javascript·vue.js
烛阴2 小时前
bignumber.js深度解析:驾驭任意精度计算的终极武器
前端·javascript·后端
你的人类朋友3 小时前
✍️Node.js CMS框架概述:Directus与Strapi详解
javascript·后端·node.js
啊~哈3 小时前
vue3+elementplus表格表头加图标及文字提示
前端·javascript·vue.js
xiaogg36783 小时前
vue+elementui 网站首页顶部菜单上下布局
javascript·vue.js·elementui
weixin_527550403 小时前
初级程序员入门指南
javascript·python·算法
钡铼技术ARM工业边缘计算机3 小时前
千元级PLC平台支持梯形图+Python双开发
javascript
高山我梦口香糖4 小时前
[electron]预脚本不显示内联script
前端·javascript·electron
拉不动的猪5 小时前
安卓和ios小程序开发中的兼容性问题举例
前端·javascript·面试
贩卖纯净水.6 小时前
浏览器兼容-polyfill-本地服务-优化
开发语言·前端·javascript