Amazonのアソシエイトとして、ラズパイダ(raspida.com)は適格販売により収入を得ています。詳しくは当サイトの プライバシーポリシーをご覧ください。

話題のMoonshine VoiceをRaspberry Pi OSで使うためにインストールや確認したことをまとめます。

  • テスト対象OS:Raspberry Pi OS Lite
  • STTエンジン:Moonshine Voice

検証環境

  • Model: Raspberry Pi 5 Model B Rev 1.1 (MEM16GB)
  • OS: Debian GNU/Linux 13 (trixie)
  • Kernel: 6.12.62+rpt-rpi-2712
  • Python 3.13.5

Python環境の構築

Python 3.13.5の環境で、以下のように準備します。

sudo apt update
sudo apt full-upgrade -y

sudo apt install -y \
python3-pip \
python3-venv \
portaudio19-dev

プロジェクト用にディレクトリを作成

mkdir stt-meeting
cd stt-meeting

Python仮想環境にして必要なパッケージをインストール

python3 -m venv venv
source venv/bin/activate

Moodshineのインストール

pip install --upgrade moonshine-voice

Moodshineのモデルをダウンロードは、通常だとenですが、日本語モデル(base)をダウンロードします。

cd ~/stt-meeting
python -m moonshine_voice.download --language ja

# 指定しないと通常はbase/en
python -m moonshine_voice.download moonshine/base --output models

モデルのパス(Path)は以下のように.cacheに入っていた。コード内で指定するから控えておく。

/home/raspida/.cache/moonshine_voice/download.moonshine.ai/model/base-ja/quantized/base-ja

実際にコード内で呼び出すときは、モデルへのパスをそのまま指定する。

追加インストール

以下のパッケージ類も使うので、入っていなければインストールしておく。

pip install sounddevice
pip install numpy

■Pi 5は8GBモデルがオススメ

USBマイクの確認

マイクのデバイス番号はコードで必要なため調べておく。

arecord -l

**** List of CAPTURE Hardware Devices ****
card 2: AK5371 [AK5371], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

もしくはマイクの詳細をpythonで実行。

python3 -c "import sounddevice as sd; print(sd.query_devices())"

大抵のUSBマイクはUSB Audioとして認識されています。

  0 vc4-hdmi-0: MAI PCM i2s-hifi-0 (hw:0,0), ALSA (0 in, 2 out)
> 1 AK5371: USB Audio (hw:2,0), ALSA (2 in, 0 out)
  2 sysdefault, ALSA (0 in, 128 out)
  3 hdmi, ALSA (0 in, 2 out)
< 4 default, ALSA (0 in, 128 out)

対応サンプリングレートの確認スクリプト

単に「録音できるか」だけでなく、**「音声認識に適している指定したサンプリングレート(16kHz)をハードウェアが正しく受け入れているか」を厳格にチェックし、さらに「録音された波形の音量(振幅)が適切か」**を診断するスクリプトです。

mic_health_check.pyなどと名前を付けて実行してみてください。

import sounddevice as sd
import numpy as np
import time

def check_microphone(device_id, target_rate=16000):
    print(f"--- マイク診断開始 (Device ID: {device_id}) ---")

    # 1. ハードウェアの対応状況を確認
    try:
        dev_info = sd.query_devices(device_id)
        print(f"【1】デバイス名: {dev_info['name']}")
        print(f"    デフォルト・レート: {dev_info['default_samplerate']} Hz")
    except Exception as e:
        print(f"エラー: デバイスが見つかりません。 {e}")
        return

    # 2. 16kHz/モノラルでの録音テスト
    print(f"\n【2】16kHz/モノラルでの動作テスト中...", end="", flush=True)
    duration = 3  # 3秒間テスト
    try:
        # 実際にそのレートで録音を試みる
        recording = sd.rec(int(duration * target_rate), samplerate=target_rate, channels=1, dtype='float32', device=device_id)
        sd.wait()
        print(" [成功]")
        print("    → このマイクは16kHz入力をハードウェアでサポートしています。")
    except Exception as e:
        print(" [失敗]")
        print(f"    → 16kHzは非対応のようです。エラー内容: {e}")
        return

    # 3. 音量(感度)のチェック
    rms = np.sqrt(np.mean(recording**2))
    peak = np.max(np.abs(recording))
    print(f"\n【3】入力レベル確認 (3秒間の平均)")
    print(f"    平均音量 (RMS): {rms:.4f}")
    print(f"    最大音量 (Peak): {peak:.4f}")

    if peak < 0.01:
        print("    [警告] 音が非常に小さいです。マイクがミュートされているか、感度が低すぎます。")
    elif peak > 0.98:
        print("    [警告] 音が割れています(クリッピング)。マイクのゲインを下げてください。")
    else:
        print("    [良好] 適切な入力レベルです。")

    print("\n--- 診断完了 ---")
    if target_rate == 16000:
        print("判定: このマイクはMoonshine STTに最適な設定で動作可能です!")

