[M1] 音声認識ツール Voskを動かす [Node]

2022.07.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Introduction

各所で話題の日本語音声認識ツール,Voskがすごいです。
実際やってみたところ、簡単なプログラムで日本語のリアルタイム音声認識ができました。
(M1非対応かと思ってたけど、なんか普通に動いた)
VoskのインストールからNodeで動かすところまでやっていきます。

Environment

  • OS : MacOS 12.4
  • Node : v18.2.0
  • yarn : 1.22.15

MacBook Pro (13-inch, M1, 2020)で動作確認。

Try

では実際にやってみます。
Githubにはいろいろなサンプルがありますが、
今回はこのシンプルなプログラムを使ってみます。
このサンプルはマイクから入力された音声を
日本語でコンソールに表示するだけのシンプルなものです。

まずは適当なディレクトリを作成し、voskをインストール。

% mkdir vosk-example && cd vosk-example
% yarn add vosk

そして、ここから日本語の
音声認識用機械学習モデル(vosk-model-small-ja-0.22)をダウンロードします。
ダウンロードしたら解凍してvosk-exampleにおいておきます。

次に、スクリプトファイルの作成。
Githubにあるサンプルほぼそのままです。

//main.js
const vosk = require("vosk");

//さきほどダウンロードしたモデルのパス
const MODEL_PATH = "./vosk-model-small-ja-0.22";

const fs = require("fs");
var mic = require("mic");

SAMPLE_RATE = 16000

if (!fs.existsSync(MODEL_PATH)) {
    console.log("Please download the model from https://alphacephei.com/vosk/models and unpack as " + MODEL_PATH + " in the current folder.")
    process.exit()
}

vosk.setLogLevel(0);
const model = new vosk.Model(MODEL_PATH);
const rec = new vosk.Recognizer({model: model, sampleRate: SAMPLE_RATE});

var micInstance = mic({
    rate: String(SAMPLE_RATE),
    channels: '1',
    debug: false,
    device: 'default',    
});

var micInputStream = micInstance.getAudioStream();

micInputStream.on('data', data => {
    if (rec.acceptWaveform(data))
        console.log(rec.result());
    else
        console.log(rec.partialResult());
});

micInputStream.on('audioProcessExitComplete', function() {
    console.log("Cleaning up");
    console.log(rec.finalResult());
    rec.free();
    model.free();
});

process.on('SIGINT', function() {
    console.log("\nStopping");
    micInstance.stop();
});

micInstance.start();

そして実行・・・したら、私の環境では↓のようなエラーがでました。

node:events:505
      throw er; // Unhandled 'error' event
      ^

Error: spawn rec ENOENT
    at ChildProcess._handle.onexit (node:internal/child_process:283:19)
    at onErrorNT (node:internal/child_process:476:16)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
Emitted 'error' event on ChildProcess instance at:
    at ChildProcess._handle.onexit (node:internal/child_process:289:12)
    at onErrorNT (node:internal/child_process:476:16)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'spawn rec',
  path: 'rec',
  spawnargs: [
    '-b',       '16',
    '--endian', 'little',
    '-c',       '1',
    '-r',       '16000',
    '-e',       'signed-integer',
    '-t',       'raw',
    '-'
  ]
}

Node.js v18.2.0

なんかいろいろしらべたところ、soxいれろとあったのでHomebrewでインストール。

% brew install sox

プログラムを起動して、「こんにちわ」と発声。
(ここでマイク入力許可を求められるかも)

% node main.js
LOG (VoskAPI:ReadDataFiles():model.cc:213) Decoding params beam=13 max-active=7000 lattice-beam=4
LOG (VoskAPI:ReadDataFiles():model.cc:216) Silence phones 1:2:3:4:5:6:7:8:9:10
LOG (VoskAPI:RemoveOrphanNodes():nnet-nnet.cc:948) Removed 0 orphan nodes.
LOG (VoskAPI:RemoveOrphanComponents():nnet-nnet.cc:847) Removing 0 orphan components.
LOG (VoskAPI:ReadDataFiles():model.cc:248) Loading i-vector extractor from ./vosk-model-small-ja-0.22/ivector/final.ie
LOG (VoskAPI:ComputeDerivedVars():ivector-extractor.cc:183) Computing derived variables for iVector extractor
LOG (VoskAPI:ComputeDerivedVars():ivector-extractor.cc:204) Done.
LOG (VoskAPI:ReadDataFiles():model.cc:282) Loading HCL and G from ./vosk-model-small-ja-0.22/graph/HCLr.fst ./vosk-model-small-ja-0.22/graph/Gr.fst
LOG (VoskAPI:ReadDataFiles():model.cc:303) Loading winfo ./vosk-model-small-ja-0.22/graph/phones/word_boundary.int
{ partial: '' }
{ partial: '' }
{ partial: '' }
{ partial: '今日' }
{ partial: '今日 は' }
{ partial: '今日 は' }
{ partial: '今日 は' }
{ text: '今日 は' }
{ partial: '' }
{ partial: '' }
{ partial: '' }
{ partial: '' }
^C
Stopping
{ partial: '' }
Cleaning up
{ text: '' }

しっかり認識してます。

Summary

とても簡単に日本語音声認識ができました。
これを元にいろいろと機能追加したり、他のサービスと組み合わせたりできそうです。

References