PythonとWhisperXの実践ガイド:音声認識、単語単位のアライメント、話者分離の実装

Artificial Intelligence tutorial - IT technology blog
Artificial Intelligence tutorial - IT technology blog

音声認識の実践課題:「聞き取る」だけでは不十分な理由

カスタマーサポート部門から、Asterisk PBXやZoomで録音された45分の通話音声が送られてきたとします。求められているのは、応対品質評価のために全文をテキスト化することです。しかし、一般的なWhisperにそのまま音声ファイルを投入すると、句読点や区切りのない数千文字の長文テキストが出力されるだけです。誰がオペレーターなのか?顧客が不満を訴えたのは何分何秒か?成約に至ったトークはどの部分か?

CapCutなどでカラオケ風の字幕テロップを作成したり、担当者別のタスクを自動抽出した議事録を作成したりするには、STT(Speech-to-Text)システムが次の3つの課題を同時に解決する必要があります。それは、「何を話したか」、「何分何秒に話したか」(単語レベルのタイムスタンプ / word-level timestamps)、そして「誰が話したか」(話者ダイアライゼーション / speaker diarization)です。

主要Speech-to-Textソリューションの比較

数百時間におよぶ会話音声を処理する中で、複数のソリューションをベンチマーク比較した実務上のインサイトを以下に示します。

  • 純粋なOpenAI Whisper(Vanilla Whisper):多言語の認識精度は極めて高いものの、タイムスタンプは文単位(segment-level)にとどまります。30分を超える長尺ファイルでは数秒単位のズレ(ドリフト)が発生しやすく、同一フレーズを無限に繰り返すハルシネーション(幻覚)に陥ることもあります。最大の制約は、話者分離機能が標準搭載されていない点です。
  • クラウド音声認識API(Google Cloud Speech-to-Text、AWS Transcribe):機能が網羅されており安定性も高いですが、コストが大きなボトルネックになります。平均単価が約$0.024/分(1時間あたり約$1.44)の場合、月間500時間の音声を処理するコンタクトセンターでは毎月$700以上のコストが発生します。さらに、クレジットカード情報や個人情報(身分証番号など)を含む社内音声をクラウドへ送信することは、コンプライアンスやセキュリティの観点でリスクを伴います。
  • WhisperX:3つの強力なツールを統合したオープンソースプロジェクトです。推論を高速化するCTranslate2ベースのfaster-whisperコア、音素アライメントを行うForced Alignmentモデル、そしてpyannote.audioのダイアライゼーションパイプラインを組み合わせています。タイムスタンプのズレを根本的に解決し、明確な話者分離を行いながら、自社インフラ上で完全オフライン稼働させることができます。

各アプローチのメリット・デメリット

1. オリジナル版Whisper(Vanilla Whisper)

  • メリット:pip install openai-whisperの1コマンドですぐにセットアップ完了。公式ライブラリであり、文脈の処理が自然。
  • デメリット:VRAM消費量が大きい(large-v3モデルで約10〜12GBのVRAMが必要)。長尺音声の推論速度が遅く、話者分離非対応。単語単位での正確な動画カット編集には不向き。

2. 有料クラウドAPIサービス

  • メリット:ハードウェアの運用管理が不要。REST APIを呼び出すだけで結果を取得可能。
  • デメリット:処理規模のスケールに伴いコストが急増。機密データが社内ネットワーク外部へ送信されるリスク。

3. WhisperX

  • メリット:CTranslate2の最適化とVAD(音声区間検出)による無音カットにより、オリジナルWhisper比で2〜4倍高速。Forced Alignmentによる単語単位の極めて正確なタイムスタンプ。Pyannote 3.1統合による高精度な話者分離。
  • デメリット:最低6GB〜8GB以上のVRAMを搭載したNVIDIA GPUが必要(RTX 3060 12GB、またはクラウド上のT4/A10を推奨)。Hugging Faceのアクセストークン取得とモデル利用規約への同意が必要。

自社運用システムにおいてWhisperXが最適な理由

ショート動画の自動字幕生成ツール、Google Meet等の議事録自動作成bot、通話品質の監査・QAシステムなどを構築する場合、WhisperXはコストと精度のバランスが最も優れた選択肢です。ハードウェア費用は固定化され、データセキュリティは完全に担保されます。さらに、出力データは詳細なJSON構造を持つため、そのままLLM(大規模言語モデル)へ渡して後続の分析や要約を行うパイプラインへ容易に統合できます。

