0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ローカルAI作曲の品質を"数値"で測る — mlx-whisperで歌詞一致率を採点するQAパイプラインを作った実録

0
Posted at

📝 この記事は Zenn(正本) からの転載です。図表・最新版はオリジナルをご覧ください。

テイクは増えるのに、聴く時間は増えない

ローカルでAI作曲を回すようになって、最初にぶつかった壁は「品質そのもの」ではなかった。だった。

生成エンジンには ACE-Step 1.5 を使っている。Apple Silicon の MLX 上でローカルAPIとして動く、0.6B のLM付き音楽生成モデルだ。英語ボーカルのAI楽曲を作る用途で回すと、1曲を確定させるまでに驚くほどテイクが積み上がる。パラメータやシード違いで v1 / v2、さらにそれぞれ2バリアント。1曲あたり4テイクは平気で出る。今回のバッチでは、これが合計 32テイク になった。

問題はここからだ。生成されたテイクを一つずつ聴くと、確かに「メロディは良い」。伴奏の質感も悪くない。ところが歌詞を正しく歌えていないテイクが一定数混ざる。母音が溶けて別の単語に聞こえる、語尾が欠ける、そもそも意図した歌詞の一部を飛ばしている。こういうテイクは、メロディの良さに引きずられると聴き逃す。

32テイクを毎回フルで人手検聴していたら、確定作業だけで一日が溶ける。しかも耳は疲れる。3曲目あたりから判断がブレる。人間の集中力に品質保証を全振りするのは、そもそも設計として破綻していた。

欲しかったのは、聴く前に候補を機械的に間引く**「足切り指標」**だった。

着想:歌えているかは、文字起こしで測れる

歌ものの品質には多くの軸がある。音程、リズム、音質、表現。そのどれもを一発で数値化するのは難しい。だが今回いちばん困っていたのは「歌詞を正しく歌えているか」という一点だった。ここだけなら、意外と素直に数値化できる。

発想はシンプルだ。生成した音源を文字起こしして、意図した歌詞テキストとの一致率を出す。 歌えていれば転写は元の歌詞に近づくし、崩れていれば離れる。一致率という一本の数字にすれば、32テイクを並べて機械的に順位づけできる。

文字起こしには mlx-whisper を選んだ。Apple Silicon ネイティブの Whisper 実装で、クラウドにアップロードせず完全にローカルで動く。API課金もアップロードの待ち時間もない。生成が ACE-Step でローカル、採点の入口も mlx-whisper でローカル。手元のマシンだけで品質ゲートが完結する構図になる。ここが個人でAI音楽を大量に回す上で決定的にありがたい。無料で、何度でも回せる。

もちろん Whisper の転写は完璧ではない。だがこの段階で必要なのは「完璧な書き起こし」ではなく「テイク同士を相対比較できるだけの再現性」だ。同じモデルで全テイクを同条件で転写すれば、少なくとも横並びの比較には耐える。

パイプライン:生成と採点を分離する

組んだQAの流れはこうなった。

ローカルAI音楽QAパイプライン

図の通り、処理は4段だ。

  1. 生成 — ACE-Step 1.5 でテイクを出す。1曲につき v1 / v2 × 2バリアント。
  2. 文字起こし — 出力音源を mlx-whisper に通し、歌われた内容をテキスト化する。
  3. 歌詞一致率の算出 — 転写テキストと、意図した歌詞テキストを突き合わせて一致率を出す。ここが自動の足切りゲートになる。
  4. 独立ルーブリック採点 — 一致率を通過した候補を、ルーブリックに沿って採点する。

このパイプラインで意図的にこだわった点が一つある。採点を、生成したモデル自身にはやらせないことだ。

生成モデルに「この曲どうだった?」と自己評価させると、評価が生成の都合に引っ張られる。自分の出力を甘く見る。これは主観テストの世界で言うところの、作った本人が審査員を兼ねる状態で、品質ゲートとしては信用できない。だから採点は生成とは別プロセスで、独立したルーブリックに沿ってやる。生成と評価を物理的に切り離すこと自体が、このゲートの肝だと考えている。

そして最後、低スコアで引っかかったテイクだけを人間の耳で最終判定する。全数検聴はしない。機械が「怪しい」と指したものだけに、人間の集中力を集中投下する。これで検聴の総量が一気に減った。

実測:32テイクを8本に絞る

実際に回した結果が下の数字だ。

32テイク→8本・一致率の分布

  • 生成した総テイク数:32(1曲あたり v1 / v2 × 2バリアント)
  • 3層の品質ゲート(①歌詞一致率 ②独立ルーブリック採点 ③人間の耳)を通して確定させた最良テイク:8本
  • 確定8本の歌詞一致率 平均:83.9%
  • 確定8本の独立ルーブリック 平均:94.1点
  • ゲートを通した後の差し戻し:1回
  • 各曲の尺は 100〜120秒afinfo で実測)

