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 音楽生成を実装:WebGPU/ONNX による安定稼働・長尺音声接合の実践解説

0
Posted at

はじめに

WebGPUとONNX Runtimeの進化により、サーバーレスでブラウザだけのAI音楽生成が実用的になりました。

しかし実際にStable Audioモデルをブラウザに導入して分かったのは、
「モデルを動かすこと自体は簡単」
「本当に難しいのはブラウザ環境特有のメモリ・キャッシュ・サンプラー・長尺処理の調整」
という点です。

本記事では、オープンソース動画エディタ Timeline Studio に実装した、ブラウザ完全ローカルAI音楽生成の技術詳細・ハマりポイント・解決策をまとめます。

GitHub:https://github.com/martindelophy/ai-video-editor

本記事の対象読者

  • WebGPU / ブラウザ端末AI開発に興味がある方
  • ONNXモデルのフロントエンド実装を学びたい方
  • 音声Diffusionモデルのサンプラー設計・品質改善を知りたい方
  • 長尺音声のシームレス接合技術を調査している方

結論(先にまとめ)

  • ブラウザAI音楽の品質問題は量子化よりもサンプラー不具合が圧倒的に多い
  • 大規模モデルはダウンロード並列・GPU初期化直列が鉄則
  • 長尺音声は完全推論せず短尺推論+スマートループ接合で安定化
  • ブラウザキャッシュは書き込み権限を単一化しないとQuotaエラーが発生
  • 本番運用にはモデルバージョンの固定が必須

1. 採用モデル:Stable Audio 3 Small Q4 ONNX

今回採用したのは Stable Audio 3 Small Music のQ4量子化ONNXモデル です。
全体サイズ 683MB で、M1 16GBなどの一般的なPCでブラウザ推論が可能です。

モデルは4つのモジュールに分かれています。

モジュール 役割 サイズ
Text Encoder プロンプトを条件ベクトルにエンコード 213MB
Number Conditioner 再生時間の条件付け 1MB未満
DiT Diffusion 拡散ノイズ除去の核心演算 380MB
Audio Decoder 潜在変数を44.1kHzステレオ音声に復号 45MB

ブラウザ向け最適化

  1. 100MB以下にファイル分割
    単一巨大ファイルはブラウザのタイムアウト・パース失敗を引き起こすため、重みを分割しています。

  2. 4bit量子化(Q4)

    • 行列演算:MatMul → MatMulNBits
    • 埋め込み層:Embedding → GatherBlockQuantized
    • その他パラメータはFP32保持

量子化によりダウンロード容量・メモリ消費を大幅削減。
トレードオフとして高周波・残響尾に若干の粒ノイズが発生しますが、ブラウザローカル実行の許容範囲です。

2. 並列ダウンロード+直列GPU初期化(最重要設計)

ダウンロード:完全並列

多数のモデル分片をPromise.allで一括取得し、初回起動時間を短縮しています。

const responses = await Promise.all(
  paths.map(path => fetchModelFile(path))
);

GPUセッション初期化:完全直列

WebGPUは複数の大規模セッションを同時初期化するとメモリ爆発します。
特にApple Siliconの統一メモリ環境では高確率でクラッシュします。

そのため初期化順を固定しています。

Text Encoder → Number Conditioner → DiT → Audio Decoder

設計原則

ネットワークIOは並列、GPUリソース初期化は直列

また、一度初期化したWebGPUセッションは保持し、2回目以降の生成はモデルロードなしで高速実行できます。

3. 日本語プロンプト対応:多言語自動変換パイプライン

Stable Audioは英語プロンプト専用のため、日本語入力に対応する独自フローを実装しました。

ユーザー日本語入力
→ 言語判定
→ ブラウザ翻訳
→ 構造化英語プロンプト補完

曲风・雰囲気・BPM・楽器・ボーカル無し制約を自動付与し、生成安定度を高めています。

変換例

入力:雨のカフェで聴く忧郁なピアノ曲
出力:

melancholic jazz piano in a rainy café,
cinematic soundtrack, dreamy, piano,
90 BPM, instrumental music,
clean production, no vocals

翻訳非対応ブラウザではフォールバック表示を行い、不正なプロンプトによる暗黙的な失敗を防いでいます。

4. 音質悪化の原因は「量子化ではなくサンプラーバグ」

初期実装では「高音ノイズ・楽器ぼやけ・リズム崩れ」が発生し、当初はQ4量子化のせいだと判断していました。

しかし真の原因は Rectified Flowサンプラーのスケジュール実装ミス です。

本来の仕様

時間パラメータt1 → 0 まで完全に減衰 する必要があります。

不具合内容