PythonによるWhisperXの実装手順

ステップ1:実行環境とライブラリの準備

WhisperXにはPython 3.10または3.11、および音声ストリーム処理のためのffmpegが必要です。

# Ubuntu/Debian環境でのffmpegのインストール
sudo apt update && sudo apt install -y ffmpeg

# 仮想環境(venv)の作成と有効化
python3 -m venv venv && source venv/bin/activate

# CUDA 12.1対応PyTorchのインストール
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

# WhisperXのインストール
pip install git+https://github.com/m-bain/whisperx.git

ステップ2:Hugging Face Access Tokenの取得

話者分離パイプラインではpyannote.audioの事前学習済みモデルを使用します。Hugging Faceアカウントにログインし、以下の2つのリポジトリで利用規約に同意(Accept)してください。

  • pyannote/speaker-diarization-3.1
  • pyannote/segmentation-3.0

続いて、Hugging Faceの Settings > Access Tokens にアクセスし、Read権限の新しいトークンを発行して保存します(Pythonコード内で指定します)。

ステップ3:エンドツーエンド音声処理スクリプトの作成

以下のスクリプトは、「音声認識 → 単語単位のタイムスタンプ整合 → 話者ラベル割り当て」という3段階のパイプラインを一貫して実行します。

import whisperx
import gc
import torch

device = "cuda" if torch.cuda.is_available() else "cpu"
audio_file = "cuoc_hop_demo.wav"
batch_size = 8  # VRAMが8GB未満の場合は4または2に下げてください
compute_type = "float16" if device == "cuda" else "int8"
HF_TOKEN = "hf_your_personal_access_token_here"

# 1. faster-whisperによる音声認識
print("--- [1/3] 音声コンテンツを文字起こし中 ---")
model = whisperx.load_model("large-v3", device, compute_type=compute_type, language="vi")
audio = whisperx.load_audio(audio_file)
result = model.transcribe(audio, batch_size=batch_size)

# 次のモデルをロードする前にGPU VRAMを解放
del model
gc.collect()
torch.cuda.empty_cache()

# 2. 単語単位の正確なアライメント(Forced Alignment)
print("--- [2/3] 単語単位のタイムスタンプを調整中 ---")
model_a, metadata = whisperx.load_align_model(language_code=result["language"], device=device)
result = whisperx.align(result["segments"], model_a, metadata, audio, device, return_char_alignments=False)

del model_a
gc.collect()
torch.cuda.empty_cache()

# 3. 話者分離(Speaker Diarization)
print("--- [3/3] Pyannoteで話者ラベルを付与中 ---")
diarize_model = whisperx.DiarizationPipeline(use_auth_token=HF_TOKEN, device=device)
diarize_segments = diarize_model(audio_file)

# 単語単位のタイムスタンプに話者情報をマージ
final_result = whisperx.assign_word_speakers(diarize_segments, result)

# コンソール画面に結果を出力
for segment in final_result["segments"]:
    speaker = segment.get("speaker", "UNKNOWN")
    start = segment["start"]
    end = segment["end"]
    text = segment["text"].strip()
    print(f"[{start:.2f}s -> {end:.2f}s] {speaker}: {text}")
    
    # ズレ検証用に各単語の詳細タイムスタンプを出力
    words_detail = [f"{w['word']} ({w.get('start', 0):.2f}-{w.get('end', 0):.2f})" for w in segment.get("words", [])]
    print("   単語詳細:", ", ".join(words_detail))

ステップ4:出力データの活用ユースケース

WhisperXの出力は、ミリ秒精度のタイムスタンプと話者識別子(SPEAKER_00、SPEAKER_01など)を含む構造化JSON配列です。このデータを活用することで、以下の3つの実用的なユースケースをすぐに展開できます。

  1. 動的字幕・テロップの生成:.srtや.assファイルに出力し、Premiere Proなどでカラオケ風テロップを作成。各フレームと完全にシンクロした字幕を実現できます。
  2. 音声検索(Audio Search):大量の通話録音アーカイブからキーワード検索を行い、その単語が発声された該当秒数へダイレクトにシーク再生できます。
  3. LLMによる高精度な会議要約:話者が明確に分かれたテキストをGPT-4oやClaude 3.5 Sonnetに投入することで、発言者の取り違えなく、個別のネクストアクションや決定事項を正確に抽出できます。
Share: