ガイドラインでは日記は書いたらダメのあるのですが、
日記の定義がよくわからないので、日記の体で書こうと思います。
自分のしくじりが他の人の糧になるかわからないですが、
それも含めて書いていきます。
思いつきで作ったアプリの経緯、作り方、AIの活用方法、
AIの使い方主義・主張のためにこの記事を書きます。
作ったアプリはgithubで公開してます。
https://github.com/roripika/voicevox-storycaster
VOICEVOXの文章朗読アプリを作った経緯
きっかけ
職場のエンジニア仲間が趣味でなろう系小説を書いてるって話を聞いて、
その人は、自分で文章を考えて、文章の破綻がないかとか、言葉が間違ってないかを
AIにチェックしてもらってると言ってたのですが、
それ、最初からAIで作ったら簡単じゃね?と思って
色々なサイトを探しながら、いけるかもしれないと
ChatGPTを使いながら文章を作っていましたが…
どうも良い文章が出てこないし、チェックも膨大に時間がかかる
何度もあらすじや世界観設定を作り直し、改稿、改稿の繰り返し
毎週の休みの日にちょこちょこ作って2ヶ月近く経ってしまった。
これは出来上がった文章を読んでたら脳が疲れてしまう。
なんか朗読してくれるアプリはないか…と
ただ喋らせるだけならウェブ上に貼り付けて喋らせれるアプリは沢山あるが
配役に合わせて声がかわらないと、
誰のセリフか判断するのに時間がかかるって思った。
VOICEVOXを使えばセリフごとに配役が決められる事を知ったので
これでわかりやすくなるぞ!と意気込みアプリをつかうぞ!
GUIの設定が細かすぎて面倒やん
エンジニアらしく、自動化できないかなと思い
最近AI流行ってるらしいし、職場でも効率化のために使え使え言われるから
codex君の力を見せてもらおうかと思い立ったのが始まりです。
VSCodeとcodexの連携
個人で持っているChatGPTは小説を書きたいがためにProライセンスを契約していました。
VSCodeに拡張追加の検索フィールドに"ChatGPT"を入力すると
OpenAI以外のChatGPTとかも出てくるので、公式のOpenAIのCodexの拡張をインストールします。
(公式の名前がコロコロ変わってるようなので、OpenAI公式か見ておいたほうがいいです)
公式の何が良いかというと、API経由でのアクセス扱いにならないので従量課金ではないことです。

これで、チャットウインドウが出てくるので、ここで作業をしていきました。
(codexにgeminiの実装を頼んでた時に大変でした)

