音声ファイルから文字起こししたファイルを作成できる whisper.cpp を Docker 環境で構築する

# はじめに
タイトルの通りです。
某PodCastの番組で知った文字起こしのアプリケーションの動作確認です。
~~普通に試すのは面白くなかったので、gccのコンテナ上で展開して実行してみました。~~
cmakeが必要になっていますので、イメージ環境を([kitware/cmake](https://hub.docker.com/r/kitware/cmake)に)変更しています。イメージにOfficialとかのマークはありませんが、きちんとした企業さんのようです。


※こちらのプログラムをコンテナ上で展開しています

https://github.com/ggerganov/whisper.cpp


# 確認環境
- windows10 pro 
- WSL2(Ubuntu22.04.3 LTS)
- Dockerのバージョン
    - Docker version 27.5.1, build 9f9e405
    - Docker Compose version v2.32.4

# 修正履歴
2025/06/02 いろいろなバージョンアップに対応

# フォルダ構成
```
[projectfolder]
 ├─ docker-compose.yml
 ├─ Dockerfile
 ├─ .env
 └─ transcribe.sh
```
※途中、`audio-files` と `trans-files` のフォルダが作成されます（設定内容による）

# ファイル
※内容見るのが面倒な方は、以下に置いています

https://github.com/naozo-se/docker-whisper.cpp/tree/main

```config:.env
# ユーザー情報(UID,GIDはホストの環境に合わせて)
UID=1000
GID=1000
USERNAME=cppuser
GROUPNAME=cppuser

# コンテナ内作業ディレクトリ
WORKDIR=/app

# タイムゾーン
TZ=Asia/Tokyo

# リソース管理
PROJECT_NAME=cpp-whisper
IMAGE_VERSION=1.0

# 音声ファイルフォルダ（ホスト側設定）
AUDIO_FILE_DIR=audio-files
# 文字起こしファイル
TRANS_FILE_DIR=trans-files

# モデル(tiny, tiny.en, base, base.en, small, small.en, medium, medium.en, large)
MODEL_TYPE=small
```

```yaml:docker-compose.yml
services:
  app:
    image: ${PROJECT_NAME}:${IMAGE_VERSION}
    build:
      context: .
      args:
        UID: ${UID}
        GID: ${GID}
        USERNAME: ${USERNAME}
        GROUPNAME: ${GROUPNAME}
        WORKDIR: ${WORKDIR}
        MODEL_TYPE: ${MODEL_TYPE}
        AUDIO_FILE_DIR: ${AUDIO_FILE_DIR}
        TRANS_FILE_DIR: ${TRANS_FILE_DIR}
    volumes:
        - ./${AUDIO_FILE_DIR}:/var/tmp/${AUDIO_FILE_DIR}
        - ./${TRANS_FILE_DIR}:/var/tmp/${TRANS_FILE_DIR}
    environment:
        - TZ=${TZ}
    restart: always
    tty: true
```

```dockerfile:Dockerfile
FROM kitware/cmake:ci-fedora42-hip-x86_64-2025-04-22

# パッケージ更新＆追加
RUN dnf update -y
RUN dnf install -y cmake \ 
        ffmpeg \ 
        libavcodec-free-devel \ 
        libavformat-free-devel \
        libavutil-free-devel
            
# パラメータ変数
ARG USERNAME
ARG GROUPNAME
ARG UID
ARG GID
ARG WORKDIR
ARG MODEL_TYPE
ARG AUDIO_FILE_DIR
ARG TRANS_FILE_DIR
 
# 環境変数
ENV AUDIOFILEPATH=/var/tmp/$AUDIO_FILE_DIR
ENV TRANSFILEPATH=/var/tmp/$TRANS_FILE_DIR

# ユーザー追加
RUN groupadd -g $GID $GROUPNAME && \
    useradd -m -s /bin/bash -u $UID -g $GID $USERNAME

# ルートフォルダ作成
RUN mkdir -p $WORKDIR
WORKDIR $WORKDIR

# リソース取得
RUN git clone https://github.com/ggerganov/whisper.cpp.git 
# 作成時のcommitidは 
# 799eacdde40b3c562cfce1508da1354b90567f8f 
# であるが、切り替えられないため、メモ残し

# 権限変更
RUN chown -R $UID:$GID $WORKDIR/whisper.cpp

# ファイル参照フォルダ作成
RUN mkdir -p $AUDIOFILEPATH
RUN mkdir -p $TRANSFILEPATH
# 権限変更
RUN chown -R $UID:$GID $AUDIOFILEPATH
RUN chown -R $UID:$GID $TRANSFILEPATH

# ユーザー切り替え
USER $USERNAME

# 作業ディレクトリ設定
WORKDIR $WORKDIR/whisper.cpp

# 文字起こしファイルコピー
COPY transcribe.sh ./

# モデルダウンロード
RUN bash ./models/download-ggml-model.sh $MODEL_TYPE

# コンパイル
RUN cmake -B build -D WHISPER_FFMPEG=yes
RUN cmake --build build --config Release
```

```bash:transcribe.sh
# 指定拡張子のファイルがあるか
for _audio_file_path in ${AUDIOFILEPATH}/*.{wav,WAV,aiff,AIFF,aac,AAC,mp3,MP3}; do

    # 指定拡張子がない場合は、以下の処理を行わない
    [ -f "$_audio_file_path" ] || continue
    
    # 拡張子なしのフォルダ
    _audio_file_name=`basename ${_audio_file_path} | sed 's/\.[^\.]*$//'`

    # 文字起こし処理実行
    ./build/bin/whisper-cli -f ${_audio_file_path} -m models/ggml-small.bin -l ja > ${TRANSFILEPATH}/${_audio_file_name}.txt

done
```

# 構築＆実行方法
1. .env を編集します
基本そのままで問題ないですが、モデルの設定は大きなサイズにすると、精度が上がるかと思います（多分）。
GUI、UIDなどは、環境に合わせて変更してください。

1. カレントディレクトリで コンテナを立てます
    ```
    docker-compose up -d --build
    ```
    ※`audio-files` と `trans-files` のフォルダが作成されます

1. 作成された `audio-files` のフォルダで、直下に音声ファイルをおく
   ※ wav,aiff,aac,mp3 に対応
   ~~※ 本来は 16kHz の wav のみしか対応していないが、事前に変換する処理を実行している~~
   ※ 以前のバージョンはwav のみしか対応していなかったが、今回は大丈夫そう(mp3しかためしていませんが…)

1. 以下のコマンドを実行して、文字起こし処理を実行(ホスト側からコンテナ内のシェルファイルを実行)
    ```
    docker exec -ti {コンテナ名} bash transcribe.sh
    ```

- `trans-files` 以下のフォルダにテキストファイルが作成されている


# 注意点
いつの間にか動かなくなっていましたので、時間がたつとまた動かなくなるかと思います…。
また、環境を再作成したいときは、以下で環境を初期化して、再作成してください
```shell
docker compose down --rmi all --volumes --remove-orphans
```


# おまけ
GeminiのAdvancedでwhisper.cppのリポジトリを読み込んで、ページのURLを指定してソースを修正案出してと頼んでみましたが、色々駄々をこねたせいもあるのか。うまくいきませんでした…。（ベース構成変えないでとかいろいろ言ったせいもあるかもしれません）

# 最後に
Qiitaも保守していかないと、すぐ記事が古くなってしまって動かなくなる…。