はじめに
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 |
ブラウザ向け最適化
-
100MB以下にファイル分割
単一巨大ファイルはブラウザのタイムアウト・パース失敗を引き起こすため、重みを分割しています。 -
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サンプラーのスケジュール実装ミス です。
本来の仕様
時間パラメータtは 1 → 0 まで完全に減衰 する必要があります。
不具合内容
旧実装ではtが0.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つの重大バグ
-
キャッシュヒットなのにダウンロード表示
クロスオリジンリクエストでカスタムヘッダーが失われる問題。
レスポンスヘッダー判定を廃止し、Workerから直接Cache Storageを照会する方式に変更。 -
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