# Demucs v4 完全ガイド：Metaの音源分離モデル(HT Demucs)を公式準拠で本番運用する

> Metaの音源分離モデル Demucs v4（HT Demucs）を公式ドキュメント（GitHub・論文）に忠実に解説。波形×スペクトログラム×Transformerの仕組み、htdemucs系モデルの選び方、CLIとPython APIの実装、ボーカル分離・カラオケ・ASR前処理・動画ローカライズの実レシピ、長尺OOM・冪等性・回復性まで、本番運用の設計を具体コードで示します。

- 公開日: 2026-06-25
- 著者: 友田 陽大
- タグ: Demucs, 音源分離, 音声処理, Python, GPU, 生成AI, MLOps
- URL: https://tomodahinata.com/blog/demucs-v4-music-source-separation-production-guide

## 要点

- Demucs v4 = HT Demucs。波形を見るencoderとスペクトログラムを見るencoderを並列に走らせ、最深部をcross-domain Transformerで繋ぐハイブリッドbi-U-Net。MUSDB HQで9.0 dB SDR、微調整版htdemucs_ftで9.20 dBと、公開モデルではSOTA級
- 4ステム（drums / bass / other / vocals、44.1kHzステレオwav）に分離。htdemucs_6sはguitar/pianoを追加。`--two-stems=vocals`で『vocals / no_vocals』のカラオケ分離が1コマンド
- 導入は`pip install -U demucs`の1行。CPUでも動き（約1.5×実時間）、GPUは3GB VRAMから動作。MITライセンスで商用可。v4は枯れていて破壊的変更が来ない＝本番に向く
- 用途はボーカル除去/カラオケ、ASR前処理（Whisper精度向上）、動画ローカライズのBGM保持、耳コピ/音楽教育、リミックス。shifts / overlap / segment / mp3 presetで品質とコストを制御する
- 本番では長尺のメモリ枯渇・ffmpeg依存・CPUフォールバックの激遅・二重処理が必ず詰まる。segment縮小→CPU退避のOOM回復、sha256冪等キー、構造化ログで回復性とコスト効率を担保する

---

## この記事のゴール