アプリが動くところまでのcodexとのやりとり
codexやりとりを行なって、
ある程度のものが出来上がってきた。
これが出来上がるまで、途中経過で動作チェックもして大体2時間ぐらいです。
Qiitaに書きやすいように、
以下形式でプロンプトごとに記録を残すように指示しました。
#### タイトル
```
[プロンプト]
{codex作業の要約}
```
ここからが対話の時系列の流れ
VOICEVOX エンジンをワンコマンドでセットアップしたい
[VOICEVOXアプリをテキストから自動音声化できる仕組みを作りたい。まずインストールスクリプトを。]
{VOICEVOXエンジンの最新リリースを取得・展開し、依存ツール確認や自動導入、展開先シンボリックリンク作成までを行う `scripts/install_voicevox_engine.sh` を作成。README へ利用方法も追記。}
Geminiプロバイダ利用時のエラー対応
[設定画面でGeminiを選び、必要パッケージをインストール後に音声生成したらプロセスが失敗。]
{Geminiクライアントの初期化でpipインストール直後に認識されるよう修正し、OPENAIキーの強制チェックを解除。さらに`gemini-1.5-flash-latest`など有効なモデルへ差し替えGUIの候補リストも更新、保存されたAPIキーを実行環境へ渡すようにして404エラーを解消。}
話者ごとの情報を一覧化したい
[VOICEVOXで利用可能な話者一覧を出力したい。詳細情報も欲しい。]
{エンジンから `/speakers` を取得して md/csv/json で出力する `scripts/export_voicevox_speakers.sh` を追加。`--details` で `/speaker_info` を収集しJSON保存できるよう対応。README に出力手順を記載。}
小説を読み込んで自動で配役し音声化するパイプラインが欲しい
[テキストをAIに渡し、キャラクター推定→VOICEVOX配役→音声生成まで自動化したい。]
{`scripts/novel_to_voicevox.py` と `config/voice_assignments.yaml` を整備し、OpenAIを使った発話割当とVOICEXOX合成を実装。READMEに実行手順を追加。}
VOICEVOX話者の担当一覧を作りたい
[抽出された話者ごとのプロフィールをYAMLにまとめたい。]
{`scripts/export_voicevox_speakers.sh` の出力を基に `config/voice_assignments.yaml` に猫使アル等のプロフィール例を追記し、READMEで使い方を説明。}
ここでcodex君が著作権の問題や勝手に読み取っていいかわからないから一覧は作れないって言い出す。
https://gemini.google.com/share/05e834e7691a
そこで話者リストを作ってもらう
このリストを使って対応表を作ってもらった。
登場人物抽出→配役→音声合成を完全自動化したい
[AIがキャラを抽出し、自動でVOICEVOXスタイルIDと紐づけて音声合成するスクリプトが欲しい。]
{`scripts/auto_assign_voicevox.py` を追加し、LLMでキャラクター抽出→VOICEVOX話者マッピング→YAML生成→音声合成まで一括実行。READMEに手順を追記。}
AIが割り当てたキャラの音声出力がナレーションだけになる
[すべてナレーション扱いになり音声が生成されないので直したい。]
{自動割当YAMLへナレーション枠(style_id=3)を必ず追加するロジックを実装し、地の文も音声化できるよう修正。}
生成した行単位音声を一本化したい
[manifestを使ってWAVを結合するスクリプトが欲しい。]
{`scripts/merge_voicevox_audio.py` を追加し、ffmpeg concatで1本のWAVにまとめられるようにした。READMEにも手順を追加。}
GUIでテキスト貼り付け→実行できるようにしたい
[初心者向けに、テキスト入力と実行ボタンだけで済むGUIランチャーが欲しい。]
{Tkinterベースの `scripts/gui_voicevox_runner.py` を作成し、テキスト貼付→音声生成→フォルダ表示まで自動化。READMEにGUIの使い方も記載。}
セットアップやGUIをワンクリックで起動したい(mac)
[Finderからダブルクリックでセットアップ・GUIが起動する .command を用意してほしい。]
{`SetupVoicevoxEnvironment.command` と `RunVoicevoxGUI.command` を追加し、`.venv` 読み込みやOpenAIキー設定も自動化。READMEで案内。}
RunVoicevoxGUI.commandをクリックして実行すると
以下UIが出力されて、webファイルが出力されるように実装されました。

