# UVR5（MDX-Net）完全ガイド：公式準拠でボーカル/伴奏を高精度分離し本番自動化する

> オープンソースの音源分離ツール UVR5 と MDX-Net アーキテクチャを、公式情報（GitHub・arXiv論文）に忠実に解説。GUIでの試用から python-audio-separator によるコード自動化、モデル選定（Inst/Vocal/Karaoke）、segment_size等のチューニング、OOM・CPUフォールバック・冪等性・可観測性まで、本番運用の実装を具体コードで示します。

- 公開日: 2026-06-25
- 著者: 友田 陽大
- タグ: UVR5, MDX-Net, 音源分離, ボーカル抽出, Python, AI音声, MLOps, 生成AI
- URL: https://tomodahinata.com/blog/uvr5-mdx-net-vocal-separation-production-guide

## 要点

- UVR5（Ultimate Vocal Remover GUI v5.6・MITライセンス）は『最先端の音源分離モデルで音声からボーカルを除去する』GUIアプリ。MDX-Netはその中核アーキテクチャの一つで、ボーカル/伴奏の分離に特に強い
- MDX-Netの正体は韓国KUIELabの二段構成ネットワーク（周波数領域のTFC-TDF-U-Net + 時間領域のDemucsをブレンド）。ISMIR 2021 Music Demixing ChallengeでLeaderboard A 2位・B 3位（arXiv:2111.12203）
- GUIで試すなら本体、自動化するなら python-audio-separator（pip install "audio-separator[gpu]"）。Separatorクラス3行でボーカル/伴奏の2ステムを44.1kHzで出力できる
- モデルは目的で選ぶ：伴奏が欲しいならInst系（UVR-MDX-NET-Inst_HQ_3）、ボーカルならKim_Vocal_2、ハモリ除去ならKARA_2。segment_size/overlap/denoiseでVRAM・速度・品質を制御する
- 本番ではOOM・GPU未使用のCPUフォールバック・モデル初回DLが必ず詰まる。モデル常駐・冪等キャッシュ・onnxruntime-gpu検証・GPU直列化・構造化ログで回復性とコストを担保する

---

## この記事のゴール

**UVR5（Ultimate Vocal Remover GUI）** は、1曲の音声を **ボーカル（声）と伴奏（インスト）に分離**するオープンソースの定番ツールです。公式README はその役割をこう書いています——「**This application uses state-of-the-art source separation models to remove vocals from audio files.**（最先端の音源分離モデルで音声からボーカルを除去する）」。

そして **MDX-Net** は、UVR5 が搭載する複数のAIアーキテクチャの中でも、**ボーカル/伴奏分離で最もよく使われる中核モデル**です。

