シナリオ
長い音声ファイルでWhisperを実行しているとき — あるいは大きなモデルを読み込んでいるだけのとき — 文字起こしの途中でクラッシュが発生します:
RuntimeError: CUDA error: out of memory
Exception raised from malloc at ../aten/src/ATen/native/cuda/CachingHostAllocator.cpp:152
読み込み時に落ちることもあれば、30秒間動いてから止まることもあります。いずれにせよ、GPUがモデルや音声チャンク用のテンソルを確保しようとしてVRAMが不足した状態です。
なぜこうなるのか
Whisperはモデル全体を最初にVRAMへ読み込みます。必要なメモリ量はモデルサイズによって大きく異なります:
tiny— 約1 GB VRAMbase— 約1 GB VRAMsmall— 約2 GB VRAMmedium— 約5 GB VRAMlarge/large-v2/large-v3— 約10 GB VRAM
モデルの重みに加えて、Whisperは音声処理用の追加バッファも確保します。GPUアクセラレーションを使用しているブラウザタブ、バックグラウンドで動いている別のトレーニングスクリプト、あるいはゲームでさえ、スクリプトが起動する前から静かに1〜3 GBのVRAMを消費していることがあります。それだけで限界を超えるには十分です。
まずここから — GPUを実際に何が使っているか確認する
コードにはまだ手を触れないでください。まず、VRAMの実際の状況を確認します:
nvidia-smi
Memory-Usageの列を確認してください。他の何かがVRAMを占有していれば、それを終了させて再試行してください — それだけで問題が解決することもあります。
GPUを正しく解放していないゾンビPythonプロセスも確認する価値があります:
nvidia-smi | grep python
kill -9 <PID>
修正1 — より小さいモデルに切り替える
最もシンプルな修正方法です。6 GBのカードでlargeを動かしているなら、一段階落としましょう:
import whisper
model = whisper.load_model("medium") # まだOOMが出る場合は"small"を試す
result = model.transcribe("audio.mp3")
print(result["text"])
mediumはほとんどのタスクで精度とVRAMのバランスが優れています。英語のみの音声であれば、smallも驚くほど高いパフォーマンスを発揮します — クリアな録音ではmediumと区別がつかないことも多いです。
修正2 — CPUにフォールバックする
VRAMがなくても大丈夫です。遅くなりますが、必ず最後まで完了します:
import whisper
model = whisper.load_model("large-v3", device="cpu")
result = model.transcribe("audio.mp3")
print(result["text"])
CPU文字起こしはGPUと比べて5〜20倍遅くなることを想定してください。GPUで30秒かかる10分の音声ファイルが、CPUでは8〜10分かかる場合があります。largeの精度がどうしても必要で、GPUの状況を変えられない一発限りの作業には十分価値があります。
修正3 — 読み込み前にキャッシュされたGPUメモリをクリアする
すでにPyTorchのテンソルがメモリに存在する大きなスクリプトの中でWhisperを実行している場合、先にアロケータのキャッシュをクリアしてください:
import torch
import whisper
torch.cuda.empty_cache()
model = whisper.load_model("large-v3")
result = model.transcribe("audio.mp3")
del model
torch.cuda.empty_cache()
注意点が一つあります:empty_cache()はPyTorchアロケータの空きブロックを解放するだけです。生きているテンソルが保持しているメモリは回収できません。ただし、以前のモデルが断片化したキャッシュを残していた場合、多くのケースでWhisperを読み込むのに十分な空き領域を確保できます。
修正4 — fp16を有効にしてVRAM使用量を半分に減らす
半精度での推論はCUDAではデフォルトで有効ですが、明示的に指定しても害はありません:
import whisper
model = whisper.load_model("large-v3")
result = model.transcribe("audio.mp3", fp16=True)
print(result["text"])
精度への影響を最小限に抑えながら、VRAMの使用量をほぼ半分に削減できます。一つ注意点があります:CPUで実行する場合はfp16=Falseを設定してください。CPUはfp16をサポートしておらず、実際の出力が埋もれてしまうほど大量の警告が表示されます。
修正5 — faster-whisperに切り替える(大規模モデルへの現実的な解決策)
faster-whisperはCTranslate2ベースのWhisper再実装です。同じモデルで、VRAMは何分の一かで済みます:
pip install faster-whisper
from faster_whisper import WhisperModel
# int8量子化 — 最低VRAM、それでも十分な品質
model = WhisperModel("large-v3", device="cuda", compute_type="int8")
segments, info = model.transcribe("audio.mp3", beam_size=5)
for segment in segments:
print(f"[{segment.start:.2f}s -> {segment.end:.2f}s] {segment.text}")
compute_type="int8"を使うと、large-v3のVRAM使用量は約10 GBから3〜4 GB程度まで下がります。6 GBのカードでOOMとスムーズな動作の差はそこにあります。
compute_typeのオプション:
float16— デフォルトのGPUモード、fp32の約半分のフットプリントint8_float16— 速度と精度のバランスが良いint8— 最低VRAM、わずかな精度のトレードオフ(通常は気にならないレベル)
修正6 — 長い音声ファイルを分割する
非常に長い録音は、モデルの読み込みは問題なくても、ピーク時のメモリ確保が限界を超えることがあります。10分単位のチャンクに分割することでメモリ使用量を一定に保てます:
from pydub import AudioSegment
import whisper
import os
model = whisper.load_model("medium")
audio = AudioSegment.from_file("long_audio.mp3")
chunk_length_ms = 10 * 60 * 1000 # 10分
chunks = [audio[i:i+chunk_length_ms] for i in range(0, len(audio), chunk_length_ms)]
full_text = []
for i, chunk in enumerate(chunks):
chunk_path = f"/tmp/chunk_{i}.mp3"
chunk.export(chunk_path, format="mp3")
result = model.transcribe(chunk_path)
full_text.append(result["text"])
os.remove(chunk_path)
print(" ".join(full_text))
本当に修正されたか確認する
Whisperの実行中にVRAMをリアルタイムで監視します:
# 別のターミナルで
watch -n 1 nvidia-smi
モデルの読み込み時にVRAMが増加し、文字起こし中は安定して推移するのが理想的です。スパイクして即クラッシュするパターンはまだ限界を超えているサインです。
正常に完了した後、Pythonからピーク使用量を確認します:
import torch
print(f"Peak VRAM: {torch.cuda.max_memory_allocated() / 1024**3:.2f} GB")
print(f"Currently allocated: {torch.cuda.memory_allocated() / 1024**3:.2f} GB")
私が実際に使っている方法
8 GBのカードでは、faster-whisperにlarge-v3 + int8の組み合わせをデフォルトとして使っています。余裕を持って収まり、動作も速く、品質はオリジナルのlargeモデルとほぼ同等です。特定の連携が必要な場合にのみ、オリジナルのwhisperライブラリに戻しています。
オリジナルライブラリを使いつつ小さなGPUしか持っていない場合は、medium + fp16=Trueがベストな選択肢です。

