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

仓库地址

相关推荐
祈澈菇凉26 分钟前
什么是 Vue 的自定义事件?如何触发和监听?
前端·javascript·vue.js
@大迁世界3 小时前
构建 Next.js 应用时的安全保障与风险防范措施
开发语言·前端·javascript·安全·ecmascript
is今夕4 小时前
postcss.config.js 动态配置基准值
javascript·vue.js·postcss
青茶绿梅*24 小时前
500字理透react的hook闭包问题
javascript·react.js·ecmascript
前端御书房4 小时前
Pinia 3.0 正式发布:全面拥抱 Vue 3 生态,升级指南与实战教程
前端·javascript·vue.js
NoneCoder5 小时前
JavaScript系列(84)--前端工程化概述
前端·javascript·状态模式
Minner-Scrapy5 小时前
Layer2 扩容解决方案详解
node.js·web3·区块链·mlnet·hardhat
Ranye1236 小时前
从 JS 到 Dart:语法基础
javascript·flutter·dart