Mistral AIのスピーチアンダースタンディングモデル「Voxtral-Mini-3B」の日本語認識能力を検証してみた

ジェネラティブエージェンツの西見です。

2025年7月にMistral AIからスピーチアンダースタンディングモデル(speech understanding model)「Voxtral-Mini-3B」がリリースされました。「Introducing the world's best (and open) speech recognition models!」ということでしたが、公式ページで日本語の性能に関する言及がなかったので、本記事ではVoxtralとOpenAIのWhisperを比較検証してみたいと思います。また、macOSでVoxtralを実行する手順についても解説します。

Voxtralとは

Voxtralは、Mistral AIが2025年7月にリリースしたオープンソースのスピーチアンダースタンディングモデル(speech understanding model)です。スピーチアンダースタンディングモデルとは単なる音声認識(ASR)モデルではなく、音声の転写のみならず、音声から直接的な理解と対話を可能にするモデルです。Apache 2.0ライセンスで提供されています。

  1. ビルトインQ&A: 音声から直接質問に回答
  2. 要約機能: 長時間の音声を自動要約
  3. ファンクションコーリング: 音声から直接アクションを実行
  4. マルチモーダル: Mistral Small 3.1のテキスト理解能力を保持

提供されているモデルサイズは次の通りです。

  • Voxtral-24B: プロダクション規模のアプリケーション向け
  • Voxtral-Mini-3B: ローカル・エッジデバイス向け(今回の検証対象)

技術仕様は次の通りで、転写(音声からテキストに変換するタスク)には時間制限があります。

  • コンテキスト長: 32,000トークン
  • 転写可能時間: 最大30分(理解タスクでは40分)
  • 対応言語: 英語、スペイン語、フランス語、ポルトガル語、ヒンディー語、ドイツ語、オランダ語、イタリア語など(自動で言語検出は可能)

mistral.ai

検証環境と方法

今回の検証環境は次の通りです。

Mac Studio (2025) 
Apple M3 Ultra
Mem: 512GB
Storage: 4TB SSD
macOS 15.5

英語と日本語とで転写タスクの性能を比較していきます。

www.youtube.com

英語音声での検証

オバマ元大統領の退任演説(203秒)の認識精度を、gpt-4.1による評価で検証しました。

検証時の設定オプション

  • Voxtral: language="en", temperature=0.1, do_sample=True, max_new_tokens=2000
  • Whisper: language=None(英語デフォルト), temperature=0.1, max_new_tokens=500, pipeline使用(chunk_length_s=30)

検証結果

英語の音声認識では各モデル間に実質的な差はありませんでした。速度はWhisper-baseが最速でした。

モデル 意味の正確さ 重要情報の網羅率 処理時間
Whisper-large-v3 99% 99% 53.2秒
Voxtral-Mini-3B 98% 99% 43.6秒
Whisper-small 98% 98% 39.2秒
Whisper-base 98% 98% 25.1秒

実行時のメモリ使用量は次の表の通りです。Voxtralの方がモデルサイズが大きいのに、メモリ使用量はWhisper-large-v3よりも小さい結果になりました。

モデル メモリ使用量 モデルサイズ
Whisper-large-v3 1,460MB 1.55B
Voxtral-Mini-3B 1,104MB 3B
Whisper-small 550MB 244M
Whisper-base 257MB 74M

日本語音声での検証

続いて日本語音声についても検証していきます。日本語音声で良いデータがなかったため、弊社で提供している「【アーカイブ】初めてのDify講座 #3 RAG」の冒頭3分間を人間の手で書き起こししたデータとの比較で検証しています。

検証時の設定オプション

  • Voxtral: language="ja", temperature=0.1, do_sample=True, max_new_tokens=2000
  • Whisper: language="japanese", temperature=0.1, max_new_tokens=500, pipeline使用(chunk_length_s=30)

書き起こしデータ