図の漏斗が示すのは、32という入口の広さと、8という出口の狭さだ。ざっくり4テイク作って1本を残す歩留まりで、残りの3本はメロディが良くても歌詞が崩れていたり、ルーブリックの基準に届かなかったりで落ちている。この「作りすぎて削る」前提こそが、量産の現実だ。だからこそ、削る工程を自動化しないと回らない。

尺を afinfo で実測したのも意図がある。生成モデルの申告する長さと、実ファイルの再生長は必ずしも一致しない。品質を数値で語るなら、尺も推定でなく実ファイルから読む。当たり前のことだが、ここを推定で埋めると数字全体の信頼が崩れる。

差し戻しが1回で済んだのは、足切りが効いた結果だと見ている。耳の判定に回る前に、一致率と独立採点で明らかな失敗テイクが落ちているので、最終検聴での「やっぱりダメ、作り直し」が減った。

前言撤回:一致率が低い曲=ダメな曲、ではなかった

ここまで読むと「一致率で足切りすれば万事解決」に見える。私も途中までそう思い込んでいた。一致率が低い = 歌えていない = ダメな曲、と。

だが、これは間違いだった。

一致率が明らかに低く出る一群があった。調べると、共通点は曲の中身にあった。アルファベットの羅列のように、単語ではなく**「文字そのものを歌う」タイプの曲**だ。この種の曲は、実測で一致率が 75.3% まで落ちた。確定8本の平均83.9%からすると、はっきり低い。

だが実際に耳で聴くと、その曲はちゃんと歌えていた。崩れていたのは曲ではなく、Whisperの転写のほうだった。

理由は考えてみれば当然で、Whisperは自然言語の音声を書き起こすように訓練されている。文脈のある単語や文なら強い。ところが「エー、ビー、シー…」と一文字ずつ歌うような、言語モデル的な文脈が薄い発話は構造的に苦手だ。転写が揺れ、元テキストとの一致率が下がる。つまりこの75.3%は曲の失敗ではなく、測定器の限界を映した数字だった。

これは重要な教訓だった。自動採点は足切りであって、最終判定ではない。一致率が低いテイクを機械的に全部捨てていたら、実際には歌えている良いテイクを、測定器の癖のせいで巻き添えで殺していたことになる。

だから運用のルールをこう固めた。低スコアのテイクは、捨てる前に必ず耳で確かめる。 高スコアは信じてよい(歌えているから一致する)。だが低スコアは「歌えていない」と「測れていない」の両方があり得るので、機械の判定をそのまま死刑宣告にしない。数値ゲートの正しい使い方は、人間の検聴を減らすことであって、置き換えることではなかった。

環境の落とし穴:Python は arm64 ネイティブで掴む

技術的な足元の話を一つ。mlx 系のツールは Apple Silicon (arm64) ネイティブで動かすことが前提だ。ここを外すと、そもそも動かなかったり、動いても遅くなったりする。

ありがちな罠が、Rosetta 下の x86_64 Python を掴んでしまうケースだ。Homebrew や pyenv、複数の Python が同居している環境では、意図せず x86_64 側の python が優先されることがある。mlx はネイティブ実行を前提にしているので、この状態だと本来の性能が出ない。

対策はシンプルで、着手前に自分の Python が arm64 かを確認すること。

python3 -c "import platform; print(platform.machine())"

これが arm64 と返れば正しい。x86_64 と出たら、それは Rosetta 越しの Python なので、mlx を回す前に環境を切り替える。文字起こしがどうにも遅い、あるいは MLX が期待通りに動かない、というときは、モデルやコードを疑う前にまずこの一行を打つ。土台がずれていると、その上でいくらチューニングしても報われない。

まとめ:数値は足切り、最終判定は耳

ローカル無料の道具立て(ACE-Step 1.5 で生成、mlx-whisper で文字起こし)だけで、「歌えているか」を数値化する品質ゲートを組めた。32テイクを機械で間引き、8本を確定させ、耳の検聴総量を大きく削れた。得られた学びを整理する。

  • 量産の品質保証は、まず足切りを自動化する。 全数を人手で聴く設計は集中力に依存して破綻する。機械的に順位づけできる一本の数字(ここでは歌詞一致率)を先に用意する。
  • 採点は生成と分離する。 生成モデルに自己評価させない。独立したルーブリックで別プロセス採点にすることが、ゲートの信頼性を担保する。
  • 数値は足切りであって最終判定ではない。 文字を歌う曲のように、測定器(Whisper)が構造的に苦手なケースでは低スコアが出る。低スコアは捨てる前に必ず耳で確かめる。
  • 土台の環境を最初に確かめる。 mlx を使うなら Python は arm64 ネイティブが必須。platform.machine()arm64 であることを着手前に確認する。

自動化の価値は「人間を消す」ことではなく、「人間の判断を、本当に判断が要る場所に集める」ことにある。数値ゲートは検聴の入口を絞るためのもので、出口の耳は最後まで人間が握る。この役割分担が、ローカルAI音楽を量産しながら品質を落とさないための、いまのところの現実解だ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?