まえがき
OpenAI Whisperの高性能推論verが話題となっていたので試してみました。
C/C++で実装され、CPUの実行に最適化されたものとなっているようです。
特徴としては以下が挙げられていました。
- 依存性のないプレーンなC/C++による実装
- x86 アーキテクチャの AVX 組み込み関数のサポート
- POWER アーキテクチャの VSX 組み込み関数のサポート
- F16 / F32 の混合精度
- 低メモリ使用量
- CPU上で実行
- Windows / Linux / Mac OS / iOS / Android / WebAssembly / Raspberry Piのプラットフォームに対応
導入
- ソースコードをローカルへクローンする
$ git clone https://github.com/ggerganov/whisper.cpp.git
- 使用するモデルをダウンロードする
$ bash ./models/download-ggml-model.sh <Model>
Downloading ggml model small ...
ggml-small.bin
100%[====================================================================>] 465.01M 2.84MB/s 時間 1m 58s
Done! Model 'small' saved in 'models/ggml-small.bin'
You can now use it like this:
./main -m models/ggml-small.bin -f samples/jfk.wav
- 対象モデルは以下となります。
Model | Disk | Mem |
---|---|---|
tiny | 75 MB | ~390 MB |
tiny.en | 75 MB | ~390 MB |
base | 142 MB | ~500 MB |
base.en | 142 MB | ~500 MB |
small | 466 MB | ~1.0 GB |
small.en | 466 MB | ~1.0 GB |
medium | 1.5 GB | ~2.6 GB |
medium.en | 1.5 GB | ~2.6 GB |
large | 2.9 GB | ~4.7 GB |
OpenAIのWhisperでは、VRAMの使用量について言及されていましたが、Whisper.cppではVRAMの記述はありません。
- makeコマンドを実行するためインストールされていない場合は、以下をインストールする
$ yum install make -y
$ yum install gcc -y
$ yum install gcc-c++ -y
- Whisper.cppをクローンしたディレクトリでmakeコマンド実行
$ make
g++ -I. -I./examples -O3 -std=c++11 -pthread -c whisper.cpp -o whisper.o
g++ -I. -I./examples -O3 -std=c++11 -pthread examples/main/main.cpp whisper.o ggml.o -o main
./main -h
usage: ./main [options] file0.wav file1.wav ...
options:
-h, --help show this help message and exit
-s SEED, --seed SEED RNG seed (default: -1)
-t N, --threads N number of threads to use during computation (default: 4)
-p N, --processors N number of processors to use during computation (default: 1)
-ot N, --offset-t N time offset in milliseconds (default: 0)
-on N, --offset-n N segment index offset (default: 0)
-d N, --duration N duration of audio to process in milliseconds (default: 0)
-mc N, --max-context N maximum number of text context tokens to store (default: max)
-ml N, --max-len N maximum segment length in characters (default: 0)
-wt N, --word-thold N word timestamp probability threshold (default: 0.010000)
-v, --verbose verbose output
--translate translate from source language to english
-otxt, --output-txt output result in a text file
-ovtt, --output-vtt output result in a vtt file
-osrt, --output-srt output result in a srt file
-owts, --output-words output script for generating karaoke video
-ps, --print_special print special tokens
-pc, --print_colors print colors
-nt, --no_timestamps do not print timestamps
-l LANG, --language LANG spoken language (default: en)
-m FNAME, --model FNAME model path (default: models/ggml-base.en.bin)
-f FNAME, --file FNAME input WAV file path
- その後、以下コマンドを実行し、Whisper.cppを動かそうとすると以下エラーが表示される。
OpenAIのWhisperはm4aなど他のファイルにも対応していたが、Whisper.cppは16kHzのWAVファイルにのみ対応しているとのこと。
そのため、ffmpegを利用して音声データをWAVファイルに変換する。
$ ./main -m models/ggml-small.bin -f output.wav -l ja -ovtt
./main: WAV file 'audio.wav' must be 16 kHz
- 以下コマンドを実施しffmpegをインストールする。(CentOS8例)
dnf install https://download.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
dnf localinstall --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm
dnf install https://rpmfind.net/linux/epel/7/x86_64/Packages/s/SDL2-2.0.14-2.el7.x86_64.rpm
dnf -y install ffmpeg
- ffmpegにより16kHzのWAVファイルに変換する。
ffmpeg -i audio.m4a -ar 16000 -ac 1 -c:a pcm_s16le output.wav
ffmpeg version 4.2.8 Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 8 (GCC)
configuration: --prefix=/usr --bindir=/usr/bin --datadir=/usr/share/ffmpeg --docdir=/usr/share/doc/ffmpeg --incdir=/usr/include/ffmpeg --libdir=/usr/lib64 --mandir=/usr/share/man --arch=x86_64 --optflags='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' --extra-ldflags='-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld ' --extra-cflags=' ' --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvo-amrwbenc --enable-version3 --enable-bzlib --disable-crystalhd --enable-fontconfig --enable-frei0r --enable-gcrypt --enable-gnutls --enable-ladspa --enable-libaom --enable-libdav1d --enable-libass --enable-libbluray --enable-libcdio --enable-libdrm --enable-libjack --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libmp3lame --enable-nvenc --enable-openal --enable-opencl --enable-opengl --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librsvg --enable-libsrt --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libvorbis --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-version3 --enable-vapoursynth --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-libzimg --enable-libzvbi --enable-avfilter --enable-avresample --enable-libmodplug --enable-postproc --enable-pthreads --disable-static --enable-shared --enable-gpl --disable-debug --disable-stripping --shlibdir=/usr/lib64 --enable-libmfx --enable-runtime-cpudetect
libavutil 56. 31.100 / 56. 31.100
libavcodec 58. 54.100 / 58. 54.100
libavformat 58. 29.100 / 58. 29.100
libavdevice 58. 8.100 / 58. 8.100
libavfilter 7. 57.100 / 7. 57.100
libavresample 4. 0. 0 / 4. 0. 0
libswscale 5. 5.100 / 5. 5.100
libswresample 3. 5.100 / 3. 5.100
libpostproc 55. 5.100 / 55. 5.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'audio.m4a':
Metadata:
major_brand : M4A
minor_version : 0
compatible_brands: M4A mp42isom
Duration: 00:00:25.22, start: 0.000000, bitrate: 127 kb/s
Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 32000 Hz, mono, fltp, 126 kb/s (default)
Stream mapping:
Stream #0:0 -> #0:0 (aac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, wav, to 'output.wav':
Metadata:
major_brand : M4A
minor_version : 0
compatible_brands: M4A mp42isom
ISFT : Lavf58.29.100
Stream #0:0(und): Audio: pcm_s16le ([1][0][0][0] / 0x0001), 16000 Hz, mono, s16, 256 kb/s (default)
Metadata:
encoder : Lavc58.54.100 pcm_s16le
size= 788kB time=00:00:25.21 bitrate= 256.0kbits/s speed=1.22e+03x
video:0kB audio:788kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.009666%
実行
オプション | 内容 |
---|---|
-m | 利用モデル |
-f | インプットとなるWAVファイルのパス |
-l | 言語を指定する |
-ovtt | 結果をvttファイルで出力する |
./main -m models/ggml-small.bin -f output.wav -l ja -ovtt
whisper_model_load: loading model from 'models/ggml-small.bin'
whisper_model_load: n_vocab = 51865
whisper_model_load: n_audio_ctx = 1500
whisper_model_load: n_audio_state = 768
whisper_model_load: n_audio_head = 12
whisper_model_load: n_audio_layer = 12
whisper_model_load: n_text_ctx = 448
whisper_model_load: n_text_state = 768
whisper_model_load: n_text_head = 12
whisper_model_load: n_text_layer = 12
whisper_model_load: n_mels = 80
whisper_model_load: f16 = 1
whisper_model_load: type = 3
whisper_model_load: mem_required = 1044.00 MB
whisper_model_load: adding 1608 extra tokens
whisper_model_load: ggml ctx size = 464.56 MB
whisper_model_load: memory size = 68.48 MB
whisper_model_load: model size = 464.44 MB
system_info: n_threads = 4 / 4 | AVX2 = 1 | AVX512 = 0 | NEON = 0 | FP16_VA = 0 | WASM_SIMD = 0 | BLAS = 0 |
main: processing 'output.wav' (403456 samples, 25.2 sec), 4 threads, 1 processors, lang = ja, task = transcribe, timestamps = 1 ...
実行結果
CPU、メモリを増設して検証してみました。(1時間分の音声データ)
増設前
- Intel(R) Xeon(R) CPU E5-2667 4コア
- RAM 8GB
この状態で実行したとき、処理完了まで33分かかりました。
増設後
- Intel(R) Xeon(R) CPU E5-2667 8コア
- RAM 16GB
この状態で実行したとき、処理完了まで26分かかりました。
総評
スケールアップをすることで、1時間当たりの音声データでVRAM非搭載サーバ上からの実行により7分の削減ができ、CPUの性能にwhisper.cppの動作が依存していると言えます。
また、OpenAI純正のWhisperで同環境で実行した際は、GPUを搭載していないため動作にかなりの時間がかかりましたので、GPU非搭載サーバ上で動作させる場合は、Whisper.cppの利用を推奨します。
参考