今回も初めてのDify、第4回目ですね、開始していきたいと思います。皆様どうも、ご参加ありがとうございます。今日は、私ジェネラティブエージェンツの取締役の吉田と、Difyエキスパートのれみおさんの方から、初めてのDify、ウェビナーを開始したいと思います。先にちょっとですね、確認ですけれど、ウェビナーのチャット及びQ&Aがちゃんとワークしてるかちょっと確認したいので、どなたかよろしければ参加者側の人でテストを、チャットとQAの方、それぞれに入力していただいてもよろしいでしょうか?OKであれば進んでいきたいと思います。ありがとうございます。はい、Q&Aの方はオッケーですね。ライブで回答完了とさせていただきますと。はい。今日の、ウェビナーのXのハッシュタグは初めてのDifyになってますので、どしどし感想等あればXの方にもポストしてください。ていうわけで早速レミオさんの方にタッチして進めていきたいかなと思います。よろしくお願いいたします。
はい、承知しました。じゃあ、えっとですね、初めてのDify始めてさせていただきたいと思います。よろしくお願いいたします。はい、今回3回目になりますけども、そうですね。弊社ジェネラティブエージェンツという会社で、AIエージェントをですね、色々広めていくっていうところ活動している会社となります。運営メンバーは、今話された吉田含め、西見と大嶋3名で取締役の方をやっておりまして、私も、AIエージェントイノベーターという形で、Difyのエキスパートとして、推進等しております。はい。こちらのですね、4月にDifyで作る生成AIアプリ完全入門という本を出させていただいて、そしてDifyに関して、色々とですね、発信等をさせていただいております。はい。で、本日のアジェンダなんですけども、前半はですね、初めてのDifyっていうところもありますので、前回、前々回やったですね、Difyの基礎解説とかですね、ハンズオンのところを簡単におさらいしてから、で、今日はですね、RAGの、ナレッジ機能ですね、ナレッジ機能を使った、簡単な社内規定アプリっていうところをですね、ハンズオンでじっくり、あの、ご説明させていただければなと思います。はい。じゃあでは早速、時間もですね、1時間というところの、限られた時間ですので、早速開始させていただきます。よろしくお願いいたします。はい。ここら辺の、おさらいのところは簡単に流していきますね。えっと、Difyとは

検証結果

実行してみた結果、Whisperのlarge-v3が最も正確に書き起こしできるという結果になりました。

モデル 意味の正確さ 重要情報の網羅率 処理時間
Whisper-large-v3 85% 88% 46.8秒
Voxtral-Mini-3B 85% 80% 41.4秒
Whisper-small 72% 75% 22.8秒
Whisper-base 65% 60% 20.9秒

実際の転写例(冒頭部分)

ただ、Voxtralによる書き起こしの方が、人間が見た感じだと句読点も自然に挿入される感じがあります。DifyをDeFiと出力してしまうのは、各モデル共通の現象でした。

人間の書き起こし

今回も初めてのDify、第4回目ですね、開始していきたいと思います。皆様どうも、ご参加ありがとうございます...

Voxtral転写結果

今回も初めてのDeFi、4回目ですかね、始めていきたいと思います。皆様、どうも、ご参加ありがとうございます...

Whisper転写結果

今回も初めてのDeFi第4回目ですかね 開始していきたいと思います皆さまどうもご参加ありがとうございます...

プロンプトによる転写精度の検証

Voxtralは音声とテキストを組み合わせた会話形式(apply_chat_template)もサポートしています。プロンプトによって精度が変わるか検証するため、様々なプロンプトパターンを試してみました。

プロンプト(完全版) 類似度 処理時間 問題点
基本転写(apply_transcrition_request、プロンプトなし) 73.9% 41.9秒 なし
Transcribe as plain text. Start immediately with the first word spoken. 77.3% 30.9秒 タイムスタンプ混入
Transcribe audio. Start with the very first word. Plain text output. 75.3% 30.1秒 タイムスタンプ混入
Japanese webinar. Transcribe exactly. 67.5% 30.0秒 タイムスタンプ混入
Transcribe exactly what is spoken. Output only the transcription, nothing else. 65.9% 30.7秒 タイムスタンプ混入
No introduction. Start transcribing from first word. 60.6% 54.9秒 タイムスタンプ混入
Plain text transcription. Start with first word. 59.8% 72.0秒 タイムスタンプ混入
この音声を一字一句正確に日本語で書き起こしてください。何も付け加えず、音声の内容のみを出力してください。 55.0% 25.3秒 精度低下
音声を転写してください。 46.1% 24.9秒 余計な文章追加
This is a Japanese webinar about Dify (a no-code tool). Transcribe the audio verbatim, preserving every word exactly as spoken. 20.2% 164.1秒 ヒント文が混入

会話形式(apply_chat_template)使用時は必ずタイムスタンプが追加されるようなのと、設定したところで精度が向上する訳ではないということで、単に書き起こしを行う目的だけであれば、何も設定しない方が良さそうです。

macOSでのVoxtral実行手順

ここからは、実際にVoxtralをmacOSで動かすための手順を解説します。

依存関係のインストール

パッケージ管理にはuvを利用します。transformersは最新版でないとVoxtralが動作しなかったので、最新版をgitで入れています。

# 基本パッケージのインストール
uv add torch torchvision torchaudio
uv add soundfile scipy numpy

# transformersの最新版をインストール
uv add git+https://github.com/huggingface/transformers.git

pyproject.tomlに以下を追加。

[tool.uv.sources]
transformers = { git = "https://github.com/huggingface/transformers.git" }

HuggingFace認証の設定

動作のためにはHuggingFaceの認証が必要です。CLIでログインするか、トークンを環境変数に設定してください。

# Hugging Face CLIのインストール
pip install huggingface_hub

# トークンでログイン
huggingface-cli login

トークンを環境変数に設定する場合は、スクリプト実行前に次のコマンドをシェルで実行してください。

export HF_TOKEN="your_hugging_face_token_here"