さらなる改造がしたくなった
ここから、欲が出てもっとカスタマイズできるようにしたいなっていうのがあって
この状態の欠点がAIのプロバイダがOpenAIしか使えないことです。
OpanAIでこのツールを使おうとするとChatGPTの課金契約をし、OpanAIのAPI Keyでアクセスしないといけないです。
そうなると従量課金になってしまうので、最低でも5ドルを注入しておかないといけない
今後も使えるようにgeminiなどのプロバイダに変更できるようにしたいと思ったのが地獄になりました。
ここからが改造のやりとりです
・Windowsの対応がしたい
・Geminiなどの他のプロバイダを選択したい
・自分がやってしまった個人名でのコミットを取り消したい
・Geminiを選択した時にエラるので解決したい!! ← この解決に3~4時間かかってしまった。
WSL環境の利用者向けインストーラが欲しい
[Windowsの初心者でもWSL+依存ツールを一括で整えたい。]
{管理者PowerShell用 `SetupWSL.ps1` を追加し、WSL2・Ubuntu導入と基本パッケージのインストールを自動化。READMEに手順を追記。}
Windows用のワンクリックセットアップ/GUIランチャーが欲しい
[WSLを使っていてもWindows側からダブルクリックでセットアップ・GUIを呼び出したい。]
{`SetupVoicevoxEnvironment_win.ps1` と `RunVoicevoxGUI_win.ps1` を追加し、PowerShellからWSL内でセットアップやGUI起動を実行できるようにした。READMEで案内。}
Gemeni や他APIへ切り替えられるようにしたい
[OpenAI以外のAPIにも対応させたい。]
{LLMクライアントを抽象化する `scripts/llm_client.py` を追加し、OpenAI/Anthropic/Geminiを`--llm-provider`で切り替え可能に改修。READMEも更新。}
CLIのGemini対応でエラーが出る
[Gemini指定時に未インストール扱いが続く&キーの設定ができない。]
{Geminiクライアントのインデントバグを修正し、GUI設定から必要パッケージ導入→キャッシュ無効化→再判定を行うよう改善。設定ウィンドウにAPIキー入力欄とウォーターマークを追加し、保存・呼び出しにも対応。}
READMEの対応OS条件と概要をわかりやすく
[ツールの概要と対応OSを初心者向けに明記してほしい。]
{README冒頭に「AIがキャラクターを推定してVOICEVOXへ自動配役し音声生成するツール」であること、生成物一覧、対応OS(macOS/Linux/WSL必須のWindows10/11)を追記。}
生成された成果物やAPI配役を詳しく説明してほしい
[README冒頭で出力ファイルの説明や配役システムを紹介したい。]
{結合済みWAV、行ごとのWAV、assignments.jsonl、manifest、voice_assignments_auto.yaml など生成結果の説明を追加。}
README に設定画面の説明を載せたい
[GUI設定ボタンからLLMを切り替えられる旨を明記したい。]
{クイックスタートに設定ボタンと `config/llm_settings.json` への保存について追記。}
WSL未利用のWindowsで必要な追加対応の説明
[Windows 10以前についての案内を追加したい。]
{READMEに「WSL対応のWin10/11向け手順」を追記し、WSLが使えない場合は現在サポート外である旨を明記。}
既存コミットの著者名をハンドルネームに変更したい
[個人名でコミットしてしまったので“roripika”名義に変えたい。]
{Git設定を `user.name=roripika` / `user.email=...` に変更し、最新コミットを --amend で上書き。}
リポジトリを GitHub へ初回プッシュしたい
[ローカルから `voicevox-storycaster` リポジトリへ push したい。]
{必要なファイルを `.gitignore` 整理の上で初期コミットし、`git push origin master` に成功(途中の大容量JSONは除外)。}
READMEに動作可能OSの条件を追記したい
[サポートOSを冒頭で明記したい。]
{macOS12+, Ubuntu20.04+, Windows10/11(WSL2+WSLg必須)を README 冒頭に追加。}
Gemini CLI利用時に不足パッケージを自動案内・インストールしたい
[設定画面でプロバイダ未インストール表示が消えないのを改善したい。]
{インストール後に importlib キャッシュを無効化し再判定できるよう修正、成功/失敗のフィードバックを追加。}
設定画面でGeminiパッケージが未インストール表示のまま
[Geminiを選択し必要パッケージをインストールしても「未インストール: google-generativeai」が消えない。]
{チェック処理をモジュール名ベースに変え、インストール直後に importlib キャッシュを無効化して即座に解消するよう改善。}
「未インストール」表示が解消されない最終対応
[改善後も再表示で未インストール扱いになる。]
{Gemini依存チェックでパッケージとモジュールを分けて評価し、キャッシュ無効化後に即座に判定させるよう再修正。blog_summary にも対応内容を追記。}
補足: importlib のキャッシュを都度クリアしても UI の表示更新タイミングに気を使う必要があった。特に GUI から連続操作されるケースを想定すると、UX を損なわない範囲でロジックを簡潔に保つのが難しい。
GUI設定からAPIキー入力欄を設け、保存・復元したい
[設定画面にAPIキー入力フィールドを用意し、プロバイダに応じてウォーターマーク表示、保存したキーを使うようにしたい。]
{設定画面にAPIキー欄を追加し、プロバイダ切り替えで既存キーや環境変数を初期表示、未設定時は「未設定」のウォーターマークを表示。保存したキーは `config/llm_settings.json` に書き込み、音声生成時には環境変数として渡すよう改修。}
補足: 平文保存になるため案内文や UI での注意喚起が欠かせず、初心者でも扱えるよう「未設定」の状態を明示するなど細かい配慮が必要だった。環境変数と保存済みキーのどちらを優先するかも調整ポイント。
LLMプロバイダ設定を外部ファイル化しGemini無料枠モデルをフォロー
[今後モデルが変わることを想定してプロバイダ/モデル一覧をコードから切り離し、無料枠モデルの案内も表示したい。]
{`config/llm_providers.yaml` を追加し、GUI設定画面で動的にプロバイダとモデルを読み込むよう改修。Gemini には `gemini-2.5-flash` / `gemini-2.5-flash-lite` を含め、ノート表示で無料枠のモデルを案内するようにした。依存チェックもコンフィグに基づいて実行。}
補足: YAML で管理すると設定変更は楽になる一方で、構成ファイルのフォーマット崩れやキー名のタイプミスが直ちに GUI の不具合に繋がる。エラー時のフォールバックやデフォルト値をしっかり用意しておく必要がある。
CLI実行時にモジュールが見つからない問題を解消したい
[`.command` や絶対パス経由でスクリプトを起動すると `ModuleNotFoundError: scripts` になる。]
{`auto_assign_voicevox.py` / `novel_to_voicevox.py` の先頭でリポジトリルートを `sys.path` に追加し、どの実行方法でも `scripts.llm_client` をインポートできるようにした。README には Finder 実行時は GUI 設定で API キーを登録する旨も追記。}
補足: スクリプト単体実行・`.command`・GUI 経由など起動パターンが増えるほどパス周りの落とし穴が増える。将来的にはモジュール化して `pip install -e` で解決するのがベターだが、現状は最小修正で回避。
Gemini利用時の出力打ち切り対策とトークン調整オプションが欲しい
[Gemini 2.5 Flash が JSON を途中で切る/finish_reason=2 になるので再現性高く失敗する。]
{Gemini向けプロンプトを厳密化し、LLM クライアントで `candidates[].content.parts` を安全に取り出すよう修正。さらに `auto_assign_voicevox.py` / `novel_to_voicevox.py` に最大出力トークン指定オプションを追加し、README にチューニング方法を記載。}
長文のチャンク分割精度を上げてオーバーラップさせたい
[段落単位だと文が途中で切れたり、チャンクごとに話者推定がぶれる。]
{`novel_to_voicevox.py` を文単位分割+指定文字数で再結合する方式へ変更し、`--chunk-overlap-sentences` で末尾文を次チャンクへ持ち越すよう対応。重複する文の話者・種別は先行チャンクの結果を優先する整合性チェックを追加。}
補足: 文境界推定は正規表現ベースなので、会話記号や三点リーダーが連続するケースでは揺らぎが出る。将来的に日本語形態素解析を組み入れる余地があるが、処理時間や依存ライブラリとのトレードオフが課題。
auto_assign_voicevox の実行ログを残したい
[コマンド実行時にログファイルを自動で出力したい。]
{`auto_assign_voicevox.py` に `--log-file` / `--log-level` を追加し、デフォルトで出力先 `artifacts/auto_assign.log` へも書き出すロギングを構築。主要処理は `logging` で記録し、GUI からの呼び出しでもログが残るようにした。}
補足: 無料枠の Gemini では長文がすぐ `finish_reason=2`(MAX_TOKENS)で途切れるため、CLI に実装したトークン制御やリトライでも厳しいケースが多い。課金環境でも応答が長いと止まりやすいので、より細かなチャンク分割やモデル切り替えが実務での落とし所になりそう。
GeminiでJSON解析が失敗した際のフォールバックを入れたい
[GeminiがJSONを途中で切り、リトライしても失敗が続くケースを改善したい。]
{`scripts/llm_client.py` に `GeminiClient.raw_generate()` を追加し、`auto_assign_voicevox.py` がリトライ後も JSON パースに失敗した場合は `generate_content` を直接呼ぶフォールバックを実装。ログにも fallback 成否を記録するようにした。}
Geminiの出力上限を公式クォータに合わせて調整したい
[1日あたりのリクエスト制限に合わせて生成上限を把握しやすくしたい。]
{Gemini クライアントのデフォルト `max_output_tokens` を 250,000 に固定し、README へ「それでも途切れる場合はテキストを分割するか他モデルを使う」旨を追記。}
これでなんとか動くところまでいきました。。。
まとめ
今回このアプリを作るにあたって、全くもってコーディングしてないです。
自分で作っていたら、
集中してやったとしても2〜3週間かかったと思いますし、
所々に前提知識がないと
できない実装があるので、調べるだけでもかなり時間かかりそうです。
Pythonコードももっと長ったらしい、コードを書いていたと思います。
メンテナンスとか考えたらそっちの方が良いかもしれないですが、
作業ツールやなんかあったら捨ててしまえるようなツールだと、やはり便利なので
今後もAIでツール作っていきそうだなと思います。
また、AIの使い方を巡って
よく職場内で対立するのですが、
1promptで結果を出せるようになりたい派の人と、
AIと対話で精度を上げていけばいい派の人が対立しています。
僕はAIと対話していく方法で実装を高めていく方が
最終到達地点の品質は高いと思っているので、
今後もそういう使い方をしていくと思います。
