AIと作る歌詞PVツール開発録:解析精度にキレ、UIに絶望し、Canvasに救いを求めた男の末路
「歌詞にタイミングを打って、文字PVを作りたい」 ……この一文だけ見れば、いかにもキラキラしたクリエイティブな開発に聞こえるだろう? だが、蓋を開けてみれば始まったのは、Whisperの「沈黙の艦隊」問題、wav2vec2の「気まぐれシェフ」状態、そして“Main UIに全部盛り込むな”という物理的限界との泥仕合だった。
現在作っているのは、音声と歌詞から project.json を錬成し、ユーザーが「これじゃない」と修正しながら、最終的に「なんかそれっぽい動画(笑)」を野ネズミのような素人でも出せるようにするツールだ。
設計は project.py(モデル)、api_server.py(通信)、pipeline.py(解析)と、一見すると「意識高い系エンジニア」のような綺麗さを保っている。……が、現場の現実はクソ。甘くない。
1. 最初の敵は精度ではなく「ユーザーの期待(と絶望)」
開発のスタート地点は、AIによる歌詞タイミング解析だ。 Whisperでアタリを付け、文字単位で時刻を振る。理屈は美しい。だが、リアルの歌はだいたい汚い。
高速ラップ、英語混じり、BGMがバカデカい曲、そして謎のビブラート(メリスマ)。 Whisperくんは「だいたい合ってる」という、一番タチの悪い嘘をつく。 特定区間がガッツリ欠損しても、後続のロジックが「まあ、この辺でええやろw」と適当に埋める。 その結果生まれるのは、
-
そもそもゴミ
-
群れの前半は盛大にズレる
-
最後の方で無理やり帳尻が合う
-
行によっては8秒くらい虚空を舞う
という、人類が最も嫌悪する「なんか変」の極致だ。 「AIのスコアが高い」ことと「人間が聴いて合っている」ことは、宇宙の法則レベルで別物だと痛感した。
2. Demucsは「曲を選ぶ救世主」だった
次に投入したのが、ボーカル分離のDemucsだ。 声だけ抜いて食わせればWhisperも本気を出すだろう、と思ったらこれが大正解で笑えた。 欠損16秒が4秒まで縮んだときは「勝った!完!」と思ったね。 ……ただし、「相性による」というオチがつく。
高速ラップソングでゴミ箱へと回帰した。思い付きで別の分離ソフト通したボーカル音源を入れると精度が爆上がりしたのだが、その時、私は悟った。 これはAIの精度の問題じゃない。「何を食わせるか」という、もはや料理人の世界なのだ。 AIという最新兵器を使っているはずが、やってることは「前処理の泥抜き」という内職。実にテック記事っぽくて、涙が止まらない。
そして右往左往したあげくの果てに、Demucsのモデルを高機能なものに変更するだけでいいかも知れない。という2段オチの可能性に膝も笑い始める。
3. 「問題は解析よりUIでは?」という不都合な真実
解析と格闘していると、別の地獄が見えてくる。 内部モデルは Line だの Char だの、自動修正と手動修正の差分まで保持できる「最強の設計」になっていた。 だが、UIが完全に「開発者専用のコックピット」だったのだ。
行ごとのエフェクト設定、文字ごとのパラメータ、旧プリセットの残骸……。 ユーザーがやりたいのは「エモいネオン感にしたい」であって、「fly_topとscale_inのどちらを適用するか」などではない。 ここでようやく、私の脳内で「全部入りUI」という思想をゴミ箱に捨てる決断が下った。
4. 「Main UI」と「Gallery UI」の絶縁宣言
メイン画面に何でも押し込むのは罠だ。 メインは「歌詞を見る」「直す」「再生する」場所。 素材を探す場所は別に作ればいい。
-
Main UI: 制作・確認・修正に特化
-
Gallery UI: テーマやプリセットをタグやサムネで「雰囲気」で選ぶ場所 この整理がついた瞬間、ツールがようやく「呼吸」を始めた気がする。
さらに、「Theme(見た目)」と「Preset(動き)」を分離した。 「色だけ変えたい」のに動きまでセットで変わる不自由さからの脱却だ。 全曲デフォルト → セクション上書き → 行上書きという三層構造。 これでようやく、素人が「テンション」で動画を作れる土台が見えてきた。
5. Canvas移行:大人への階段(あるいは敗北宣言)
描画エリア(Stage)も大きな転機だった。 最初はDOM(ブラウザの要素)で頑張っていた。GSAPで文字を飛ばせば、それっぽく見えた。 だが、その先の「発光、パーティクル、グリッチ、画面の揺れ」をDOMでやろうとしたら、ブラウザが「俺を殺す気か?」と悲鳴を上げるのは目に見えている。
そこで、StageだけをPixiJS(Canvas)に寄せることにした。 いきなり全面移行する勇気はないので、DOMとCanvasを並存させ、地味に、安全に、一歩ずつ移植する。 これを「大人」と呼ぶか「日和った」と呼ぶかは自由だ。
6. 生まれたてのStageState
最後に出てきたのが、「StageState」という化け物だ。 Galleryでポチポチ設定を変えたとき、いちいち再生が止まったり再構築されたりするのは、UX(ユーザー体験)の死を意味する。 「再生中にリアルタイムで反映される」というTextAliveのリスペクト機能を実現するために、全設定を1つのstoreにぶち込んだ。
途中でデータ構造が複雑すぎて死にかけたり、フラットな構造に戻したりという「開発あるある」を完遂し、ようやく「再生しながら色をライブパッチできる」ところまで漕ぎ着けた。
結局、何が進んだのか?
一言で言えば、 「音声解析ツールを作っていたつもりが、最終的に『リアルタイムで気持ちよく選べる制作環境』を作っていた」 ということだ。
もちろん、プリセットを50個作る地獄や、Canvas移植の苦労はこれからだ。 だが、もう迷走はしていない。「何をどこに置くか」の思想は固まった。 開発が「迷走フェーズ」から「積み上げ(地獄)フェーズ」に入ったことを、ここに報告しておく。
次に地獄を見るのは、エフェクトの数が増えすぎてブラウザのメモリが足りなくなった時だろう。 それはそれで面白いから、よしとする。