実装例

import torch
import soundfile as sf
import numpy as np
from scipy import signal
from transformers import VoxtralForConditionalGeneration, VoxtralProcessor

def transcribe_audio(audio_path):
    """基本的な転写(transcription)"""
    model_name = "mistralai/Voxtral-Mini-3B-2507"
    processor = VoxtralProcessor.from_pretrained(model_name, trust_remote_code=True)
    model = VoxtralForConditionalGeneration.from_pretrained(
        model_name, torch_dtype=torch.float16, trust_remote_code=True
    )
    
    device = "mps" if torch.backends.mps.is_available() else "cpu"
    model = model.to(device)
    
    # 音声転写用の処理
    audio_data, original_sr = sf.read(audio_path)
    if len(audio_data.shape) > 1:
        audio_data = np.mean(audio_data, axis=1)
    if original_sr != 16000:
        audio_data = signal.resample(
            audio_data, int(len(audio_data) * 16000 / original_sr)
        )
    
    transcription_inputs = processor.apply_transcrition_request(
        language="en", audio=audio_data.astype(np.float32),
        model_id=model_name, sampling_rate=16000, format=["wav"]
    )
    
    model_inputs = {k: v.to(device) for k, v in transcription_inputs.items()}
    
    with torch.no_grad():
        outputs = model.generate(
            **model_inputs, max_new_tokens=500, temperature=0.0, do_sample=False
        )
    
    return processor.tokenizer.decode(outputs[0], skip_special_tokens=True)

def summarize_audio(audio_path):
    """音声内容の要約"""
    model_name = "mistralai/Voxtral-Mini-3B-2507"
    processor = VoxtralProcessor.from_pretrained(model_name, trust_remote_code=True)
    model = VoxtralForConditionalGeneration.from_pretrained(
        model_name, torch_dtype=torch.float16, trust_remote_code=True
    )
    
    device = "mps" if torch.backends.mps.is_available() else "cpu"
    model = model.to(device)
    
    # 音声要約用の会話形式
    conversation = [
        {
            "role": "user",
            "content": [
                {"type": "audio", "path": audio_path},
                {"type": "text", "text": "この音声の内容を日本語で要約してください。"}
            ]
        }
    ]
    
    inputs = processor.apply_chat_template(conversation, return_tensors="pt")
    model_inputs = {k: v.to(device) for k, v in inputs.items()}
    
    with torch.no_grad():
        outputs = model.generate(
            **model_inputs, max_new_tokens=500, temperature=0.2, 
            top_p=0.95, do_sample=True
        )
    
    return processor.tokenizer.decode(outputs[0], skip_special_tokens=True)

def answer_audio_question(audio_path, question):
    """音声に対する質問応答"""
    model_name = "mistralai/Voxtral-Mini-3B-2507"
    processor = VoxtralProcessor.from_pretrained(model_name, trust_remote_code=True)
    model = VoxtralForConditionalGeneration.from_pretrained(
        model_name, torch_dtype=torch.float16, trust_remote_code=True
    )
    
    device = "mps" if torch.backends.mps.is_available() else "cpu"
    model = model.to(device)
    
    # 音声質問応答用の会話形式
    conversation = [
        {
            "role": "user", 
            "content": [
                {"type": "audio", "path": audio_path},
                {"type": "text", "text": question}
            ]
        }
    ]
    
    inputs = processor.apply_chat_template(conversation, return_tensors="pt")
    model_inputs = {k: v.to(device) for k, v in inputs.items()}
    
    with torch.no_grad():
        outputs = model.generate(
            **model_inputs, max_new_tokens=400, temperature=0.2, 
            top_p=0.95, do_sample=True
        )
    
    return processor.tokenizer.decode(outputs[0], skip_special_tokens=True)

# 使用例
if __name__ == "__main__":
    audio_file = "obama_speech.mp3"
    
    # 1. 基本的な音声転写
    transcription = transcribe_audio(audio_file)
    print(f"転写結果: {transcription}")
    
    # 2. 音声要約機能
    summary = summarize_audio(audio_file)
    print(f"要約結果: {summary}")
    
    # 3. 音声質問応答機能
    question = "話者の感情や心境について分析してください。"
    answer = answer_audio_question(audio_file, question)
    print(f"質問応答結果: {answer}")

※ コードはClaude Codeを利用して作成しています。

まとめ

日本語音声の文字起こし精度は、依然としてWhisperの方が高い、という結果になりました。一方で、Voxtralは音声認識モデルに留まらないスピーチアンダースタンディングモデルなので、音声によるFunction callingの実用度合いも気になるところです。

次期アップデートとして、Voxtralは以下の機能のリリースも予定されています。話者分離の性能は気になりますね。

  • 話者分離(Speaker segmentation)
  • 音声の年齢・感情マークアップ
  • 単語レベルのタイムスタンプ
  • 非音声オーディオ認識

現場からは以上です。