概要
お疲れさまです、ツーナです!
最近、個人利用のAIと会話できるアプリを作っているのですが、
その過程で「つくよみちゃん」の声を使いたいなと思い、
調べたところ COEIROINK に辿り着きました。
COEIROINKのダウンロードページ
https://coeiroink.com/download
当初は、以下のエンジンリポジトリがあることを知り、
これを利用して起動する予定でした。
https://github.com/shirowanisan/voicevox_engine
しかしながら、pyopenjtalkのビルド周りや依存関係に
関するエラー修正難航してしまい、一旦断念しました。
そこで一旦GUIの方がどうなっているのか見てみようかなと
COEIROINKエディタ版の 中身をざっと見ると
engineというバイナリがあり、
これを起動することでAPIサーバが立ち上がる
仕様になっていました。
なので、これをうまく使えばAWSやGCP(FargateやCloud Run)
で利用するなどにも応用できそうです。
今回は、
- COEIROINKのLinux版をDocker上で動かす
- CLIでAPIサーバを立ち上げる
- PostmanでAPIを叩き、音声を合成する
という流れをまとめました!
結論
最終的に出来上がったDockerfileは以下に
なりますので、結論だけ欲しい方は以下よりお願いします。
https://github.com/devtoona/coe-cloud-run
ディレクトリ構成
プロジェクトルートに以下を配置しています。
.
├── Dockerfile
├── start.sh
└── COEIROINK_LINUX_CPU_v.2.11.2/
├── engine/
│ └── engine (実行バイナリ)
└── 他フォルダ・ファイル
Dockerfileの作成
Dockerfileを最小構成に仕上げるため
engineが依存している共有ライブラリを確認してみました。
ldd engine/engine
出力は以下のとおりでした。
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fffff7b8000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fffff79c000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fffff797000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fffff56e000)
/lib64/ld-linux-x86-64.so.2 (0x00007ffffffc4000)
で、ライブラリ名とubuntuイメージに含まれているかを確認したところ、
全て標準で含まれているのでCOEIROINKエンジンを動かすのに追加で
インストールは必要なさそうです。
ライブラリ名 | 内容 | Ubuntuに含まれるか |
---|---|---|
libdl.so.2 |
動的リンク用ライブラリ | ✅ 標準(glibc) |
libz.so.1 |
圧縮・解凍ライブラリ(zlib) | ✅ 標準 |
libpthread.so.0 |
POSIXスレッドライブラリ | ✅ 標準(glibc) |
libc.so.6 |
C言語標準ライブラリ | ✅ 標準(glibc) |
ld-linux-x86-64.so.2 |
ELFローダ(実行時リンクローダ) | ✅ 標準(glibc) |
なので、
- COEIROINKのダウンロード
- ダウンロードしたCOEIROINKをDocker内にコピー
- Ubuntu 22.04ベースのDockerfileを用意し、
engine
を実行
という手順でAPIが使える!と思いきや、APIに接続できない という
壁にぶち当たりました。
接続できなかった原因
127.0.0.1
にしかバインドされていない
./engine/engine
このコマンドでAPIサーバは 127.0.0.1:50032
にバインドされます。
そのため、Dockerで以下のようにポートを開けても:
docker run -p 50032:50032 ...
ホストからはアクセスできません。
理由は「127.0.0.1」はコンテナ内のローカルを指しており、
ホスト側から見たときにそのポートは見えないからです。
解決策
socat
でポートフォワーディング
socat
はネットワークプロキシのように動きます。
socat TCP-LISTEN:50033,fork TCP:127.0.0.1:50032
このコマンドにより:
-
0.0.0.0:50033
で受けた通信を -
127.0.0.1:50032
に中継してくれます
つまり、ホストからは localhost:50033
にアクセスするだけで
Docker内の 127.0.0.1:50032
に繋がる、という仕組みになります。
Dockerでは -p 50033:50033
でポートを開けておけばOK!
最終的に出来上がったDockerfile
FROM ubuntu:22.04
# 非対話モードにしておく
ENV DEBIAN_FRONTEND=noninteractive
# ポート中継に必要なsocatをインストール
RUN apt update && apt install -y \
socat \
&& apt clean && rm -rf /var/lib/apt/lists/*
ARG ENGINE_NAME="COEIROINK_LINUX_CPU_v.2.11.2"
COPY ./${ENGINE_NAME} /opt/${ENGINE_NAME}
COPY ./start.sh /opt/${ENGINE_NAME}/start.sh
WORKDIR /opt/${ENGINE_NAME}
# バイナリやシェルスクリプトに実行権限を付与
RUN chmod +x ./engine/engine
RUN chmod +x ./start.sh
CMD ["./start.sh"]
#!/bin/bash
# バイナリの起動をログファイルを使って監視
./engine/engine > engine.log 2>&1 &
# "Uvicorn running" が出るまで(エンジン起動まで)ループで待機
while ! grep -q "Uvicorn running on" engine.log; do
sleep 0.2
done
color="\033[1;32m"
color_default="\033[0m"
# エンジン起動後にカスタムメッセージを表示
echo -e "${color}INFO${color_default} running on http://127.0.0.1:50033 (Press CTRL+C to quit)"
# socatでポート中継
socat TCP-LISTEN:50033,fork TCP:127.0.0.1:50032
ビルドと実行
以下に示すコマンドでビルドと実行をします。
私の環境では、M1macを利用していたため、platformを指定しています。
# ビルド
docker buildx build --platform linux/amd64 --load -t coeiroink-engine-x86
# 実行
docker run -p 50033:50033 -it --platform linux/amd64 coeiroink-engine-x86.
補足
platformをlinux/amd64に指定しないと
rosetta error: failed to open elf at /lib64/ld-linux-x86-64.so.2
というエラーが出ます。
これは、Apple Silicon(M1/M2などのarm64)Mac上で、linux/amd64 向けのバイナリを実行しようとして失敗するためです。
(言い換えれば、COEIROINKを実行にはlinux/amd64である必要があるということです。)
APIを呼び出し音声合成できるかの確認
上記が終わったら、127.0.0.1:50033にアクセスして
APIを呼びだせると思います。
APIの仕様は公式サイト(https://coeiroink.com/help/002)
が参考になると思います。
私の環境では、APIドキュメントを参考にPostmanを使って
話者リストを取得し、その値を使いつつ
/v1/synthesisを呼び出すと音声合成できました。
そのときの設定値は以下ですが、色々変えてみるのも面白いと思います。
{
"volumeScale": 1.0,
"pitchScale": 0.1,
"intonationScale": 1.0,
"prePhonemeLength": 1.0,
"postPhonemeLength":1.0,
"outputSamplingRate": 48000,
"speakerUuid": "3c37646f-3881-5374-2a83-149267990abc",
"styleId": 6,
"text": "こんにちは!つくよみちゃんです!",
"speedScale": 1.0
}
まとめ
COEIROINKのランタイムAPIを、Docker + CLI + Postmanで
動かすことに成功しました!
調べてもGUIで立ち上げるみたいな記事ばかりでCLIで起動している
方法がほとんどなかったので、同じように
「DockerからAPI叩きたいけどアクセスできねぇ!」
と悩んでいる方の役に立てば嬉しいです!