作りました。どうぞ。というかこの記事自体が作ったでっていう報告みたいなもんです。
TL;DR
- Open WebUIでVOICEVOXのTTS使うためのブリッジ作ったで
-
報告だけやと短いからついでに学んだことを書いてくで
Open WebUIとは
Ollamaとそのモデルをブラウザ上で動かせるやつです。
デフォルトならOllamaってCLI上で動かすものなんですが、Open WebUIを使ったらChatGPTライクな画面で動かせます。
詳しくはこちらから。
VOICEVOXで喋ってもらおう
皆さんご存知であろうVOICEVOX。AIを用いた音声合成を行ってくれる無料ソフトです。仕組み等々はオープンソースになってます。また、APIもあって、他のソフトなどとの連携もしやすいようになっています。
で、今回はそんなVOICEVOXの音声合成をOpen WebUIから使えるようにするためのブリッジを作ったので、その宣伝と、ついでにどうやって作ったかをちょっとだけ紹介します。
使用
コードはここです。
あと、使用にはPython
, ffmpeg
が必要です。パスを通しておいてください。
1. ブリッジを起動
openaitts2voicevox_bridge.py
を起動してください。
また、VOICEVOXも起動してください。
2.Open WebUIでの設定
TTSの設定からOpenAIを選択して、URLにhttp://localhost:8000/v1
を入れます。ほかは何かしら書いておくといいかも。
3.多分動く
音声再生をすれば多分動きます。
詳しい設定はGithubのreadme.mdに書いてあるのでそっち見てください。
作りながら得た知識
1.PythonのFastAPIは超便利
当方APIブリッジどころか、FastAPIを使ったのも初めてですし、curlのPOSTすら使い方が怪しいのですが、そういう自分から見ても、FastAPIはメチャクチャわかりやすかったです。
特に、Swagger UI
は感動しました。自分で立てたサーバーの動作をGUI付きで、しかもcurlせずにテストできるのは感動モノです。
2.configparserも捨てたもんじゃない
設定ファイル言語って言うんでしょうか?json
とかtoml
とか。最新のPythonにはどうやらtoml
のパーサが追加されたようですが、ウチのPythonは3.10なもので、設定ファイルがjson
かconfigparser
しか扱えそうにありません。
わざわざパッケージを使いたくもないし、人間が書くということを考えるとconfigparser
か...。と思い、渋々configparser
を使ってみましたが...。これが案外悪くない。
言語仕様が不明だったり、そもそもiniファイル自体が古すぎて意味不明だったり...。問題点も多いですが、小規模なプロジェクトには十分でした。
まあ、大規模プロジェクトならtoml
とかyaml
とかにしてほしいところです。
3.クソコードを止める + ChatGPTで知らないことを知る
こんなコードを書くシーンが有りました。
def voicevox_api(input, voice):
# switch-case文が恋しい
if is_int(voice):
return voicevox_api_runner(input, voice)
elif voice == "alloy":
return voicevox_api_runner(input, config["ALTID"]["ALLOY"])
elif voice == "echo":
return voicevox_api_runner(input, config["ALTID"]["ECHO"])
elif voice == "fable":
return voicevox_api_runner(input, config["ALTID"]["FABLE"])
elif voice == "onyx":
return voicevox_api_runner(input, config["ALTID"]["ONYX"])
elif voice == "nova":
return voicevox_api_runner(input, config["ALTID"]["NOVA"])
elif voice == "shimmer":
return voicevox_api_runner(input, config["ALTID"]["SHIMMER"])
else:
# IDでも上記のでもないときはこっち
return voicevox_api_runner(input, config["ALTID"]["DEFAULT_SPEAKER"])
voicevox_api_runner
関数でVOICEVOXのAPIと通信します。is_int
関数は名前のとおりです...。
ただしこれ、まあまあなクソコードですよね。
だから、ChatGPTに聞いて以下のように修正しました。
def voicevox_api(input, voice):
voice_map = {
"alloy": config["ALTID"]["ALLOY"],
"echo": config["ALTID"]["ECHO"],
"fable": config["ALTID"]["FABLE"],
"onyx": config["ALTID"]["ONYX"],
"nova": config["ALTID"]["NOVA"],
"shimmer": config["ALTID"]["SHIMMER"]
}
return voicevox_api_runner(input, voice_map.get(voice, config["ALTID"]["DEFAULT_SPEAKER"]) if not is_int(voice) else voice)
.get()
で変数内に要素がない場合に代わりの要素を指定する方法とか初めて知りました。なんとも知識不足。そんな業があったのかって感じです。
ChatGPTって、ハルシネーションとかもあって良くないとは言われますが、「知らないことすら知らないことを知るためのツール」としてはすごく優秀だと思っています。
特に、日曜プログラマの自分なんかは人のコードを読む機会が現職のエンジニアさんたちよりも少ないので、ChatGPTは結構貴重な話し相手です。
まとめ?
MITで公開してます。これで何も気にせず使えます。
ぜひウチのブリッジ使ってな!