本稿は、その**公式情報（[UVR5 GitHub](https://github.com/Anjok07/ultimatevocalremovergui) / [MDX-Net 論文 arXiv:2111.12203](https://arxiv.org/abs/2111.12203) / [python-audio-separator](https://github.com/nomadkaraoke/python-audio-separator)）に厳密に基づきつつ**、公式ドキュメントには書かれていない「**どの場面で・どう使い・どこで詰まるか**」を、実際に動くコードで埋めるものです。読み終えたときに、次の3つができる状態を目指します。

1. UVR5 と MDX-Net が**何をするツールで、なぜ精度が高いのか**を、人に説明できる。
2. **GUI（試す）** と **python-audio-separator（自動化する）** のどちらを選ぶべきか判断し、**今日中に手を動かせる**。
3. デモではなく**本番**——長尺でのOOM・GPUが効かないCPUフォールバック・モデルの初回ダウンロード——に耐える**回復性のある実装**を組める。

> **筆者について（信頼性の開示）**：私は、動画をアップロードするだけで「**音声分離 → 文字起こし → 翻訳 → 多言語吹き替え → 口元同期**」まで全自動化する **AI動画ローカライズ基盤を単独で設計・実装し、本番運用**しています。その**第1段が、まさにこの音源分離**です。声と背景音楽（BGM）を分けてから文字起こし・翻訳に回すことで認識精度が上がり、伴奏を保持したまま吹き替え音声を被せられる——この前処理の良し悪しが、後段すべての品質を決めます。本稿の「落とし穴」と「回復性設計」は、デモ用の知識ではなく、その実運用で踏み抜いた地雷の記録です。後段の文字起こしは[Whisper の記事](/blog/openai-whisper-production-guide-selfhost-vs-api)、口元同期は[LatentSync の記事](/blog/latentsync-lip-sync-diffusion-model-production-guide)、パイプライン全体は[ローカライズ基盤の記事](/blog/production-ai-video-localization-lipsync-gpu-pipeline)にまとめています。

---

## 30秒のまとめ（結論を先に）

| 観点 | 結論 |
| --- | --- |
| **何のツールか** | 1つの音声を**ボーカルと伴奏（その他ステム）に分離**するOSS。GUI版が **UVR5 v5.6**（MITライセンス） |
| **MDX-Netとは** | UVR5搭載の中核AIアーキテクチャ。**周波数領域+時間領域の二段構成**でボーカル/伴奏分離に強い |
| **学術的根拠** | KUIELab-MDX-Net（[arXiv:2111.12203](https://arxiv.org/abs/2111.12203)）。**ISMIR 2021 Music Demixing Challenge で Leaderboard A 2位・B 3位** |
| **試すだけ** | **UVR5 GUI**：Win/Mac/Linux対応。ドラッグ&ドロップで分離。非エンジニアでも使える |
| **自動化する** | **python-audio-separator**：`pip install "audio-separator[gpu]"`。`Separator` クラス3行でCLI/サーバー組み込み |
| **必要GPU** | **GTX 1060 6GB が最低**、**8GB以上のVRAM推奨**（公式README）。Apple Silicon は MPS 対応 |
| **出力** | 既定で**2ステム（Vocals / Instrumental）**、サンプルレート **44.1kHz** |
| **モデルの選び方** | 伴奏が欲しい→ **Inst系**（`UVR-MDX-NET-Inst_HQ_3`）／声が欲しい→ **Vocal系**（`Kim_Vocal_2`）／ハモリ除去→ `UVR_MDXNET_KARA_2` |
| **品質の主ノブ** | `segment_size`（大=速い・VRAM増）／`overlap`（境界アーティファクト低減）／`enable_denoise`（残響ノイズ抑制・約2倍コスト） |
| **向く用途** | 動画ローカライズ前処理・カラオケ音源/アカペラ作成・ポッドキャストのBGM除去・音声データセットの前処理 |
| **向かない用途** | リアルタイム/ゼロレイテンシ処理、著作権処理を伴うステムの無断再配布 |

「**まずドラッグ&ドロップで品質を見たい**」なら [GUI 章](#使い方aまず-gui-で試すuvr5-本体)へ、「**サーバーに組み込みたい**」なら [コード章](#使い方bコードで自動化python-audio-separator)へ飛んでください。

---

## UVR5 / MDX-Net は何をするのか

入力は **1つの音声（または動画の音声トラック）**、出力は **分離された複数のステム**です。最も基本的な使い方では、UVR5 は音声を **「ボーカル」と「インストゥルメンタル（伴奏）」の2つ**に分けます。

これが効くのは、たとえば次のような場面です。

- **動画ローカライズ（吹き替え）の前処理**：元動画から**声だけを抜いて文字起こし・翻訳**に回す。背景音楽が混ざったまま ASR にかけると認識精度が落ちるが、声を分離すれば精度が上がる。さらに**伴奏トラックは保持**しておき、吹き替え音声の下に再ミックスすれば、BGM ごと差し替わる違和感を防げる。
- **カラオケ音源 / アカペラの作成**：曲から**伴奏だけ**を取り出してカラオケに、**ボーカルだけ**を取り出してアカペラ・リミックス素材にする。
- **ポッドキャスト / 会議音声のクリーニング**：収録に紛れ込んだ **BGM やノイズを除去**して、声を聞き取りやすくする。
- **音声データセットの前処理**：TTS / ASR 学習用に、**音楽や環境音を除いたクリーンな音声**を量産する。

逆に、**ゼロレイテンシのリアルタイム処理**（ライブ配信の即時分離など）には向きません。MDX-Net は1ファイルをまとめて処理する**バッチ志向**で、品質と引き換えにそれなりの計算時間を要します。

> ⚖️ **著作権の注意（重要）**：音源分離の技術それ自体は中立ですが、**処理対象の音源にはほぼ常に著作権**があります。市販曲を分離して得たステムを**無断で再配布・公開する行為は権利侵害**になり得ます。UVR5 のコードは MIT ライセンスでも、それは**「あなたが処理する音声の権利」とは別問題**です。自作曲・許諾済み素材・私的利用の範囲で使ってください。

---

## 仕組み：なぜ MDX-Net は分離精度が高いのか（論文準拠でやさしく）

ここは MDX-Net の核心を、**正確さを保ったまま噛み砕く**章です。実装だけ知りたい人は[次章](#アーキテクチャの選び方mdx-net-vs-vr-vs-demucs-vs-mdx23c)へ飛んで構いません。ただし「なぜ落とし穴がああいう形で出るのか」はここを理解していると腑に落ちます。

> 📌 **正確性のための注記**：UVR5 の README には「MDX-Net とは何か」を説明する文章は**ありません**（搭載アーキテクチャはクレジット欄で `Kuielab & Woosung Choi` に帰属表示されているだけ）。アーキテクチャの定義は、以下の**学術論文を一次情報**として参照します。

### 出発点：音源分離は「混ざった波形を解く」問題

1曲の波形は、ボーカル・ドラム・ベース・その他が**足し合わさった1本の信号**です。音源分離（source separation / music demixing）は、この足し算を**元の成分に解き戻す**タスク。アプローチは大きく2系統あります。

- **周波数領域（time-frequency）**：音声を STFT でスペクトログラム（時間×周波数の画像）に変換し、**画像処理的な U-Net** で各成分のマスクを推定する。
- **時間領域（time-domain）**：波形そのものを畳み込みネットワークで直接処理する（**Demucs** が代表）。

それぞれ得意・不得意があり、**どちらか一方では限界**があります。

### MDX-Net の答え：二段構成（two-stream）でブレンドする

MDX-Net の原典は、韓国 KUIELab（高麗大学）の **「KUIELab-MDX-Net: A Two-Stream Neural Network for Music Demixing」**（[arXiv:2111.12203](https://arxiv.org/abs/2111.12203)、Minseok Kim・Woosung Choi ほか）です。論文の要旨が設計思想を端的に表しています。

> *The proposed model has a time-frequency branch and a time-domain branch, where each branch separates stems, respectively. It blends results from two streams to generate the final estimation.*

つまり——

1. **周波数領域ブランチ**：スペクトログラムを処理する **TFC-TDF-U-Net v2**（後述の系譜）でステムを推定する。
2. **時間領域ブランチ**：**学習済み Demucs** を（追加学習なしで）使い、波形側からも推定する。
3. **ブレンド**：2つの推定結果を**重み付き平均で統合**し、最終出力とする。

周波数領域は「成分の輪郭」を、時間領域は「波形の質感」を捉えるのが得意で、**両者を合成することで単独モデルより安定して高品質**になる——これが MDX-Net の強さの正体です。

### 実績：Sony/AIcrowd の Music Demixing Challenge 2021

KUIELab-MDX-Net は、Sony と AIcrowd が主催した **ISMIR 2021 Music Demixing (MDX) Challenge** で、**Leaderboard A で2位、Leaderboard B で3位**を獲得しました（論文要旨より）。

> ⚠️ **正確さのために**：これは「**2位/3位**」であって「**優勝**」ではありません。ネット上の解説には「優勝」と書くものもありますが、一次情報（論文要旨）に従い、本稿は正確に記載します。それでもこの順位は、**限られた学習データ条件で達成されたもの**で、実用品質として十分に高いという評価です。

### 系譜：TFC-TDF ブロック（ISMIR 2020）

MDX-Net の周波数領域ブランチの土台は、同じ研究室の先行研究 **「Investigating U-Nets with various Intermediate Blocks for Spectrogram-based Singing Voice Separation」**（[arXiv:1912.02591](https://arxiv.org/abs/1912.02591)、ISMIR 2020、Woosung Choi ほか）にあります。ここで提案された **TFC-TDF ブロック（Time-Frequency Convolutions + Time-Distributed Fully-connected）** が、複素スペクトログラムを扱う U-Net の中間ブロックとして高い分離性能を出しました。

整理すると、系譜はこうです。

```text
TFC-TDF ブロック / U-Net           （ISMIR 2020, arXiv:1912.02591）
        ↓ 発展
TFC-TDF-U-Net v2 を内蔵した
KUIELab-MDX-Net（二段構成 + Demucs）（MDX Challenge 2021, arXiv:2111.12203）
        ↓ UVR5 に実装・モデル配布
UVR-MDX-NET / Kim_Vocal / KARA …  （Anjok07/ultimatevocalremovergui に搭載）
```

### この仕組みが「落とし穴の形」を決めている

仕組みを押さえると、後述のトラブルが**必然**だと分かります。

- 周波数領域処理は **STFT のチャンク単位（`segment_size`）で GPU に載せる**ため、ここが **VRAM と速度を直接左右**する。
- チャンク境界に**継ぎ目アーティファクト**が出るので、`overlap` で重ねて緩和する（その分遅くなる）。
- 推論は **ONNX Runtime（`.onnx` モデル）** で走るため、**CUDA/cuDNN が噛み合わないと黙って CPU に落ちて激遅**になる。

つまりパラメータは「気分」で回すものではなく、**この設計の延長線上で意味を持つノブ**なのです。

---

## アーキテクチャの選び方：MDX-Net vs VR vs Demucs vs MDX23C

UVR5 は MDX-Net 以外にも複数のアーキテクチャを搭載しています（READMEのクレジットで原作者が明示されています）。**用途で選ぶ**のが正解で、万能の1つはありません。

| アーキテクチャ | 方式 | 原作者（README） | 得意 | 形式 |
| --- | --- | --- | --- | --- |
| **MDX-Net** | 周波数+時間の二段構成 | Kuielab & Woosung Choi | **ボーカル/伴奏の2分離・速度と品質の総合力** | `.onnx` |
| **VR Architecture** | スペクトログラムU-Net | tsurumeso | 残響・エコー除去、TTA/aggression等の細かい制御 | `.pth` |
| **Demucs（v4 htdemucs）** | 時間領域 | Adefossez & Demucs（Meta） | **4ステム分離**（vocals/drums/bass/other）、Apple Silicon対応 | `.ckpt` |
| **MDX23C / MDXC** | MDXの後継・高品質化 | ZFTurbo | 最新世代の高品質分離 | `.ckpt` |

**選び方はシンプルです。**

- **ボーカルと伴奏の2つに分けたいだけ** → **MDX-Net**。最も実績があり、速度と品質のバランスが良い。本稿の主役。
- **ドラム・ベース・その他まで4ステムに分けたい**（リミックス・採譜・耳コピ）→ **Demucs v4（htdemucs）**。Apple Silicon の MPS でも動く。Demucs 単体の本番運用は[専用ガイド](/blog/demucs-v4-music-source-separation-production-guide)で詳しく扱っています。
- **残響・エコーを除去したい** → **VR Architecture** の専用モデル。
- **とにかく最新の最高品質を試したい** → **MDX23C/MDXC** や、複数モデルの **アンサンブル**。

> 💡 **アンサンブルという奥の手**：UVR5 は複数モデルの出力を統合する **Ensemble モード**を持ちます。`Kim_Vocal_2`（ボーカル特化）と `UVR-MDX-NET-Inst_HQ_3`（伴奏特化）を組み合わせると、単独より残留が減りやすい——ただし**処理時間はモデル数だけ増える**ので、品質最優先のときの選択肢です。

---

## 使い方A：まず GUI で試す（UVR5 本体）

「自分の音源で品質が通用するか、まず確かめたい」段階では、**コードを書かず GUI で叩く**のが最短です。非エンジニアでも使えます。

1. [公式リリース](https://github.com/Anjok07/ultimatevocalremovergui/releases)から OS に合うインストーラを入手（**Windows 10+ / macOS Big Sur+ / Linux**）。Windows は **C: ドライブ直下**へのインストールが推奨です。
2. 起動後、**Process Method** で **MDX-Net** を選択。
3. **モデル**に `UVR-MDX-NET-Inst_HQ_3`（伴奏抽出）などを選び、初回はモデルが自動ダウンロードされる。
4. 音声/動画ファイルを**ドラッグ&ドロップ**し、出力先を指定して **Start Processing**。

**動作要件（公式README）**：

- GPU は **NVIDIA GTX 1060 6GB が最低要件、8GB 以上の VRAM 推奨**。
- **AMD は現状サポートが限定的**。
- **Apple Silicon（M1 以降）は MPS（GPU）アクセラレーションに対応**——Demucs v4 と**すべての MDX-Net モデル**で利用可能。
- Intel Pentium / Celeron 系 CPU は動作保証外。

GUI は手軽ですが、**バッチ処理・サーバー組み込み・CI連携には向きません**。「毎回手で1ファイルずつ」は本番では破綻します。自動化は次章のライブラリで行います。

---

## 使い方B：コードで自動化（python-audio-separator）

UVR5 本体は GUI アプリなのでスクリプトから直接は叩けません。**コードで自動化するときの正解は、UVR と同じモデル（`.onnx` 等）を読み込めるライブラリ [python-audio-separator](https://github.com/nomadkaraoke/python-audio-separator)** を使うことです。UVR5 と**同じ MDX-Net モデルを CLI / Python から**実行できます。

### 1. インストール（公式手順に忠実）

```bash
# GPU（NVIDIA CUDA）。本番はこちら
pip install "audio-separator[gpu]"

# CPU / Apple Silicon
pip install "audio-separator[cpu]"

# conda
conda install audio-separator -c pytorch -c conda-forge
```

- **Python は 3.10 以上**が必要。
- 推論は **ONNX Runtime（`.onnx` の MDX-Net/VR モデル）+ PyTorch（Demucs等の `.ckpt`）** で走る。
- **対応 CUDA は 11.8 と 12.2**。GPU 版で「動くのに激遅」のときは、ほぼ **CUDA/cuDNN と onnxruntime-gpu の不整合**（後述の落とし穴①）。

### 2. 最小コード（3行で動く）

公式の最小例はこうです。`Separator` を作り、モデルを読み、`separate()` を呼ぶだけ。

```python
from audio_separator.separator import Separator

separator = Separator()                  # 既定設定で初期化
separator.load_model(                     # MDX-Netの伴奏抽出モデルを指定（初回は自動DL）
    model_filename="UVR-MDX-NET-Inst_HQ_3.onnx"
)
output_files = separator.separate("song.wav")
print(output_files)
# 例: ['song_(Vocals)_UVR-MDX-NET-Inst_HQ_3.wav',
#      'song_(Instrumental)_UVR-MDX-NET-Inst_HQ_3.wav']
```

`separate()` は**生成された出力ファイルのパスのリストを返します**。既定では **Vocals と Instrumental の2ステム**が、**44.1kHz** で出力されます。出力フォーマットは指定でき、**ライブラリの既定は `WAV`** です。

> ⚠️ **既定値の食い違い（要注意）**：`output_format` の既定は、**Python の `Separator` では `WAV`**、**CLI（`--output_format`）では `FLAC`** と**異なります**。後段で再ミックスするなら**可逆な `flac`/`wav` を明示**するのが安全です（`mp3` は劣化する）。

### 3. CLI（バッチ・シェル・CI向け）

サーバー上での単発・バッチ実行なら CLI が手軽です。

```bash
# 1ファイルを伴奏抽出モデルで分離
audio-separator song.wav \
  --model_filename UVR-MDX-NET-Inst_HQ_3.onnx \
  --output_dir ./stems \
  --output_format flac

# 利用可能なモデルを一覧（"今この瞬間"の正確なファイル名はこれで確認するのが確実）
audio-separator --list_models --list_filter vocals

# 伴奏だけ欲しい（片方のステムのみ出力＝書き出しを減らす）
audio-separator song.wav \
  --model_filename UVR-MDX-NET-Inst_HQ_3.onnx \
  --single_stem Instrumental
```

> 🔧 **CLIとライブラリで名前が違うパラメータ**：片方のステムだけ出すオプションは、**CLI では `--single_stem`**、**Python の `Separator` では `output_single_stem`** です。同じ機能なのに名前が違うので取り違えに注意。

### 4. MDX-Net のパラメータ（既定値と意味）

`Separator` の `mdx_params` で MDX-Net の挙動を制御します。**以下は audio-separator の既定値**です。

```python
separator = Separator(
    output_dir="stems",
    output_format="flac",        # 可逆。後段の品質劣化を避ける
    sample_rate=44100,           # 既定。CD品質
    mdx_params={
        "segment_size": 256,     # GPUに載せるチャンクの大きさ。大=速い・VRAM増
        "overlap": 0.25,         # チャンク境界の重なり。大=継ぎ目低減・低速
        "batch_size": 1,         # まとめて処理する数。大=スループット増・VRAM増
        "hop_length": 1024,      # STFTのホップ幅。基本いじらない
        "enable_denoise": False, # 位相反転で残響ノイズを抑制。約2倍コスト
    },
)
separator.load_model(model_filename="UVR-MDX-NET-Inst_HQ_3.onnx")
```

> 💡 これらの**数値はライブラリ既定**です。`enable_denoise` や `overlap` の内部挙動の詳細は、公式の defaults を超える部分はコミュニティ知見（[UVR Discussion #831](https://github.com/Anjok07/ultimatevocalremovergui/discussions/831)）に基づきます。**まず既定で回し、不満な点だけ動かす**のが鉄則です。

---

## モデル選定ガイド：目的から逆引きする

**どのステムが欲しいか**でモデルを選ぶのが基本です。「伴奏が欲しいのにボーカル特化モデルを使う」と品質が落ちます。以下のファイル名は UVR 公式の `model_name_mapper.json` で確認したもの（✅）ですが、**配布リストは更新される**ため、本番投入前に必ず `audio-separator --list_models` で実在を確認してください。

| 目的 | おすすめモデル | 種別 | 状態 |
| --- | --- | --- | --- |
| **伴奏（インスト）を綺麗に取りたい** | `UVR-MDX-NET-Inst_HQ_3.onnx` | Inst | ✅ 公式mapper確認済 |
| 伴奏（旧世代・長い持続音に強い比較用） | `UVR-MDX-NET-Inst_HQ_2.onnx` | Inst | ✅ |
| **ボーカル（声）を綺麗に取りたい** | `Kim_Vocal_2.onnx` | Vocal | ✅ |
| ボーカル（さらにクリーンなアカペラ狙い） | `UVR-MDX-NET-Voc_FT.onnx` | Vocal | 🟡 `--list_models`で要確認 |
| **ハモリ/コーラスを除去しメイン声だけに** | `UVR_MDXNET_KARA_2.onnx` | Karaoke | ✅ |
| 汎用（標準） | `UVR_MDXNET_Main.onnx` | 汎用 | ✅ |

**選び方の原則（コミュニティ合意・[Discussion #444](https://github.com/Anjok07/ultimatevocalremovergui/discussions/444)）**：

- **「Inst」系は伴奏を綺麗に残す**ように、**「Vocal」系は声を綺麗に抜く**ように最適化されている。**欲しいステムに合わせて選ぶ**と、そのステムの品質が上がる。
- **ボーカル抽出**は `Kim_Vocal_2` が高速かつ高品質で定番。
- **伴奏抽出**は `UVR-MDX-NET-Inst_HQ_3`（HQ系）が定番。
- **ハモリ除去**（リードボーカルだけ残す）は `UVR_MDXNET_KARA_2`。
- 最高品質を狙うなら **ボーカル特化 + 伴奏特化のアンサンブル**（その分、時間は増える）。

> 📌 これらの**おすすめは公式仕様ではなくコミュニティ合意**です。SDR等のベンチマーク値を伴う断定は避け、**自分の音源で2〜3モデルを比較**して採用するのが確実です。

---

## パラメータ実践チューニング：用途別プリセット

公式が示すのは既定値だけです。ここに**実務での当たり値**を足します。下表はそのまま使えるプリセットの考え方です。

| 用途 | `segment_size` | `overlap` | `enable_denoise` | 狙い |
| --- | --- | --- | --- | --- |
| **VRAMが少ない（6〜8GB）** | 128〜256 | 0.25 | off | OOMを避けつつ実用品質 |
| **標準（12〜16GB）** | 256 | 0.25 | off | 既定。まずここから |
| **品質最優先（24GB+）** | 384〜512 | 0.5 | on | 継ぎ目とノイズを最小化 |
| **大量バッチで速度優先** | できる限り大 | 0.25 | off | スループット最大化 |
| **継ぎ目ノイズが気になる** | 据え置き | ↑（0.5） | off | 境界アーティファクトを緩和 |
| **残響・残留ノイズが気になる** | 据え置き | 据え置き | **on** | 位相反転で抑制（約2倍時間） |

ノブの意味を実務語で言い換えるとこうです。

- **`segment_size`（チャンクの大きさ）**：大きいほど **GPU との往復が減って速い**が、**VRAM を食う**。OOM が出たらまずここを下げる。VRAM に余裕があるなら**許す限り大きく**。
- **`overlap`（チャンクの重なり）**：上げると**チャンク境界の継ぎ目ノイズが減る**が、その分**遅くなる**。継ぎ目が気になる素材だけ上げる。
- **`enable_denoise`（ノイズ抑制）**：通常入力と**位相反転入力の両方で推論して平均**し、残響・残留ノイズを抑える。**計算量がおよそ2倍**になるので、最終仕上げのときだけ。
- **`batch_size`**：上げると**スループットが上がる**が VRAM 増。単発処理では 1 のままでよい。

> **コスト直結の原則**：品質を上げるノブ（`overlap`↑・`denoise` on）は**ほぼそのまま時間=お金**に跳ね返ります。「**全件は既定で回し、不満なカット/曲だけ高品質設定で再処理**」の二段構えが、本番の単価を最も効かせます。

---

## 応用：実務での使いどころ（公式を超えて役立てる）

公式は「分離する」までしか説明しません。ここからが**実際に案件で価値になる**使い方です。

### ① 動画ローカライズの前処理（声を抜いてから文字起こし）

吹き替えパイプラインでは、**BGM が混ざった音声をそのまま文字起こしすると誤認識が増えます**。先に**声だけを分離**してから [Whisper](/blog/openai-whisper-production-guide-selfhost-vs-api) に渡すと、認識精度が上がる。さらに**伴奏トラックは保持**しておき、吹き替え音声の下に再ミックスすれば、BGM ごと差し替わる違和感を防げます。

```python
# 動画ローカライズ前処理：声だけ抽出 → ASR、伴奏は保持して後で再ミックス
from audio_separator.separator import Separator

# 声だけ欲しいので Vocal特化モデル + 単一ステム出力
vocal_sep = Separator(output_dir="work", output_format="flac",
                      output_single_stem="Vocals")
vocal_sep.load_model(model_filename="Kim_Vocal_2.onnx")
vocals = vocal_sep.separate("episode.wav")        # 声だけのトラック

transcript = whisper_transcribe(vocals[0])         # 伴奏ノイズが消えてASRが安定
# 伴奏は別途 UVR-MDX-NET-Inst_HQ_3 で抜いておき、吹き替え音声と再ミックスする
```

### ② カラオケ音源・アカペラ・リミックス素材

曲から**伴奏だけ**（カラオケ）または**ボーカルだけ**（アカペラ／サンプリング素材）を取り出す、最も直球の用途。**Inst 系で伴奏**、**Vocal 系で声**を取り、必要なら **Demucs v4 で4ステム**に分けてリミックスやコピーに使います。

### ③ ポッドキャスト・会議音声のクリーニング

収録に紛れた **BGM やテレビ音声を除去**し、声を聞き取りやすくする前処理。文字起こし・要約の前段に挟むと、後段の品質が上がります。

### ④ 音声データセットの前処理（TTS / ASR 学習）

学習データから**音楽・環境音を除いたクリーンな音声**を量産する。データの質がモデルの質を決めるので、ここに音源分離を挟む価値は大きい。

---

## 本番で必ず詰まる5つの落とし穴と回復性設計

デモ（短い1ファイル・手元のGPU）では起きず、**本番（大量バッチ・コンテナ・長尺）で一斉に噴出**する問題です。私が実運用で踏んだ順に、原因と対策を示します。

### ① GPUが効かず CPU に落ちる（最頻出・最も気づきにくい）

`audio-separator[gpu]` を入れても、**CUDA/cuDNN と onnxruntime-gpu のバージョンが噛み合わないと、ONNX Runtime は黙って CPU 実行にフォールバック**します。エラーは出ず、ただ**数十倍遅くなる**だけ——本番で最も気づきにくく、最も高くつく罠です。

**対策**：起動時に **`CUDAExecutionProvider` が利用可能か検証**し、本番では**起動を止める（fail-fast）**。

```python
import onnxruntime as ort

def verify_gpu(require: bool = True) -> None:
    """CUDAが効いているか起動時に検証。本番でCPUに落ちると激遅。"""
    providers = ort.get_available_providers()
    if "CUDAExecutionProvider" not in providers:
        msg = f"CUDA未検出（利用可能: {providers}）。onnxruntime-gpuとCUDA/cuDNNの整合を確認。"
        if require:
            raise RuntimeError(msg)   # 気づけないまま遅い本番を避ける
        print(f"[WARN] {msg}")
```

### ② モデルの初回ダウンロードがコールドスタート毎に走る

モデルは初回利用時に `model_file_dir`（既定 `/tmp/audio-separator-models/`）へ自動ダウンロードされます。**コンテナ/サーバーレスでは `/tmp` が揮発**するため、**コールドスタートのたびに数百MBを再ダウンロード**——遅延とegress課金の温床です。

**対策**：`model_file_dir` を**永続ボリューム**に向け、可能なら**モデルをイメージに焼き込む**（ビルド時に1回だけDL）。

### ③ 長尺・高 batch_size での VRAM 枯渇（OOM）

`audio-separator` は `segment_size` 単位で内部的にチャンク処理するため、拡散モデルほど丸ごと OOM にはなりにくいものの、**`segment_size` や `batch_size` を上げすぎる**と `CUDA out of memory` で落ちます。

**対策**：OOM を**例外ではなく正常系**として扱い、**`segment_size` を下げて作り直して再試行**する。モデルの再ロードは高コストなので、**最初から VRAM に合わせた `segment_size` を選ぶ**のが本筋です。

```python
def separate_with_oom_fallback(audio: str, model: str, segment: int = 256):
    for seg in (segment, segment // 2, 64):     # 段階的に小さくして粘る
        try:
            sep = Separator(mdx_params={"segment_size": seg, "overlap": 0.25,
                                        "batch_size": 1, "hop_length": 1024,
                                        "enable_denoise": False})
            sep.load_model(model_filename=model)
            return sep.separate(audio)
        except RuntimeError as exc:              # onnxruntimeのOOMはRuntimeErrorで届く
            if "memory" not in str(exc).lower() or seg == 64:
                raise                            # OOM以外、または下限＝本物の異常
    raise RuntimeError("unreachable")
```

### ④ 入力フォーマットの不一致

入力は WAV/MP3/FLAC/M4A など一般的な形式に対応しますが、**壊れたヘッダや想定外コーデック**は処理失敗の原因になります。

**対策**：投入前に **ffmpeg で正規化**を1段挟む。サンプルレートとチャンネルを揃えるだけで安定性が上がります。

```bash
# 投入前の正規化：44.1kHz・ステレオ・wavに統一
ffmpeg -y -i input.m4a -ar 44100 -ac 2 normalized.wav
```

### ⑤ 品質を「耳」でしか確認していない

大量バッチで最も危険なのは、**品質ゲートが人手の試聴だけ**であること。破綻した分離がすり抜けます。

**対策**：分離後に **伴奏トラックに残ったボーカル残留**などを簡易指標で機械チェックし、しきい値を超えたものだけ人手レビュー or 再処理に回す。完璧な自動評価は難しくとも、**「明らかな失敗を弾く」ゲートだけでもレビュー工数を激減**させられます。

---

## 本番運用の設計原則を実装する（冪等性・回復性・可観測性・コスト）

落とし穴の対策を、**1つの本番向けマイクロサービス**に集約します。これが「動く」と「本番で落ちない」の差です。設計方針は4点——**①モデルは常駐させ再利用、②入力の中身でキー化した冪等キャッシュ、③GPU検証とGPU直列化、④失敗を握りつぶさず構造化ログに残す**。

```python
# separation_service.py — 本番向け音源分離マイクロサービス（UVR5 / MDX-Net）
from __future__ import annotations

import asyncio
import hashlib
import json
import logging
import os
import threading
from pathlib import Path

import onnxruntime as ort
from audio_separator.separator import Separator
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field

logger = logging.getLogger("separation")

MODEL_CACHE = Path(os.environ.get("MODEL_CACHE_DIR", "/models"))     # 永続ボリューム推奨
OUTPUT_DIR = Path(os.environ.get("OUTPUT_DIR", "/data/stems"))
DEFAULT_MODEL = os.environ.get("SEPARATION_MODEL", "UVR-MDX-NET-Inst_HQ_3.onnx")
REQUIRE_GPU = os.environ.get("REQUIRE_GPU", "true").lower() == "true"

# MDXの推論パラメータ。再現性のため固定し、冪等キーの一部にする
MDX_PARAMS = {"segment_size": 256, "overlap": 0.25, "batch_size": 1,
              "hop_length": 1024, "enable_denoise": False}

_separator: Separator | None = None
_gpu_sem = asyncio.Semaphore(int(os.environ.get("GPU_CONCURRENCY", "1")))  # GPUは原則直列
_manifest_lock = threading.Lock()
_MANIFEST = OUTPUT_DIR / "manifest.json"


def _verify_gpu() -> None:
    """CUDAが効いているか検証。本番でCPUに落ちると数十倍遅い（落とし穴①）。"""
    providers = ort.get_available_providers()
    if "CUDAExecutionProvider" not in providers:
        msg = f"CUDA未検出（利用可能: {providers}）。onnxruntime-gpuとCUDA/cuDNNを確認。"
        if REQUIRE_GPU:
            raise RuntimeError(msg)
        logger.warning(msg)


def get_separator() -> Separator:
    """プロセス内シングルトン。モデルは一度だけVRAMへ常駐させ、リクエスト間で再利用する。"""
    global _separator
    if _separator is None:
        _verify_gpu()
        OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
        sep = Separator(
            output_dir=str(OUTPUT_DIR),
            output_format="flac",            # 可逆。再ミックスで品質を落とさない
            model_file_dir=str(MODEL_CACHE),  # 初回DLを永続化（落とし穴②）
            sample_rate=44100,
            mdx_params=MDX_PARAMS,
        )
        sep.load_model(model_filename=DEFAULT_MODEL)
        _separator = sep
        logger.info("model loaded model=%s", DEFAULT_MODEL)
    return _separator


def _content_key(path: Path) -> str:
    """ファイル名ではなく"中身+モデル+パラメータ"でキー化。再送で再計算しない。"""
    h = hashlib.sha256()
    with path.open("rb") as f:                      # 大きい音源もメモリに載せず逐次ハッシュ
        for block in iter(lambda: f.read(1 << 20), b""):
            h.update(block)
    h.update(DEFAULT_MODEL.encode())
    h.update(json.dumps(MDX_PARAMS, sort_keys=True).encode())
    return h.hexdigest()[:16]


def _manifest() -> dict[str, list[str]]:
    return json.loads(_MANIFEST.read_text()) if _MANIFEST.exists() else {}


def _record(key: str, stems: list[str]) -> None:
    with _manifest_lock:        # 単一プロセス前提。複数レプリカならRedis等の共有ストアへ
        data = _manifest()
        data[key] = stems
        _MANIFEST.write_text(json.dumps(data))


class SeparateRequest(BaseModel):
    audio_path: str = Field(..., description="サーバーからアクセス可能な入力音声パス")


class SeparateResponse(BaseModel):
    job_key: str
    stems: list[str]
    cached: bool


app = FastAPI()


@app.on_event("startup")
def _startup() -> None:
    get_separator()             # 最初のリクエストを待たせない（ウォームアップ）


@app.post("/separate", response_model=SeparateResponse)
async def separate(req: SeparateRequest) -> SeparateResponse:
    src = Path(req.audio_path)
    if not src.is_file():                                   # 外部入力は境界で検証
        raise HTTPException(status_code=422, detail="input audio not found")

    key = _content_key(src)
    cached = _manifest().get(key)
    if cached and all(Path(p).exists() for p in cached):    # 冪等：再送/リトライで再計算しない
        logger.info("cache hit key=%s", key)
        return SeparateResponse(job_key=key, stems=cached, cached=True)

    try:
        async with _gpu_sem:                                # GPUは1ジョブずつ＝VRAM競合/OOM回避
            stems = await asyncio.to_thread(get_separator().separate, str(src))
    except Exception as exc:                                # 失敗を握りつぶさず構造化ログへ
        logger.exception("separation failed key=%s", key)
        raise HTTPException(status_code=500, detail="separation failed") from exc

    _record(key, stems)
    logger.info("separated key=%s stems=%d", key, len(stems))
    return SeparateResponse(job_key=key, stems=stems, cached=False)
```

このサービスを、TypeScript（Next.js等）から**型安全に**叩くクライアントはこうです。境界で必ず Zod 検証します。

```ts
// lib/separation-client.ts — Python分離サービスを叩く型安全クライアント
import { z } from "zod";

const SeparateResponse = z.object({
  job_key: z.string(),
  stems: z.array(z.string()),
  cached: z.boolean(),
});
export type SeparateResult = z.infer<typeof SeparateResponse>;

export async function separateAudio(audioPath: string): Promise<SeparateResult> {
  const res = await fetch(`${process.env.SEPARATION_SERVICE_URL}/separate`, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ audio_path: audioPath }),
  });
  if (!res.ok) throw new Error(`separation failed: ${res.status}`);
  return SeparateResponse.parse(await res.json()); // 外部応答は信用せず境界で検証
}
```

設計原則を運用の言葉でまとめ直すと、こうです。

- **冪等性**：`sha256(音源の中身 + モデル + パラメータ)` を**ジョブキー**にし、結果をマニフェストにキャッシュ。再送・連打・リトライで**二重 GPU 実行をしない**。ファイル名ではなく**中身**でキー化するのがポイント。
- **回復性**：OOM・CPUフォールバックを**例外ではなく設計事項**として扱う。GPU 未検出は起動時に弾き、OOM は `segment_size` を下げて再試行する。
- **可観測性**：ジョブごとに **キー・モデル・ステム数・キャッシュ有無**を構造化ログに残し、「どのジョブがどのモデルで何を出したか」を後から追える状態にする。音声内容（PII になり得る）はログに出さない。
- **コスト効率**：①モデル常駐でロードコストを償却、②冪等キャッシュで再生成ゼロ、③`single_stem` で不要なステム書き出しを省略、④品質ノブは全件ではなく不満分だけ上げる——の積み重ねで単価を刻む。
- **テスト容易性**：`_content_key` のような**純関数**は I/O なしで単体テストでき、分離本体（GPU依存）はサービス境界でモック差し替えできる。

---

## 他ツール・APIとの比較：結局どれを使う？

| 選択肢 | 形態 | 強み | 弱み | 向く場面 |
| --- | --- | --- | --- | --- |
| **UVR5（GUI）** | デスクトップアプリ | 無料・GUIで手軽・MDX/VR/Demucs/MDXC全部入り | 自動化不可・1ファイルずつ | 試用・少量・非エンジニア |
| **python-audio-separator** | Pythonライブラリ/CLI | **UVRと同じモデルをコードで・バッチ/サーバー組み込み** | 環境構築（CUDA整合）が要 | **本番自動化・大量処理** |
| **Demucs（単体）** | Pythonライブラリ | 4ステム分離・Meta製・活発 | ボーカル/伴奏2分離ではMDXが好まれる場面も | 4ステム・リミックス用途 |
| **商用クラウドAPI** | SaaS | 環境構築ゼロ・即利用 | 従量課金・データを外部に出す | PoC・データを外に出せる案件 |

実務の意思決定はおおむねこうです。

- **まず品質を見たい / 少量** → **UVR5 GUI**。
- **サーバーに組み込み、大量・継続処理する** → **python-audio-separator**（本稿の本番設計）。
- **ドラム/ベースまで分けたい** → **Demucs v4**。
- **環境構築の手間を一切かけたくない、データを外に出せる** → 商用 API。まずそこで需要を確かめ、量が増えたらセルフホストへ移すのが王道。

> 各モデル・ツールのライセンスや配布条件は更新されます。**商用利用は必ず一次情報で確認**してください。UVR5 のコードは本稿執筆時点で **MIT** です（処理する音源の著作権は別問題）。

---

## よくある質問（FAQ）

**Q. UVR5 と MDX-Net の関係は？**
A. **UVR5（Ultimate Vocal Remover GUI v5.6）が「アプリ」**、**MDX-Net はそのアプリが搭載する「AIアーキテクチャの一つ」**です。UVR5 は MDX-Net のほかに VR Architecture・Demucs・MDX23C/MDXC も搭載しています。ボーカル/伴奏の2分離では MDX-Net が定番です。

**Q. コードから使うにはどうすれば？**
A. UVR5 本体は GUI なのでスクリプトから直接は叩けません。**[python-audio-separator](https://github.com/nomadkaraoke/python-audio-separator)** を `pip install "audio-separator[gpu]"` で入れ、UVR と同じ MDX-Net モデル（`.onnx`）を `Separator` から読み込みます。本稿の[コード章](#使い方bコードで自動化python-audio-separator)が最短です。

**Q. どのモデルを使えばいい？**
A. **欲しいステムで選びます**。伴奏（カラオケ）なら `UVR-MDX-NET-Inst_HQ_3`、ボーカル（アカペラ）なら `Kim_Vocal_2`、ハモリ除去なら `UVR_MDXNET_KARA_2`。実在は `audio-separator --list_models` で確認し、自分の音源で2〜3個比較するのが確実です。

**Q. 必要な GPU / VRAM は？**
A. 公式READMEは **GTX 1060 6GB を最低要件、8GB 以上を推奨**としています。VRAM が少ないときは `segment_size` を下げます。**Apple Silicon（M1+）は MPS 対応**で、Demucs v4 と全 MDX-Net モデルが動きます。

**Q. GPU を入れたのに遅いです。**
A. ほぼ **CUDA/cuDNN と onnxruntime-gpu の不整合で CPU にフォールバック**しています。対応 CUDA は **11.8 / 12.2**。`onnxruntime.get_available_providers()` に `CUDAExecutionProvider` が含まれるかを起動時に検証してください（[落とし穴①](#①-gpuが効かず-cpu-に落ちる最頻出最も気づきにくい)）。

**Q. 出力フォーマットの既定は？**
A. **Python ライブラリの既定は `WAV`、CLI の既定は `FLAC`**と異なります。後段で再ミックスするなら可逆な `flac`/`wav` を明示してください（`mp3` は劣化します）。出力は既定で **Vocals / Instrumental の2ステム・44.1kHz** です。

**Q. リアルタイム処理に使える？**
A. 向きません。MDX-Net は1ファイルをまとめて処理する**バッチ志向**です。即時性が要件なら別アプローチを検討してください。

**Q. 市販曲を分離して公開してもいい？**
A. **技術的には可能でも、法的には別問題**です。市販曲には著作権があり、得たステムの**無断再配布・公開は権利侵害**になり得ます。自作曲・許諾済み素材・私的利用の範囲で使ってください。

---

## まとめ：UVR5/MDX-Net を「動く」から「本番で稼ぐ」へ

MDX-Net の本質は、**周波数領域と時間領域の二段構成を重み付き平均でブレンドし、単独モデルより安定して高品質な分離を出す**点にあります（[arXiv:2111.12203](https://arxiv.org/abs/2111.12203)）。だからこそ `segment_size`・`overlap`・`denoise` という**設計に根ざしたノブ**を理解して扱う必要があります。

実装の道筋はシンプルです。

1. **UVR5 GUI** で自分の音源の品質をまず確かめる（無料・ドラッグ&ドロップ）。
2. 手応えがあれば **python-audio-separator** でコード化し、**目的別にモデルを選び**、パラメータを詰める。
3. **本番は冪等性・回復性・可観測性・コスト**を設計に織り込む——モデル常駐、GPU検証、GPU直列化、中身ハッシュの冪等キャッシュ、OOM フォールバック、構造化ログ。

ここまでやって初めて、デモではなく「**顧客の音源で落ちない**」プロダクトになります。そして、ここが一番伝えたい点ですが——**この一連の設計判断こそが、外注で差がつくところ**です。「モデルを呼ぶだけ」のデモは誰でも作れますが、**CPUフォールバック・OOM・コールドスタート再DL・大量バッチで破綻しない基盤**は、踏んだ地雷の数がそのまま品質になります。

> 私は、本稿の落とし穴と回復性設計を、**音声分離を第1段に持つ AI動画ローカライズ基盤**で実際に本番運用しています。音源分離を含む音声・動画 AI パイプラインの構築・改善をお考えなら、[実績](/case-studies/ai-video-localization-lipsync)をご覧のうえ、お気軽にご相談ください。**一人 × 生成AI**で、PoCから本番運用まで一気通貫で、速く・安く・安全に作ります。

---

## 出典・公式リソース

- **UVR5 公式リポジトリ（GitHub）**：[Anjok07/ultimatevocalremovergui](https://github.com/Anjok07/ultimatevocalremovergui) — README（v5.6・MIT・動作要件・アーキテクチャのクレジット）
- **MDX-Net 論文（arXiv）**：[KUIELab-MDX-Net: A Two-Stream Neural Network for Music Demixing (2111.12203)](https://arxiv.org/abs/2111.12203) — 二段構成・ブレンド・MDX Challenge 2021 結果
- **系譜の論文（arXiv）**：[Investigating U-Nets with various Intermediate Blocks for Spectrogram-based Singing Voice Separation (1912.02591)](https://arxiv.org/abs/1912.02591) — TFC-TDF ブロック（ISMIR 2020）
- **コードで使うライブラリ**：[nomadkaraoke/python-audio-separator](https://github.com/nomadkaraoke/python-audio-separator) ／ [PyPI: audio-separator](https://pypi.org/project/audio-separator/) — インストール・`Separator` API・CLI・モデル一覧
- **モデル選定・パラメータの議論**：[Discussion #444（モデル推奨）](https://github.com/Anjok07/ultimatevocalremovergui/discussions/444) ／ [Discussion #831（segment_size 等）](https://github.com/Anjok07/ultimatevocalremovergui/discussions/831)

※ バージョン・モデル名・パラメータ既定値・ライセンスは更新されます。**実装前に必ず一次情報を確認**してください（特にモデルのファイル名は `audio-separator --list_models` で実在確認を推奨）。本稿の事実（UVR5 v5.6・MIT、MDX Challenge 2021 で Leaderboard A 2位/B 3位、二段構成、`audio-separator[gpu]`・Python 3.10+・CUDA 11.8/12.2、既定2ステム/44.1kHz、`output_format` のライブラリWAV/CLI FLAC など）は、本稿執筆時点の公式情報に基づきます。