if __name__ == "__main__":
    # デバイスリストを表示して、'USB Audio' という名前が含まれるものを探す
    devices = sd.query_devices()
    print("--- 認識されているデバイス一覧 ---")
    target_id = None
    for i, dev in enumerate(devices):
        print(f"ID {i}: {dev['name']} (入力: {dev['max_input_channels']}ch)")
        # 新しいマイクが届いたら、名前に 'USB' や 'PR-SK95CK' が入っているものを自動選択
        if dev['max_input_channels'] > 0 and 'USB' in dev['name']:
            target_id = i

    if target_id is not None:
        print(f"\n自動選択されたデバイス ID {target_id} でテストを開始します。\n")
        check_microphone(target_id)
    else:
        print("\nマイク(入力デバイス)が見つかりませんでした。")

手持ちの16kHzに対応していないAK5371を実行すると、結果はちゃんと"失敗"と判別されました。

python3 mic_health_check.py
--- 認識されているデバイス一覧 ---
ID 0: AK5371: USB Audio (hw:0,0) (入力: 2ch)
ID 1: vc4-hdmi-0: MAI PCM i2s-hifi-0 (hw:1,0) (入力: 0ch)
ID 2: sysdefault (入力: 128ch)
ID 3: spdif (入力: 2ch)
ID 4: default (入力: 128ch)

自動選択されたデバイス ID 0 でテストを開始します。

--- マイク診断開始 (Device ID: 0) ---
【1】デバイス名: AK5371: USB Audio (hw:0,0)
    デフォルト・レート: 44100.0 Hz

【2】16kHz/モノラルでの動作テスト中...Expression 'paInvalidSampleRate' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2048
Expression 'PaAlsaStreamComponent_InitialConfigure( &self->capture, inParams, self->primeBuffers, hwParamsCapture, &realSr )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2718
Expression 'PaAlsaStream_Configure( stream, inputParameters, outputParameters, sampleRate, framesPerBuffer, &inputLatency, &outputLatency, &hostBufferSizeMode )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2842
 [失敗]
    → 16kHzは非対応のようです。エラー内容: Error opening InputStream: Invalid sample rate [PaErrorCode -9997]

対応していないならUSBマイクは見直そう

マイク(hw:1,0)で、強制的に16kHz/1chで録音を試みるコマンド

arecord -D hw:1,0 -r 16000 -f S16_LE -c 1 -d 5 test.wav

このとき、エラーで詳しいことが分かりました。

Warning: rate is not accurate (requested = 16000Hz, got = 11025Hz)
         please, try the plug plugin
Recording WAVE 'test-16khz.wav' : Signed 16 bit Little Endian, Rate 11025 Hz, Mono

このマイクのハードウェア(またはドライバ)は、16kHzというサンプリングレートを直接扱うことができず、代わりにさらに低い 11,025Hz に落とされていました。

11,025Hzまで落ちると、高音域の成分が削られすぎてしまい、Moonshineの認識精度(特に「さ行」や「た行」の区別)が劇的に悪化します。

これはこのマイクでハルシネーション(誤認)が起きていた物理的な要因の一つです。

Rブラック Rブラック
ちょっとマイクを買いなおそう
Rレッド Rレッド
でも、安価な製品だと固定されているのが多いのが実情です。
Rグリーン Rグリーン
音声認識にちょうど良いのがあったら、またお知らせしますね。