この記事のゴール
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) で提案され、公開モデルとしてSOTA級の分離品質を達成しています。
本稿は、その公式ドキュメント(GitHub / docs/api.md / 論文)の内容に厳密に基づきつつ、公式 README には書かれていない「どの場面で・どう使い・どこで詰まるか」までを、実際に動くコードで埋めるものです。読み終えたときに、次の3つができる状態を目指します。
- Demucs v4 が何をするモデルで、なぜ品質が高いのかを、人に説明できる。
- CLI(試す) と Python API(組み込む) を使い分け、今日中に手を動かせる。
- デモではなく本番——長尺音声のメモリ枯渇・ffmpeg依存・二重処理——に耐える回復性のある実装を組める。
筆者について(信頼性の開示):私は、動画をアップロードするだけで「音声分離 → 文字起こし → 翻訳 → 多言語吹き替え → 口元同期」まで全自動化するAI動画ローカライズ基盤を単独で設計・実装し、本番運用しています。その第1段(音声分離)——元動画から「人の声」と「BGM・効果音」を切り離し、BGMを残したまま別言語のナレーションを載せ替える——を担うのが、まさに本稿の Demucs です。本稿の「落とし穴」と「回復性設計」は、デモ用の知識ではなく、その実運用で踏み抜いた地雷の記録です。パイプライン全体の設計は別記事に、案件の概要は本稿末尾の実績リンクにまとめています。
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ワンライナー に飛んでください。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 の記事と組み合わせる定番テクニック。
- 動画ローカライズ(吹き替え):元動画の音声を「ナレーション」と「BGM・効果音」に分け、BGMを残したまま別言語のナレーションを載せ替える。字幕やベタ差し替えより没入感が段違いで、海外展開のCVを上げる。私の基盤の第1段がこれです。
- 耳コピ・音楽教育:ベースだけ・ドラムだけを取り出してコピーや採譜、リズム練習に使う。
- リミックス・サンプリング・DJ:ステムを取り出して再構成する。アカペラやインスト素材の抽出。
逆に、厳密なリアルタイム配信(数十ms以内の応答が要る用途)には向きません。Demucs は1本ずつまとめて処理するオフライン処理が基本で、CPUならおおよそ音源の長さの1.5倍の時間がかかります(GPUはずっと速い)。ライブ用途は別系統の軽量モデルを検討してください。
仕組み:なぜ「波形 × スペクトログラム × Transformer」なのか(論文準拠でやさしく)
ここは公式論文の核心を、正確さを保ったまま噛み砕く章です。実装だけ知りたい人はモデルの選び方へ飛んで構いません。ただし「なぜ落とし穴がああいう形で出るのか」はここを理解していると腑に落ちます。
音源分離には「2つの見方」がある
音を機械に渡すとき、表現の仕方が大きく2つあります。
- 波形(temporal / waveform):時間軸そのもの。アタックの鋭さや位相など、時間的なディテールに強い。
- スペクトログラム(spectral / STFT):周波数 × 時間の画像。どの音域に何が鳴っているかという、人が「楽器を聞き分ける」感覚に近い。
歴代の音源分離モデルは、このどちらか一方に寄っていました。Demucs v3(Hybrid Demucs)が両方を1つのネットに統合し、v4 はその上に Transformer を載せたものです。
v4の構造:ハイブリッド bi-U-Net + cross-domain Transformer
論文(arXiv: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. インストール
# Python 3.8+ が前提。仮想環境を切ってから入れるのが安全
python3 -m pip install -U demucs
# mp3 など wav 以外を扱うなら ffmpeg も入れる(Windowsは特に必須)
# macOS: brew install ffmpeg
# Ubuntu: sudo apt install ffmpeg
2. 分離する(1コマンド)
# 既定モデル(htdemucs)で4ステムに分離
demucs song.mp3
# 出力はこの構成で書き出される:
# separated/htdemucs/song/
# ├── drums.wav
# ├── bass.wav
# ├── other.wav
# └── vocals.wav
3. よく使うパターン
# ① カラオケ/ボーカル除去: 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 のAPIをそのまま使います。
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 でやるなら、非ボーカルを合算します。
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 でチャンクの進行を拾えます。
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 に渡すと精度が上がります。
# 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 の記事に。「Demucsで声を抜く → Whisperで起こす」は、動画ローカライズや議事録の品質を底上げする定番の前処理です。
B. 動画ローカライズ:BGMを残して別言語に吹き替える
字幕ではなく音声そのものを差し替えるとき、BGM・効果音まで消えると安っぽくなります。Demucsでナレーションだけ剥がし、BGM(no_vocals)を残すのが肝です。
# 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. カラオケ / 歌ってみた用オフボーカル
demucs --two-stems=vocals --mp3 --mp3-bitrate 320 song.mp3
# → no_vocals.mp3 がそのままカラオケ音源
D. 耳コピ・採譜:ベース/ドラムだけ取り出す
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を例外ではなく正常系として、段階的に縮退させます。
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実行を警告として可視化します。
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段を挟むと、再現性と互換性が跳ね上がります。
# 投入前の正規化: どんな入力でも 44.1kHz ステレオ wav に揃える
ffmpeg -y -i input.any -ar 44100 -ac 2 normalized.wav
④ 二重処理(同じ音源を何度も分離してGPU代を溶かす)
ユーザーの再送・リトライ・連打で、同一音源を何度も分離するとGPU時間がそのまま無駄になります。分離は重い処理なので、ここの取りこぼしはコストに直結します。
対策:入力の中身(ファイルのsha256)+ モデル + パラメータから決定的なジョブキーを作り、結果をキャッシュ。同じ入力なら計算せず既存結果を返す(冪等性)。
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)は「環境を作らず数本だけ試す」のに便利だが、定常的な大量処理は自前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へ退避(回復性のコード参照)。
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 の記事と併読を。
Q. 自前運用とAPI、どちらが安い? A. Demucsは軽量・MITなのでセルフホストが基本。数本試すだけならホスティング(Replicate等)が手軽ですが、定常的な大量処理はGPUバッチの自前運用が単価で有利になりやすい。まずローカルで品質を確かめ、量が増えたらワーカー化、が王道です。
まとめ:Demucs を「動く」から「本番で稼ぐ」へ
Demucs v4(HT Demucs)の本質は、「時間で聞く波形」と「周波数で聞くスペクトログラム」を同時に持ち、Transformer で長距離の文脈を突き合わせた点にあります。だからこそ公開モデルでSOTA級の品質が出て、だからこそ segment・shifts・overlap という設計に根ざしたノブを理解して扱う必要があります。
実装の道筋はシンプルです。
- CLI(
pip install -U demucs→demucs song.mp3) で自分の音源の品質をまず確かめる(GPU不要・CPUでも動く)。 - 手応えがあれば Python API(
demucs.api.Separator) で自前パイプラインに組み込み、用途別プリセットで詰める。 - 本番は冪等性・回復性・可観測性・コストを設計に織り込む——sha256冪等キー、OOMの段階縮退、ffmpeg正規化、構造化ログ。
ここまでやって初めて、デモではなく「顧客の素材で落ちない」プロダクトになります。そして、ここが一番伝えたい点ですが——この一連の設計判断こそが、外注で差がつくところです。「demucs を叩くだけ」のデモは誰でも作れますが、長尺・多様フォーマット・大量バッチの現実で破綻しない基盤は、踏んだ地雷の数がそのまま品質になります。
私は、本稿の落とし穴と回復性設計を実際に本番運用しているAI動画ローカライズ基盤の第1段(音声分離)で実装しました。音源分離を含む音声/動画AIパイプラインの構築・改善をお考えなら、実績をご覧のうえ、お気軽にご相談ください。一人 × 生成AIで、PoCから本番運用まで一気通貫で、速く・安く・安全に作ります。
出典・公式リソース
- 公式リポジトリ(GitHub):adefossez/demucs — README・CLIフラグ・モデル一覧・ハードウェア要件
- Python APIドキュメント:docs/api.md —
demucs.api.Separator/save_audio/list_models - 論文(arXiv):Hybrid Transformers for Music Source Separation (2211.08553) — Rouard, Massa, Défossez(ICASSP 2023)。アーキテクチャ・SDR・sparse attention
- ホスティングAPI(Replicate):cjwbw/demucs — 環境構築なしで試す場合の入力スキーマ・料金
※ バージョン・パラメータ・料金・ライセンスは更新されます。実装前に必ず一次情報を確認してください。本稿の数値(SDR 9.0 / 9.20 dB、segment最大7.8秒、3GB/7GB VRAM、shifts +最大0.2dB、CPU約1.5×実時間など)は本稿執筆時点の公式情報に基づきます。