旧実装ではt0.27までしか下がっていなかったため、
最終的な潜在変数に 27%のノイズが残留 し、音質が崩壊していました。

修正後のサンプラーロジック

const logSnr = 2 - t * 8.2;
const sigma = 1 / (1 + Math.exp(logSnr));

schedule[0] = 1;
schedule[steps] = 0;

if (tNext === 0) {
  x = denoised;
}

この修正により、サンプリング数を増やすよりも大幅に音質が改善しました。

重要な知見

端末AIの品質不良は、量子化よりも前処理・サンプラーロジックの不具合が圧倒的に多い

5. 潜在変数 → WAVファイルの完全変換フロー

音声長に応じて潜在長を動的計算します。

latentLength =
  Math.ceil((seconds + 6) * 44100 / 8192) * 2;

DiT出力後、Decoderから出力される形式は以下です。

  • 形状:[1, 2, audioFrames]
  • フォーマット:Float32
  • 範囲:-1 ~ 1
  • サンプリングレート:44100Hz

ブラウザ上で16bit PCMに変換しWAVを生成します。

sample16 = sample < 0 ? sample * 32768 : sample * 32767;

生成後は自動でアセット登録・波形解析・タイムライン登録まで行い、エディタワークフローに直結しています。

6. 長尺音声(90s/120s)の安定化:短尺推論+スマート接合

120秒などの長尺音声を全量推論すると、
WebGPUバッファ確保失敗・メモリオーバー・タブクラッシュが発生します。

そのため次の戦略を採用しています。

  • 90秒指定 → 45秒推論+ループ接合
  • 120秒指定 → 60秒推論+ループ接合

推論コストを半分に削減し、ブラウザの負荷を大幅に低減しています。

7. シームレス接合:ノイズ・クリック音を完全解消

単純なループ再生は音量ジャンプ・位相ズレ・ドラム切断・爆音が発生します。

そこで最終5秒の波形を分析し、複合スコアで最適な切断点を選出しています。

score =
  rms * 0.7
  + amplitudeJump * 0.8
  + slopeJump * 0.25
  + shortenedRatio * 0.08;
  • RMS:低エネルギー区間を優先
  • 振幅変化:音量ジャンプ抑制
  • 傾き変化:波形の不連続抑制
  • 短縮ペナルティ:不自然な早切れ防止

またフェード時間を動的に調整(0.25s~1.5s)

fadeSeconds = clamp(
  0.25 + localRms * 4,
  0.25,
  1.5
);

高音量区間は長めにフェード、無音区間は短く処理し、自然なループを実現しています。

8. 大規模モデルキャッシュのトラブル解決

683MBのモデルを毎回ダウンロードすると実用にならないため、
Service Worker + Cache Storage による永続キャッシュを実装しています。

解決した2つの重大バグ

  1. キャッシュヒットなのにダウンロード表示
    クロスオリジンリクエストでカスタムヘッダーが失われる問題。
    レスポンスヘッダー判定を廃止し、Workerから直接Cache Storageを照会する方式に変更。

  2. QuotaExceededError(容量超過)
    WorkerとService Workerの二重書き込みによる一時的な容量オーバーを防ぐため、
    書き込み権限をService Workerに一本化

大規模モデルキャッシュは「書き込み元を一つにする」ことが安定化の鍵

9. モデル供給安定化:リポジトリミラー+固定コミット

外部HuggingFaceリポジトリ依存は、削除・上書き・更新による突然の障害が発生します。

本番では完全ミラー+固定コミットで安定性を確保しています。

  • ミラー先:haixin/stable-audio-3-small-music-onnx
  • 固定コミット:0b8a05e0bc3511e674b4cb3413d3ef6c48880cdb

全ファイルのSHA256検証を行い、古いキャッシュとの互換も維持しています。

10. ブラウザAI音楽の限界と価値

限界

  • Q4量子化によるわずかな音質劣化
  • 長尺音声はループ合成に依存
  • WebGPU環境依存

メリット(非常に大きい)

  • プロンプト・音声データが完全ローカル処理でプライバシー保護
  • サーバーコスト0
  • 1回ダウンロードで永続キャッシュ
  • 静的ホスティングだけで公開可能
  • エディタワークフローにシームレス統合

まとめ

ブラウザでのAI音楽生成は、
「モデルを動かす技術」よりも
「ブラウザの制約に適応させるエンジニアリング」
が圧倒的に難しいです。

今回の実装で得られた知見は、WebGPUを用いたあらゆる大規模端末AIモデルに通用します。

本機能は完全オープンソースで公開しています。
ぜひStar・Forkで応援してください!

GitHub

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?