📝

FFmpeg と Core ML に対応した Whisper.cpp をビルドする

に公開

はじめに

今さらではありますが FFmpeg と Core ML 対応の Whisper.cpp をビルドしたときのメモです。
公式の情報だけでは上手くいかなかったため、その補足です。

https://github.com/ggml-org/whisper.cpp

0. 今回の環境

  • MacBook Air (Apple M2)
  • macOS Tahoe 26.1
  • Whisper.cpp v1.8.2

Xcode のコマンドラインツールと Homebrew は既にインストールしてあることを前提で始めます。

1. 必要なものをインストール

CMake をインストール。
また対応するオーディオファイルの種類を増やすために FFmpeg もインストールします。

brew install cmake
brew install ccache
brew install ffmpeg

OpenMP のランタイムライブラリをインストールして ~/.zshrc に環境変数を追加、それを反映させて Apple Clang にインストール先を教えてあげます。

brew install libomp
.zshrc
export OpenMP_ROOT=$(brew --prefix)/opt/libomp
source ~/.zshrc

公式に従って Python 3.11 の仮想環境を作ります。今回は 3.11.14 をインストールしました。

brew install pyenv
pyenv install 3.11.14
pyenv local 3.11.14
python -m venv whisper.cpp-env
source whisper.cpp-env/bin/activate

PyTorch は 2.5.0 を指定します。

pip install ane_transformers
pip install openai-whisper
pip install coremltools
pip install torch==2.5.0

リポジトリをクローンします。

git clone https://github.com/ggml-org/whisper.cpp.git
cd whisper.cpp

2. ビルド

Core ML 対応モデルを生成します。今回は small を選択しました。

./models/generate-coreml-model.sh small

この時点で Python の仮想環境は終了しても大丈夫です。

deactivate

バイナリファイルをビルドします。
-DGGML_NATIVE=OFF を付けないと Clang に「native とかいう引数は知らん」と叱られて途中で止まってしまいます。

rm -rf build
cmake -B build -DWHISPER_COREML=ON -DWHISPER_FFMPEG=ON -DGGML_NATIVE=OFF
cmake --build build -j --config Release

警告が出るかもしれませんが、ここまでの工程に問題がなければビルドは無事完了します。

出力結果
- 途中省略 -

[100%] Built target vad-speech-segments
[100%] Built target test-vad-full
[100%] Built target whisper-cli
[100%] Built target test-vad
[100%] Built target whisper-server
[100%] Built target quantize

3. 動作テスト

FFmpeg の効果を確認するため、AAC に変換したサンプルを作成して入力してみます。

./build/bin/whisper-cli -m models/ggml-small.bin -f samples/jfk.aac
出力結果
- 途中省略 -

system_info: n_threads = 4 / 8 | WHISPER : COREML = 1 | OPENVINO = 0 | Metal : EMBED_LIBRARY = 1 | CPU : NEON = 1 | ARM_FMA = 1 | FP16_VA = 1 | DOTPROD = 1 | ACCELERATE = 1 | OPENMP = 1 | REPACK = 1 |

main: processing 'samples/jfk.aac' (179200 samples, 11.2 sec), 4 threads, 1 processors, 5 beams + best of 5, lang = en, task = transcribe, timestamps = 1 ...


[00:00:00.000 --> 00:00:11.000]   And so, my fellow Americans, ask not what your country can do for you, ask what you can do for your country.

whisper_print_timings:     load time =   168.01 ms
whisper_print_timings:     fallbacks =   0 p /   0 h
whisper_print_timings:      mel time =     4.37 ms
whisper_print_timings:   sample time =    33.78 ms /   142 runs (     0.24 ms per run)
whisper_print_timings:   encode time =   146.13 ms /     1 runs (   146.13 ms per run)
whisper_print_timings:   decode time =     6.74 ms /     1 runs (     6.74 ms per run)
whisper_print_timings:   batchd time =   186.15 ms /   139 runs (     1.34 ms per run)
whisper_print_timings:   prompt time =     0.00 ms /     1 runs (     0.00 ms per run)
whisper_print_timings:    total time =   639.47 ms
ggml_metal_free: deallocating

AAC は OK でしたが MP4 ではエラーが出てしまいます。

./build/bin/whisper-cli -m models/ggml-small.bin -f samples/jfk.mp4
出力結果
- 途中省略 -

[mov,mp4,m4a,3gp,3g2,mj2 @ 0xa0f3fc000] stream 0, offset 0x2c: partial file
[mov,mp4,m4a,3gp,3g2,mj2 @ 0xa0f3fc000] stream 0, offset 0x2c: partial file
zsh: segmentation fault  ./build/bin/whisper-cli -m models/ggml-small.bin -f samples/jfk.mp4

ですがサーバーモードで起動すると MP4 も処理してくれます。

サーバー起動
./build/bin/whisper-server -m models/ggml-small.bin --port 8080 --convert
別ウインドウにて
curl localhost:8080/inference -F "file=@samples/jfk.mp4"
出力結果

{"text":" And so my fellow Americans, ask not what your country can do for you, ask what you can do for your country.\n"}%

と思いましたが、どうやら先に Whisper.cpp が FFmpeg を呼び出して変換した後に Whisper.cpp が処理しているようです。
つまり FFmpeg がインストールしてある環境で --convert オプションを付けてサーバーを起動させた場合、-DWHISPER_FFMPEG=OFF でビルドしたバイナリでも同じ結果になります。

また日本語の音声を認識させる場合サーバー起動時に -l ja オプションを付けるか、ファイル送信時に -F "language=ja" を付けないとローマ字に変換されてしまいます。

(例) 日本語の input.mp4 を送信し、返信された JSON から text フィールドのみを output.txt に保存する場合

curl localhost:8080/inference -F "file=@input.mp4" -F "language=ja" | jq -r '.text' > output.txt

おわりに

せっかくビルドできたので何かに活用したいと思います。

参考文献

https://zenn.dev/shu223/articles/whisper-coreml
https://zenn.dev/arawii/articles/47a24cf2d0a3b2
https://qiita.com/asadeyy/items/6993bccb73f77d3231c1

Discussion