Demucs（デムークス）は Meta（旧 Facebook AI Research）が公開した、**1本の楽曲・音声を「ボーカル / ドラム / ベース / その他」に分解する音源分離（Music Source Separation, MSS）モデル**です。その第4世代 **Demucs v4 = HT Demucs（Hybrid Transformer Demucs）** は、論文 [_Hybrid Transformers for Music Source Separation_（ICASSP 2023）](https://arxiv.org/abs/2211.08553) で提案され、公開モデルとして**SOTA級の分離品質**を達成しています。

本稿は、その**公式ドキュメント（[GitHub](https://github.com/adefossez/demucs) / [docs/api.md](https://github.com/adefossez/demucs/blob/main/docs/api.md) / [論文](https://arxiv.org/abs/2211.08553)）の内容に厳密に基づきつつ**、公式 README には書かれていない「**どの場面で・どう使い・どこで詰まるか**」までを、実際に動くコードで埋めるものです。読み終えたときに、次の3つができる状態を目指します。

1. Demucs v4 が**何をするモデルで、なぜ品質が高いのか**を、人に説明できる。
2. **CLI（試す）** と **Python API（組み込む）** を使い分け、**今日中に手を動かせる**。
3. デモではなく**本番**——長尺音声のメモリ枯渇・ffmpeg依存・二重処理——に耐える**回復性のある実装**を組める。

> **筆者について（信頼性の開示）**：私は、動画をアップロードするだけで「**音声分離 → 文字起こし → 翻訳 → 多言語吹き替え → 口元同期**」まで全自動化する**AI動画ローカライズ基盤を単独で設計・実装し、本番運用**しています。その**第1段（音声分離）**——元動画から「人の声」と「BGM・効果音」を切り離し、**BGMを残したまま別言語のナレーションを載せ替える**——を担うのが、まさに本稿の Demucs です。本稿の「落とし穴」と「回復性設計」は、デモ用の知識ではなく、その実運用で踏み抜いた地雷の記録です。パイプライン全体の設計は[別記事](/blog/production-ai-video-localization-lipsync-gpu-pipeline)に、案件の概要は本稿末尾の[実績リンク](/case-studies/ai-video-localization-lipsync)にまとめています。

---

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

| 観点 | 結論 |
| --- | --- |
| **何のモデルか** | 1本の音声 →「**ボーカル / ドラム / ベース / その他**」の4ステムに分解する音源分離モデル |
| **何がすごいか** | **波形とスペクトログラムの両方**を並列に処理し、Transformerで橋渡し。MUSDB HQで **9.0 dB SDR**（微調整版 `htdemucs_ft` で **9.20 dB**）と公開モデルでSOTA級 |
| **世代** | **v4 = HT Demucs**。論文は ICASSP 2023（Rouard, Massa, Défossez）。現在の**安定最新版** |
| **導入の軽さ** | `pip install -U demucs` の**1行**。**CPUでも動く**（約1.5×実時間）。GPUは **3GB VRAM** から |
| **ライセンス** | **MIT**。商用利用可（ただし分離した音源の原盤権・著作権は別問題） |
| **試すだけ** | **CLI 一発**：`demucs song.mp3`。出力は `separated/htdemucs/song/{vocals,drums,bass,other}.wav` |
| **作り込む** | **Python API**：`demucs.api.Separator` でテンソルを受け取り、自前パイプラインに組み込む |
| **品質の主要ノブ** | `shifts`（予測の平均化で +最大0.2dB・N倍遅い）／`overlap`（既定0.25）／`segment`（メモリと品質） |
| **向く用途** | カラオケ/ボーカル除去、**ASR前処理（Whisper精度向上）**、動画ローカライズのBGM保持、耳コピ・教育、リミックス |
| **向かない用途** | 厳密なゼロレイテンシのライブ配信（基本オフライン処理） |

「**まず自分の音源で品質を確かめたい**」なら、この後すぐの [使い方A：CLIワンライナー](#使い方aまず試すcliワンライナー) に飛んでください。`pip install` を含めても数分で結果が出ます。

---

## Demucs v4 は何をするモデルなのか

入力は**1本の音声ファイル**（楽曲・ナレーション・配信録音など）です。出力は**4本のステム**——**ボーカル（vocals）・ドラム（drums）・ベース（bass）・その他（other）**——で、いずれも元と同じ **44.1kHz のステレオ wav** として書き出されます。`htdemucs_6s` を選べば、ここに **ギター（guitar）・ピアノ（piano）** が加わり6ステムになります。

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

- **カラオケ・ボーカル除去**：`--two-stems=vocals` で「**vocals**」と「**no_vocals**（伴奏）」の2本に割る。歌ってみた用のオフボーカル音源、練習用カラオケが1コマンドで作れる。
- **ASR（文字起こし）の前処理**：BGMや雑音が乗った音声から**人の声だけを抜き出してから Whisper に渡す**と、音楽下・ノイズ下の文字起こし精度が上がる（後述の[レシピ](#ユースケース別レシピそのまま使えるコード)）。[Whisper の記事](/blog/openai-whisper-production-guide-selfhost-vs-api)と組み合わせる定番テクニック。
- **動画ローカライズ（吹き替え）**：元動画の音声を「ナレーション」と「BGM・効果音」に分け、**BGMを残したまま別言語のナレーションを載せ替える**。字幕やベタ差し替えより**没入感が段違い**で、海外展開のCVを上げる。私の基盤の第1段がこれです。
- **耳コピ・音楽教育**：ベースだけ・ドラムだけを取り出して**コピーや採譜、リズム練習**に使う。
- **リミックス・サンプリング・DJ**：ステムを取り出して再構成する。アカペラやインスト素材の抽出。

逆に、**厳密なリアルタイム配信**（数十ms以内の応答が要る用途）には向きません。Demucs は**1本ずつまとめて処理するオフライン処理**が基本で、CPUなら**おおよそ音源の長さの1.5倍**の時間がかかります（GPUはずっと速い）。ライブ用途は別系統の軽量モデルを検討してください。

---

## 仕組み：なぜ「波形 × スペクトログラム × Transformer」なのか（論文準拠でやさしく）

ここは公式論文の核心を、**正確さを保ったまま噛み砕く**章です。実装だけ知りたい人は[モデルの選び方](#モデルの選び方htdemucs-htdemucsft-htdemucs6s-mdx系)へ飛んで構いません。ただし「なぜ落とし穴がああいう形で出るのか」はここを理解していると腑に落ちます。

### 音源分離には「2つの見方」がある

音を機械に渡すとき、表現の仕方が大きく2つあります。

- **波形（temporal / waveform）**：時間軸そのもの。アタックの鋭さや位相など、**時間的なディテール**に強い。
- **スペクトログラム（spectral / STFT）**：周波数 × 時間の画像。**どの音域に何が鳴っているか**という、人が「楽器を聞き分ける」感覚に近い。

歴代の音源分離モデルは、このどちらか一方に寄っていました。**Demucs v3（Hybrid Demucs）が両方を1つのネットに統合**し、v4 はその上に **Transformer** を載せたものです。

### v4の構造：ハイブリッド bi-U-Net + cross-domain Transformer

論文（[arXiv:2211.08553](https://arxiv.org/abs/2211.08553)）の定義をそのまま噛み砕くと、HT Demucs はこういう形です。

- **2本の並列エンコーダ**を走らせる。1本は**波形**を、もう1本は**スペクトログラム**を処理する（temporal/spectral の **bi-U-Net**）。
- その**最深部（innermost layers）を、cross-domain Transformer Encoder に置き換える**。
- Transformer は、**同じ領域の中では self-attention**（波形なら波形どうし）、**領域をまたいでは cross-attention**（波形 ↔ スペクトログラム）で情報を統合する。

直感的に言えば、「**時間で聞く耳**」と「**周波数で聞く耳**」を同時に持ち、Transformer の注意機構で**両者の長距離の文脈を突き合わせて**、どの音がどのステムに属するかを判断している、というわけです。論文が立てた問いは「**音源分離に長距離の文脈は役立つのか、局所的な音響特徴で十分なのか**」で、答えは「**役立つ**」でした。

### 品質：MUSDB HQ で 9.0〜9.20 dB SDR

分離品質は **SDR（Signal-to-Distortion Ratio、信号対歪み比。高いほど良い）** で測ります。公式の報告は次の通りです。

| モデル | SDR（MUSDB HQ） | 備考 |
| --- | --- | --- |
| Hybrid Demucs（v3） | 約 **7.7 dB** | 追加データなし |
| **HT Demucs（v4, htdemucs）** | **9.0 dB** | MusDB + 800曲で学習 |
| **HT Demucs f.t.（v4, htdemucs_ft）** | **9.20 dB** | sparse attention + ソース別微調整。**公開モデルでSOTA級** |

論文は、800曲の追加データで学習したとき HT Demucs が Hybrid Demucs を **0.45 dB** 上回り、さらに **sparse attention（疎な注意機構で受容野を拡大）** と**ソースごとの微調整**を加えて **9.20 dB** に到達したと報告しています。

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

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

- Transformer モデルは**1区間あたりのメモリ消費が大きく**、`htdemucs` は**1セグメント最大7.8秒**という制約がある。だから長尺は**自動でセグメント分割**され、メモリ圧は `segment`・`jobs`・`shifts` で決まる。
- 波形とスペクトログラムの**両方**を持つぶん計算が重く、**CPUだと遅い**（GPU推奨だが3GBから動く）。
- 品質ノブ（`shifts`）は**予測を複数回平均する**ので、品質と時間がきれいにトレードオフする。

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

---

## モデルの選び方（htdemucs / htdemucs_ft / htdemucs_6s / mdx系）

Demucs は複数の事前学習モデルを同梱しており、`-n`（CLI）または `model=`（API）で選びます。実務での選び方はシンプルです。

| モデル名 | ステム | 速度 | 品質 | こう選ぶ |
| --- | --- | --- | --- | --- |
| **`htdemucs`**（既定） | 4（vocals/drums/bass/other） | 標準 | 高 | **まず迷わずこれ**。v4の標準。多くの用途で十分 |
| **`htdemucs_ft`** | 4 | **約4倍遅い** | 最高 | 品質最優先。各ソースに特化して微調整したモデルを束ねた構成（公式：_"4 times more time but might be a bit better"_） |
| **`htdemucs_6s`** | 6（+guitar/piano） | 標準 | 高（pianoは弱い） | ギター・ピアノも分けたいとき。**ただしピアノ品質は公式も「まだ良くない」と明言** |
| **`hdemucs_mmi`** | 4 | 速め | 中〜高 | v3（Hybrid Demucs）の再学習版。Transformer不要で軽くしたいとき |
| **`mdx` / `mdx_extra`** | 4 | 速め | 中〜高 | 旧 MDX チャレンジ向け。`mdx_extra` は追加データ込み |
| **`mdx_q` / `mdx_extra_q`** | 4 | 速い | 中 | **量子化版**。メモリ・容量を抑えたいとき |

**判断のショートカット：**

- **とりあえず最良の標準**を使いたい → **`htdemucs`**（既定）。指定不要。
- **最後の数%の品質**が欲しい（納品物・主役カット）→ **`htdemucs_ft`**。4倍の時間と引き換え。
- **ギター/ピアノも分けたい** → **`htdemucs_6s`**。ただしピアノは過度に期待しない。
- **メモリ/容量が厳しい**（エッジ・大量バッチ）→ **`mdx_q` / `mdx_extra_q`** の量子化版。

> 💡 `htdemucs_ft` が「4倍遅い」のは、内部で**ソース別に微調整された複数モデルを順に走らせる**から。`demucs.api.list_models()` の戻り値が `{"single": [...], "bag": [...]}` に分かれているのはこのためで、`htdemucs_ft` は **bag（モデルの束）** 側に属します。品質の伸びは「わずか」なので、**ドラフトは `htdemucs`、納品だけ `htdemucs_ft`** の二段構えがコスト効率の良い使い方です。

---

## 使い方A：まず試す（CLIワンライナー）

Demucs の最大の長所は**導入が軽い**ことです。LatentSync のような重い拡散モデルと違い、**GPUがなくても**動きます（遅いだけ）。まずは自分の音源で品質を体感しましょう。

### 1. インストール

```bash
# Python 3.8+ が前提。仮想環境を切ってから入れるのが安全
python3 -m pip install -U demucs

# mp3 など wav 以外を扱うなら ffmpeg も入れる（Windowsは特に必須）
#   macOS:  brew install ffmpeg
#   Ubuntu: sudo apt install ffmpeg
```

### 2. 分離する（1コマンド）

```bash
# 既定モデル(htdemucs)で4ステムに分離
demucs song.mp3

# 出力はこの構成で書き出される:
# separated/htdemucs/song/
#   ├── drums.wav
#   ├── bass.wav
#   ├── other.wav
#   └── vocals.wav
```

### 3. よく使うパターン

```bash
# ① カラオケ/ボーカル除去: vocals と no_vocals の2本だけ作る
demucs --two-stems=vocals song.mp3
#   → separated/htdemucs/song/vocals.wav, no_vocals.wav

# ② GPUを明示（既定は自動。CPUを強制したいなら -d cpu）
demucs -d cuda song.mp3

# ③ 最高品質モデル + mp3で書き出し(320kbps)
demucs -n htdemucs_ft --mp3 --mp3-bitrate 320 song.mp3

# ④ 出力先を指定 + 複数ファイルを一括
demucs -o ./out track1.wav track2.flac track3.mp3

# ⑤ 6ステム(ギター/ピアノ込み)
demucs -n htdemucs_6s song.mp3
```

`demucs --help` で全フラグが出ます。主要なものは次の通り。

| フラグ | 役割 | 既定 |
| --- | --- | --- |
| `-n MODEL` | モデル選択 | `htdemucs` |
| `--two-stems=vocals` | 2ステム（指定ソース / それ以外）に絞る | off（4ステム） |
| `-d {cpu,cuda}` | 計算デバイス | 自動 |
| `--mp3` / `--flac` | 出力形式（既定は16bit wav） | wav |
| `--mp3-bitrate` | mp3ビットレート(kbps) | `320` |
| `--mp3-preset` | mp3品質（2=最高〜7=最速） | — |
| `--int24` / `--float32` | wavを24bit整数 / 32bit浮動小数で保存 | 16bit |
| `--shifts N` | ランダム時間シフトでN回平均（品質↑・N倍遅い） | `1` |
| `--overlap` | セグメント重なり率 | `0.25` |
| `--segment SEC` | 1セグメント長（htdemucsは**最大7.8**） | モデル既定 |
| `-j JOBS` | 並列ジョブ数（速いがメモリ↑） | `1` |
| `--clip-mode {rescale,clamp}` | クリッピング処理 | `rescale` |
| `-o DIR` | 出力ディレクトリ | `separated` |

---

## 使い方B：Python API で組み込む

自前のサーバーやバッチに組み込むなら、**CLIを叩くより Python API（`demucs.api`）**が筋が良い。テンソルを直接受け取れるので、後段（ミックス、エンコード、アップロード）にそのまま繋げられます。

### 最小構成

公式 [`docs/api.md`](https://github.com/adefossez/demucs/blob/main/docs/api.md) のAPIをそのまま使います。

```python
import demucs.api

# Separatorを1度だけ生成してモデルをロード（使い回す）
separator = demucs.api.Separator(model="htdemucs")

# 分離: 戻り値は (元の波形, {ステム名: テンソル}) のタプル
origin, stems = separator.separate_audio_file("song.mp3")
# stems = {"drums": Tensor, "bass": Tensor, "other": Tensor, "vocals": Tensor}

# 各ステムを書き出す
for name, source in stems.items():
    demucs.api.save_audio(source, f"{name}.wav", samplerate=separator.samplerate)
```

`Separator` のコンストラクタ引数（公式準拠）：

| 引数 | 意味 |
| --- | --- |
| `model="htdemucs"` | モデル名 |
| `repo=None` | ローカルのモデル置き場（オフライン運用時） |
| `device=None` | `"cuda"` / `"cpu"` / `torch.device`。`None`は自動 |
| `shifts=None` | >0でランダムシフト平均（SDR +最大0.2、その分遅い） |
| `overlap=None` | セグメント重なり率（既定0.25相当） |
| `split=None` | 長尺をチャンク分割するか |
| `segment=None` | 1セグメント長（秒）。htdemucsは最大7.8 |
| `jobs=None` | 並列ジョブ数 |
| `progress=False` | 進捗バー表示 |
| `callback=None` | チャンクの開始/終了で呼ばれる関数（進捗・観測に使う） |

### カラオケ（vocals / no_vocals）をAPIで作る

CLIの `--two-stems` 相当を API でやるなら、**非ボーカルを合算**します。

```python
import demucs.api

separator = demucs.api.Separator(model="htdemucs")
origin, stems = separator.separate_audio_file("song.mp3")

# ボーカル以外を足し合わせれば「伴奏(no_vocals)」になる
no_vocals = sum(src for name, src in stems.items() if name != "vocals")

demucs.api.save_audio(stems["vocals"], "vocals.wav", samplerate=separator.samplerate)
demucs.api.save_audio(no_vocals, "no_vocals.wav", samplerate=separator.samplerate)
```

### 進捗を観測する（callback）

長尺ではユーザーに進捗を見せたい。`callback` でチャンクの進行を拾えます。

```python
def on_progress(data: dict) -> None:
    # data には現在のセグメント番号・総数・モデル状態などが入る
    # 本番では構造化ログ/メトリクスに流す（標準出力にPIIを出さない）
    if data.get("state") == "end":
        print(f"segment {data.get('segment_offset')} done")

separator = demucs.api.Separator(model="htdemucs", callback=on_progress, progress=True)
```

---

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

公式はノブの存在と既定値を示します。ここに**実務での当たり値**を足します。下表はそのまま使えるプリセットです。

| 用途 | モデル | `shifts` | `overlap` | `segment` | 出力 | 狙い |
| --- | --- | --- | --- | --- | --- | --- |
| **ドラフト確認**（社内レビュー） | `htdemucs` | 1 | 0.25 | 既定 | mp3 320 | 速く・安く形を見る |
| **標準の納品**（配信/広報） | `htdemucs` | 2 | 0.25 | 既定 | wav | 品質と速度の最良点 |
| **最高品質**（主役・マスタリング） | `htdemucs_ft` | 5 | 0.5 | 既定 | float32 | 細部最優先（時間は数倍） |
| **省メモリ**（小VRAM/CPU） | `mdx_q` | 1 | 0.1 | 小さめ | mp3 | OOM回避・完走優先 |
| **ASR前処理**（Whisperへ） | `htdemucs` | 1 | 0.25 | 既定 | wav（vocalsのみ） | 速度優先・声だけ要る |

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

- **`shifts`（時間シフト平均）**：入力を少しずつずらして**N回予測し平均**する。品質は上がるが（公式：**最大 +0.2 dB SDR**）、**時間はN倍**。納品物だけ `2〜5`、ドラフトは `1` が定石。
- **`overlap`（セグメント重なり）**：既定 **0.25**。上げると継ぎ目のアーティファクトが減るが**遅くなる**。継ぎ目が気になる素材だけ `0.5` に。
- **`segment`（1区間の長さ）**：**メモリと品質の主ノブ**。`htdemucs` は**最大7.8秒**。**OOMが出たら下げる**。下げすぎると継ぎ目が増えるので、まずは既定→ダメなら段階的に縮める。
- **`-j / jobs`（並列数）**：複数曲を同時処理して速くできるが、**メモリは並列数ぶん増える**。VRAM/RAMと相談。
- **`--mp3-preset`**：`2`（最高品質・低速）〜`7`（最速・低品質）。納品は2〜3、確認用は速い方。

> **コスト直結の原則**：品質は `shifts` に**ほぼ比例して時間=お金**がかかります。全曲を高 `shifts` で回すのは無駄。「**ドラフトは `shifts=1` で確認 → 採用分だけ `htdemucs_ft` + `shifts=2〜5`**」の二段構えが、本番の単価を最も効かせます。

---

## ユースケース別レシピ（そのまま使えるコード）

### A. ASR（Whisper）の前処理：BGM下の文字起こし精度を上げる

音楽や雑音が乗った音声は、そのまま渡すと ASR が誤認識します。**Demucsで人の声だけ抜いてから Whisper に渡す**と精度が上がります。

```bash
# 1) 声だけ抽出（伴奏・雑音を落とす）
demucs --two-stems=vocals -o sep podcast_with_bgm.wav

# 2) クリーンな声をWhisperへ（自前運用 or API は別記事参照）
whisper sep/htdemucs/podcast_with_bgm/vocals.wav --language ja
```

詳しい Whisper 側の本番設計（自前運用 vs API、コスト、タイムスタンプ）は[Whisper の記事](/blog/openai-whisper-production-guide-selfhost-vs-api)に。**「Demucsで声を抜く → Whisperで起こす」は、動画ローカライズや議事録の品質を底上げする定番の前処理**です。

### B. 動画ローカライズ：BGMを残して別言語に吹き替える

字幕ではなく**音声そのものを差し替える**とき、BGM・効果音まで消えると安っぽくなります。Demucsで**ナレーションだけ剥がし、BGM(no_vocals)を残す**のが肝です。

```bash
# 1) 動画から音声を抽出（44.1kHz）
ffmpeg -i source.mp4 -vn -ar 44100 audio.wav

# 2) ナレーション(vocals) と BGM・効果音(no_vocals) に分離
demucs --two-stems=vocals -o sep audio.wav

# 3) sep/htdemucs/audio/no_vocals.wav が「BGM・効果音だけ」のトラック。
#    これに新言語のナレーションをミックスすれば、世界観を保ったまま吹き替えできる。
ffmpeg -i sep/htdemucs/audio/no_vocals.wav -i narration_en.wav \
  -filter_complex amix=inputs=2:duration=longest dubbed_audio.wav
```

これが私のAI動画ローカライズ基盤の**第1段**そのものです。ここで BGM をきれいに残せるかが、最終的な吹き替え動画の「**本物っぽさ**」を決めます。

### C. カラオケ / 歌ってみた用オフボーカル

```bash
demucs --two-stems=vocals --mp3 --mp3-bitrate 320 song.mp3
# → no_vocals.mp3 がそのままカラオケ音源
```

### D. 耳コピ・採譜：ベース/ドラムだけ取り出す

```bash
demucs song.mp3
# separated/htdemucs/song/bass.wav だけをDAWに読み込めば、ベースラインが追いやすい
```

---

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

デモ（4分のwav・1本）では起きず、**現実（数十分・大量・多様なフォーマット）で一斉に噴出**する問題です。仕組み章で見たとおり、これらは**Demucsの設計の必然**として現れます。

### ① 長尺・並列でのメモリ枯渇（OOM）

Transformer は1区間のメモリ消費が大きい。長尺音声、`shifts` 増、`-j` 並列を重ねると、GPUでもCPU(RAM)でも **out of memory** で落ちます。

**対策**：Demucsは長尺を**自動でセグメント分割**するので、効くノブは **`segment` を下げる・`jobs` を減らす・`shifts` を戻す**こと。低VRAM環境では環境変数 **`PYTORCH_NO_CUDA_MEMORY_CACHING=1`** も効きます。そして**OOMを例外ではなく正常系**として、**段階的に縮退**させます。

```python
import torch
import demucs.api

def separate_resilient(path: str, model: str = "htdemucs"):
    """OOMを正常系として扱い、segment縮小→CPU退避の順に縮退する。"""
    device = "cuda" if torch.cuda.is_available() else "cpu"
    segment: float | None = None  # まずモデル既定で挑む

    for attempt in range(4):
        try:
            sep = demucs.api.Separator(model=model, device=device, segment=segment)
            return sep.separate_audio_file(path)
        except torch.cuda.OutOfMemoryError:
            torch.cuda.empty_cache()
            if segment is None:
                segment = 7.0          # htdemucsの上限(7.8)未満から開始
            elif segment > 4:
                segment = segment / 2   # まずsegmentを縮める
            elif device == "cuda":
                device, segment = "cpu", None  # 最後の砦: CPUへ退避（遅いが完走する）
            else:
                raise                   # CPUでも割れない＝本物の異常。握りつぶさない
    raise RuntimeError("separation failed after retries")
```

### ② CPUフォールバックの「動くが激遅」

GPUが無い／ドライバ不整合でCPUに落ちると、**音源の約1.5倍の時間**がかかります。4分の曲で約6分、1時間の音声なら約1.5時間。「動いてはいるが終わらない」状態になりがちです。

**対策**：CPU実行は**必ずタイムアウトと進捗ログ**を付ける。バッチはGPUに寄せ、CPUは「フォールバックの最後の砦」と割り切る。`torch.cuda.is_available()` を起動時に検査し、**意図せぬCPU実行を警告として可視化**します。

```python
import torch, logging

logger = logging.getLogger("demucs")
if not torch.cuda.is_available():
    logger.warning("CUDA unavailable: running on CPU (~1.5x realtime). Batch jobs will be slow.")
```

### ③ ffmpeg依存・フォーマット非互換

`torchaudio` が読めるのは wav / mp3 / flac / ogg 等。**Windowsや一部環境ではmp3の読み書きにffmpegが必須**で、無いと「wavなら動くがmp3で落ちる」という分かりにくい失敗をします。

**対策**：投入前に **ffmpeg で wav 44.1kHz に正規化**する1段を挟むと、再現性と互換性が跳ね上がります。

```bash
# 投入前の正規化: どんな入力でも 44.1kHz ステレオ wav に揃える
ffmpeg -y -i input.any -ar 44100 -ac 2 normalized.wav
```

### ④ 二重処理（同じ音源を何度も分離してGPU代を溶かす）

ユーザーの再送・リトライ・連打で、**同一音源を何度も分離**するとGPU時間がそのまま無駄になります。分離は重い処理なので、ここの取りこぼしはコストに直結します。

**対策**：**入力の中身（ファイルのsha256）+ モデル + パラメータ**から決定的なジョブキーを作り、**結果をキャッシュ**。同じ入力なら計算せず既存結果を返す（冪等性）。

```python
import hashlib, json
from dataclasses import dataclass, asdict
from pathlib import Path

@dataclass(frozen=True, slots=True)
class SepParams:
    model: str = "htdemucs"
    two_stems: str | None = None
    shifts: int = 1
    overlap: float = 0.25

def file_sha256(path: Path) -> str:
    h = hashlib.sha256()
    with path.open("rb") as f:
        for chunk in iter(lambda: f.read(1 << 20), b""):  # 1MBずつ（大ファイルでもメモリ一定）
            h.update(chunk)
    return h.hexdigest()

def job_key(audio: Path, params: SepParams) -> str:
    payload = json.dumps({"audio": file_sha256(audio), **asdict(params)}, sort_keys=True)
    return hashlib.sha256(payload.encode()).hexdigest()

def separate_idempotent(audio: Path, out_root: Path, params: SepParams) -> Path:
    dest = out_root / job_key(audio, params)
    if (dest / "vocals.wav").exists():   # 冪等性: 同じ入力×同じ設定は再計算しない
        return dest                       # 連打・リトライでもGPUを再消費しない
    dest.mkdir(parents=True, exist_ok=True)
    # ... ここで separate_resilient を呼び、dest 配下に保存 ...
    return dest
```

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

大量バッチでは、**ボーカルの消し残り**や**ステムへの音漏れ**が必ずすり抜けます。

**対策**：分離後に **ステムのRMS/相関などを機械的にチェック**し、しきい値を外れたものだけ人手レビューに回す。たとえば「no_vocals に人声成分が残りすぎていないか」を簡易指標で見張るだけでも、レビュー工数は激減します。完璧な指標は要りません——**外れ値を機械で拾う**のが目的です。

---

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

落とし穴の対策を、運用品質の言葉でまとめ直します。これが「動く」と「本番で落ちない」の差です。

- **冪等性**：`sha256(音源の中身 + model + params)` を**ジョブキー**にし、結果をキャッシュ。再送・連打・リトライで二重分離しない。重い処理ほど効く。
- **回復性**：OOM・CPUフォールバック・フォーマット不整合を**例外ではなく正常系**として扱う。「`segment`を縮める→CPUへ退避」「投入前にffmpeg正規化」で、1本の失敗が全体を巻き込まないようにする。
- **可観測性**：曲ごとに **どのモデルで・shifts/overlap いくつ・何秒かかったか・デバイスはGPUかCPUか**を構造化ログに残す。「なぜこの曲だけ遅い/品質が悪い」を後から追える状態にする。音声内容そのもの（PII）はログに出さない。
- **コスト効率**：①冪等キャッシュで再分離ゼロ ②ドラフトは`htdemucs`+`shifts=1`、納品だけ`htdemucs_ft` ③GPUバッチで埋めて回す、の三段で単価を刻む。Demucsは**軽量なのでセルフホストの単価が出しやすい**のが強み。
- **API vs セルフホスト**：Demucsは**MIT・3GB VRAMから動く**ので、**セルフホストが基本線**。Replicate 等のホスティング（例：[`cjwbw/demucs`](https://replicate.com/cjwbw/demucs)）は「環境を作らず数本だけ試す」のに便利だが、**定常的な大量処理は自前GPUバッチが断然安い**。まずローカルCLIで品質を確かめ、量が増えたらGPUワーカー化する流れが王道です（料金・仕様は変動するため利用時に一次情報を確認）。

---

## 他の音源分離ツールとの比較

「結局どれを使う？」に答えるための整理です。**用途で選ぶ**のが正解で、万能の1つはありません。

| ツール | 方式 | 品質（目安） | 速度・軽さ | ライセンス | 向く場面 |
| --- | --- | --- | --- | --- | --- |
| **Demucs v4（HT Demucs）** | ハイブリッド（波形+スペクトル）+ Transformer | **公開モデルでSOTA級**（9.0〜9.20 dB） | GPUで高速・**CPU可**・3GB VRAM〜 | **MIT** | 品質最優先・本番の分離全般 |
| **Spleeter（Deezer）** | CNN（スペクトログラム） | 一段下 | **非常に高速** | MIT | 速度優先・大量ドラフト |
| **Open-Unmix（UMX）** | BiLSTM | 控えめ（参照実装） | 軽量 | MIT | 研究・ベースライン比較 |
| **MDX-Net系**（UVR等に同梱） | スペクトログラム | 高い（アンサンブルで強い） | モデル次第 | 各種 | **Demucsと併用**してアンサンブル |

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

- **品質が最重要で、MITで商用も通したい** → **Demucs v4**。第一候補。
- **とにかく速く大量に下処理したい** → Spleeter でドラフト → 採用分を Demucs で本処理、の二段構え。
- **最後の数%を詰めたい** → Demucs（`htdemucs_ft`）と MDX系を**アンサンブル**（UVRなどのGUIが実装）。

> 各ツールのライセンス・品質は更新されます。**商用利用は必ず一次情報で確認**してください。Demucs は本稿執筆時点で **MIT**（公式リポジトリ）です。

---

## よくある質問（FAQ）

**Q. 商用利用できますか？**
A. Demucs のコードとモデルは **MIT ライセンス**で、商用利用に対応します。ただし**分離した音源そのものの著作権・原盤権は別問題**です。市販曲を分離して二次配布する行為などは権利者の許諾が要ります。権利処理は利用者の責任で行ってください。

**Q. GPUは必須ですか？**
A. 不要です。**CPUでも動きます**（約1.5×実時間と遅い）。GPUなら **3GB VRAM** から動作し、既定設定の快適動作には **7GB** が目安です。バッチ大量処理はGPU推奨。

**Q. リアルタイムでできますか？**
A. 基本は**オフライン処理**です。1本ずつまとめて分離する設計で、CPUは約1.5×実時間。厳密な低遅延ライブには向きません。

**Q. どのモデルを選べばいい？**
A. まず既定の **`htdemucs`** で十分です。最高品質が要るカットだけ **`htdemucs_ft`**（4倍遅い）、ギター/ピアノも分けたいなら **`htdemucs_6s`**（ピアノは過度に期待しない）。

**Q. 5分超の曲でメモリ不足になります。**
A. Demucsは長尺を**自動でセグメント分割**します。OOM時は **`segment`を下げる・`jobs`を減らす・`shifts`を戻す**、低VRAMなら環境変数 **`PYTORCH_NO_CUDA_MEMORY_CACHING=1`**。それでも厳しければ **CPUへ退避**（[回復性のコード](#本番で必ず詰まる5つの落とし穴と回復性設計)参照）。

**Q. mp3で出力するには？**
A. `--mp3 --mp3-bitrate 320`。既定は**16bit wav**。より高ビット深度なら `--int24` / `--float32`、flacなら `--flac`。

**Q. 歌だけでなく、ナレーション/会議音声でも使えますか？**
A. 使えます。`vocals` は「**人の声**」を捉えるので、歌でなくても**ナレーション・話し声とBGM/雑音の分離**に有効です。動画ローカライズやASR前処理で実際に役立ちます。

**Q. Whisper の前処理に使えますか？**
A. 有効です。`--two-stems=vocals` で**声だけにしてから ASR に渡す**と、BGM・雑音下の文字起こし精度が上がります。[Whisper の記事](/blog/openai-whisper-production-guide-selfhost-vs-api)と併読を。

**Q. 自前運用とAPI、どちらが安い？**
A. Demucsは軽量・MITなので**セルフホストが基本**。数本試すだけならホスティング（Replicate等）が手軽ですが、**定常的な大量処理はGPUバッチの自前運用が単価で有利**になりやすい。まずローカルで品質を確かめ、量が増えたらワーカー化、が王道です。

---

## まとめ：Demucs を「動く」から「本番で稼ぐ」へ

Demucs v4（HT Demucs）の本質は、**「時間で聞く波形」と「周波数で聞くスペクトログラム」を同時に持ち、Transformer で長距離の文脈を突き合わせた点**にあります。だからこそ公開モデルでSOTA級の品質が出て、だからこそ `segment`・`shifts`・`overlap` という**設計に根ざしたノブ**を理解して扱う必要があります。

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

1. **CLI（`pip install -U demucs` → `demucs song.mp3`）** で自分の音源の品質をまず確かめる（GPU不要・CPUでも動く）。
2. 手応えがあれば **Python API（`demucs.api.Separator`）** で自前パイプラインに組み込み、用途別プリセットで詰める。
3. **本番は冪等性・回復性・可観測性・コスト**を設計に織り込む——sha256冪等キー、OOMの段階縮退、ffmpeg正規化、構造化ログ。

ここまでやって初めて、デモではなく「**顧客の素材で落ちない**」プロダクトになります。そして、ここが一番伝えたい点ですが——**この一連の設計判断こそが、外注で差がつくところ**です。「`demucs` を叩くだけ」のデモは誰でも作れますが、**長尺・多様フォーマット・大量バッチの現実で破綻しない基盤**は、踏んだ地雷の数がそのまま品質になります。

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

---

## 出典・公式リソース

- **公式リポジトリ（GitHub）**：[adefossez/demucs](https://github.com/adefossez/demucs) — README・CLIフラグ・モデル一覧・ハードウェア要件
- **Python APIドキュメント**：[docs/api.md](https://github.com/adefossez/demucs/blob/main/docs/api.md) — `demucs.api.Separator` / `save_audio` / `list_models`
- **論文（arXiv）**：[Hybrid Transformers for Music Source Separation (2211.08553)](https://arxiv.org/abs/2211.08553) — Rouard, Massa, Défossez（ICASSP 2023）。アーキテクチャ・SDR・sparse attention
- **ホスティングAPI（Replicate）**：[cjwbw/demucs](https://replicate.com/cjwbw/demucs) — 環境構築なしで試す場合の入力スキーマ・料金

※ バージョン・パラメータ・料金・ライセンスは更新されます。**実装前に必ず一次情報を確認**してください。本稿の数値（SDR 9.0 / 9.20 dB、segment最大7.8秒、3GB/7GB VRAM、shifts +最大0.2dB、CPU約1.5×実時間など）は本稿執筆時点の公式情報に基づきます。
