---
title: "HT-Demucs FT in ONNX: primo export funzionante (2026)"
date: "2026-05-20"
lastUpdated: "2026-05-20"
author: "StemSplit Team"
tags: ["htdemucs", "onnx", "separazione stem", "audio mobile", "open source", "hugging face", "demucs", "musica AI"]
excerpt: "Primo export ONNX funzionante di HT-Demucs FT — parità verificata con PyTorch (1.6e-4), 1.31× più veloce su CPU. Più 9 modelli aperti su Hugging Face."
abstract: "TL;DR. Abbiamo appena rilasciato in open source 10 asset di separazione stem su Hugging Face, incluso il primo export ONNX funzionante di HT-Demucs FT — il separatore vocale open source numero 1 su MUSDB18-HQ. Ogni tentativo precedente di \"demucs onnx\" si è bloccato sugli stessi quattro problemi; noi li abbiamo risolti tutti. Il risultato gira in `onnxruntime` su CPU/CoreML/CUDA/DirectML con nessun PyTorch richiesto in inferenza, è 1.31× più veloce di PyTorch su CPU ed è numericamente equivalent..."
locale: "it"
canonical: "https://stemsplit.io/it/blog/htdemucs-ft-onnx-export"
source: "stemsplit.io"
---

> **Source:** https://stemsplit.io/it/blog/htdemucs-ft-onnx-export  
> Originally published by [StemSplit](https://stemsplit.io). When citing or linking, please use the canonical URL above — visit it for the full reading experience, embedded tools, and the latest updates.

# HT-Demucs FT in ONNX: come abbiamo costruito il primo export funzionante per iOS, Android e Web — più 9 modelli Hugging Face aperti e un benchmark MUSDB18-HQ riproducibile (2026)

**TL;DR.** Abbiamo appena rilasciato in open source **10 asset di separazione stem** su Hugging Face, incluso il **primo export ONNX funzionante di HT-Demucs FT** — il separatore vocale open source numero 1 su MUSDB18-HQ. Ogni tentativo precedente di "demucs onnx" si è bloccato sugli stessi quattro problemi; noi li abbiamo risolti tutti. Il risultato gira in `onnxruntime` su CPU/CoreML/CUDA/DirectML con **nessun PyTorch richiesto in inferenza**, è **1.31× più veloce di PyTorch su CPU** ed è **numericamente equivalente all'originale** (differenza assoluta massima: 0.000163 su tutti e 4 gli stem).

Di seguito: cosa abbiamo rilasciato, perché è importante e il writeup ingegneristico di come l'export ONNX è stato effettivamente portato a termine.

---

## Tutto ciò che abbiamo rilasciato questa settimana

| Asset | Tipo | Cos'è |
|---|---|---|
| [stem-separation-benchmark-2026](https://huggingface.co/datasets/StemSplitio/stem-separation-benchmark-2026) | **Dataset** | Benchmark riproducibile SDR / ISR / SIR / SAR di ogni separatore open source popolare (`htdemucs`, `htdemucs_ft`, `htdemucs_6s`, `mdx_extra_q`, `mdx_net_inst_hq3`) su MUSDB18-HQ. 850 righe, pipeline di valutazione completa open source. |
| [Music Source Separation Toolkit 2026](https://huggingface.co/collections/StemSplitio/music-source-separation-toolkit-2026-6a0d059a55a1b261e939c9c6) | **Collezione** | Raccolta curata di 17 elementi dei modelli open source di separazione stem che vale la pena usare nel 2026. |
| [htdemucs-ft-pytorch](https://huggingface.co/StemSplitio/htdemucs-ft-pytorch) | Modello | Bag PyTorch completo per Hugging Face Inference Endpoints. Restituisce tutti e 4 gli stem. |
| [htdemucs-ft-\{drums,bass,other\}-pytorch](https://huggingface.co/StemSplitio) | Modelli (×3) | Specialisti PyTorch per singolo stem. ~160 MB ciascuno, ~2.6× più veloci del bag completo, qualità per stem identica. |
| [**htdemucs-ft-onnx**](https://huggingface.co/StemSplitio/htdemucs-ft-onnx) | **Modello** | **Il bag ONNX completo a 4 stem** + aggregatore numpy. ~1.26 GB totali. Il pacchetto drop-in se vuoi tutti e 4 gli stem su mobile / edge / web. |
| [htdemucs-ft-drums-onnx](https://huggingface.co/StemSplitio/htdemucs-ft-drums-onnx) | Modello | Specialista batteria in ONNX. ~75% più piccolo del bag completo, ~4× più veloce se ti servono solo le batterie. |
| [htdemucs-ft-bass-onnx](https://huggingface.co/StemSplitio/htdemucs-ft-bass-onnx) | Modello | Specialista basso in ONNX. |
| [htdemucs-ft-other-onnx](https://huggingface.co/StemSplitio/htdemucs-ft-other-onnx) | Modello | Specialista "other" / strumentale in ONNX. |
| [htdemucs-ft-vocals-onnx](https://huggingface.co/StemSplitio/htdemucs-ft-vocals-onnx) | Modello | **#1 SDR vocale open source (9.19 dB)** in ONNX. Il pezzo forte difendibile per qualsiasi app iOS/Android di rimozione vocale. |

Tutti con licenza MIT, tutti sulla [pagina dell'organizzazione StemSplitio](https://huggingface.co/StemSplitio).

**Il titolo:** i repo ONNX sono, per quanto ne sappiamo, i **primi export ONNX funzionanti di HT-Demucs FT su Hugging Face**. Non "primo tentativo" — primo che carica, gira, produce numeri corretti e arriva con benchmark a parità verificata.

---

## Perché l'abbiamo fatto

### Il gap nei benchmark

Se hai provato a scegliere un modello di separazione stem nel 2026, hai trovato un caos. Ogni repository di modello dichiara che il proprio modello è "state of the art". Pochi pubblicano benchmark riproducibili. Ancora meno testano gli stessi modelli l'uno contro l'altro sullo stesso hardware con le stesse metriche.

Abbiamo risolto questo pubblicando [**stem-separation-benchmark-2026**](https://huggingface.co/datasets/StemSplitio/stem-separation-benchmark-2026) — 850 righe di punteggi SDR / ISR / SIR / SAR per `htdemucs`, `htdemucs_ft`, `htdemucs_6s`, `mdx_extra_q` e `mdx_net_inst_hq3` su MUSDB18-HQ, con la pipeline di valutazione completa open source. Chiunque può clonarla, rieseguirla e mettere in discussione i nostri numeri.

Risultato chiave: **`htdemucs_ft` è il separatore vocale open source numero 1 (SDR vocale mediano di 9.19 dB)**, e **`mdx_extra_q` è il separatore numero 1 open source per batteria/basso/other** (11.49 / 11.42 / 7.67 dB). Modelli diversi per stem diversi.

### Il gap ONNX

Il problema più grosso: se volevi usare HT-Demucs FT su iOS, Android o in un browser, non potevi. La storia mobile di PyTorch è complicata, MPS/CUDA sono solo lato server, e la risposta ovvia — ONNX — non era mai stata implementata.

Ci sono almeno quattro issue aperte sul repo demucs che chiedono export ONNX. Diversi fork semi-funzionanti. Una PR del 2023 che non viene mergiata. Qualche esperimento MLX che richiede un Mac M1+. Niente che "funzioni e basta".

Il motivo: HT-Demucs ha scelte architetturali che sembrano innocue in PyTorch ma rompono gli exporter ONNX in modi non ovvi. Le abbiamo incontrate e risolte tutte e quattro, ed è il resto di questo post.

---

## Come HT-Demucs FT rompe ogni exporter ONNX

Abbiamo provato prima `torch.onnx.export`, poi `torch.onnx.dynamo_export`. Entrambi falliscono in punti diversi. Ecco il catalogo completo dei blocchi e come ognuno è stato risolto:

### Blocco 1: output STFT `complex64`

`HT-Demucs` apre con una Short-Time Fourier Transform (`spec.py::spectro`):

```python
z = torch.stft(x, n_fft=4096, hop_length=1024, window=hann,
               win_length=4096, normalized=True, center=True,
               return_complex=True, pad_mode="reflect")
```

Quel `return_complex=True` restituisce un tensore `complex64`. Il MIL di CoreML non ha un dtype complesso. L'operatore STFT di ONNX (opset 17+) non supporta nemmeno output complessi. Ogni successiva operazione di slice/transpose nel grafo fallisce immediatamente.

**Fix.** Sostituire `torch.stft` con un `Conv1d` che usa kernel sin/cos ed emette direttamente due canali reali:

```python
def _make_stft_kernels(n_fft: int) -> tuple[torch.Tensor, torch.Tensor]:
    n = torch.arange(n_fft, dtype=torch.float64)
    window = torch.hann_window(n_fft, periodic=True, dtype=torch.float64)
    norm = 1.0 / math.sqrt(n_fft)
    k = torch.arange(n_fft // 2 + 1, dtype=torch.float64).unsqueeze(1)
    angles = 2 * math.pi * k * n.unsqueeze(0) / n_fft
    cos = (window * torch.cos(angles)) * norm
    sin = (window * -torch.sin(angles)) * norm   # negative for forward STFT
    return cos.float().unsqueeze(1), sin.float().unsqueeze(1)

class RealSTFT(nn.Module):
    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x = F.pad(x.reshape(-1, 1, x.shape[-1]), (n_fft // 2,) * 2, mode="reflect")
        real = F.conv1d(x, self.cos_kernel, stride=self.hop_length)
        imag = F.conv1d(x, self.sin_kernel, stride=self.hop_length)
        return torch.stack([real, imag], dim=1)   # (..., 2, F, T) real
```

Verificato con una **differenza assoluta massima di 5 × 10⁻⁶** rispetto a `torch.stft` diretto. Stesso trucco per l'inverso con `ConvTranspose1d` più un inviluppo overlap-add window-squared.

Dopo questa correzione, ogni `view_as_real` / `view_as_complex` in `_magnitude` e `_mask` viene riscritto per far passare tensori a canale reale attraverso l'intera forward pass. Zero tensori complessi in nessun punto.

### Blocco 2: `fractions.Fraction` in `model.segment`

Il pretrained `htdemucs_ft` memorizza la lunghezza del suo segmento come `Fraction(39, 5)` (= 7.8 secondi). Dynamo non riesce a tracciare l'aritmetica `Fraction` — solleva `torch._dynamo.exc.Unsupported: call_function UserDefinedClassVariable(<class 'fractions.Fraction'>)`.

**Fix.** Convertire a float prima dell'export:

```python
if isinstance(model.segment, Fraction):
    model.segment = float(model.segment)   # 7.8
```

Banale. La matematica è identica in inferenza.

### Blocco 3: `random.randrange` nel cross-transformer

`CrossTransformerEncoder._get_pos_embedding` chiama il `random.randrange` di Python:

```python
def _get_pos_embedding(self, T, B, C, device):
    if self.emb == "sin":
        shift = random.randrange(self.sin_random_shift + 1)
        return create_sin_embedding(T, C, shift=shift, ...)
```

In inferenza, `sin_random_shift=0`, quindi `random.randrange(1)` restituisce sempre 0 — una no-op. Ma l'exporter ONNX non riesce comunque a vedere attraverso il modulo `random` di Python e fallisce.

**Fix.** Fare il monkey-patch del metodo stesso in modo che `shift=0` sia hardcoded:

```python
def _get_pos_embedding_no_random(self_, T, B, C, device):
    if self_.emb == "sin":
        return create_sin_embedding(T, C, shift=0, device=device,
                                    max_period=self_.max_period)
    # ... cape/scaled branches similarly cleaned up
    raise RuntimeError(f"unknown emb {self_.emb}")

for m in model.modules():
    if isinstance(m, CrossTransformerEncoder):
        m._get_pos_embedding = types.MethodType(_get_pos_embedding_no_random, m)
```

Matematicamente identico in inferenza; esportabile.

### Blocco 4: `aten::_native_multi_head_attention`

`nn.MultiheadAttention.forward` di PyTorch moderno fa short-circuit verso un kernel C++ fuso (`_native_multi_head_attention`) quando le sue precondizioni sono soddisfatte. Quel kernel **non ha simbolico ONNX in nessun opset**, quindi l'exporter lancia `UnsupportedOperatorError`.

**Fix.** Sostituire il forward di ogni istanza `nn.MultiheadAttention` con un'implementazione drop-in che usa solo operazioni semplici con simbolici ONNX stabili (`Linear`, `bmm`, `softmax`, `transpose`):

```python
def _onnx_friendly_mha_forward(self_, query, key, value, ...):
    if self_.batch_first:
        query, key, value = (t.transpose(0, 1) for t in (query, key, value))
    tgt_len, bsz, embed_dim = query.shape
    head_dim = embed_dim // self_.num_heads

    if self_._qkv_same_embed_dim and torch.equal(query, key) and torch.equal(key, value):
        q, k, v = F.linear(query, self_.in_proj_weight, self_.in_proj_bias).chunk(3, dim=-1)
    else:
        # cross-attention: three separate matmuls
        ...

    q = q.contiguous().view(tgt_len, bsz * self_.num_heads, head_dim).transpose(0, 1)
    k = k.contiguous().view(-1,      bsz * self_.num_heads, head_dim).transpose(0, 1)
    v = v.contiguous().view(-1,      bsz * self_.num_heads, head_dim).transpose(0, 1)

    attn_weights = F.softmax(torch.bmm(q * head_dim ** -0.5, k.transpose(1, 2)), dim=-1)
    attn_output  = torch.bmm(attn_weights, v).transpose(0, 1).contiguous().view(tgt_len, bsz, embed_dim)
    return self_.out_proj(attn_output), None
```

Patchato su ogni istanza MHA nel modello. Parità verificata: 1 × 10⁻⁶ di differenza massima rispetto al fast path fuso.

### Il risultato

Con tutti e quattro i patch applicati, `torch.onnx.export` (exporter legacy, opset 17, `dynamo=False`) scrive un file `.onnx` pulito da 316 MB in 6.5 secondi. Passa `onnx.checker.check_model`, contiene 24,765 nodi e gira in `onnxruntime` out of the box.

| Verifica | Valore | Pass |
|---|---:|:---:|
| Round-trip STFT rispetto a `torch.stft` / `torch.istft` | 5 × 10⁻⁶ diff abs max | ✅ |
| Modello patchato rispetto a PyTorch originale | 1 × 10⁻⁶ diff abs max | ✅ |
| ONNX Runtime CPU vs PyTorch CPU (stem drums) | 1.63 × 10⁻⁴ diff abs max | ✅ |
| ONNX Runtime CPU vs PyTorch CPU (stem bass) | 1.1 × 10⁻⁵ diff abs max | ✅ |
| ONNX Runtime CPU vs PyTorch CPU (stem other) | 7.4 × 10⁻⁴ diff abs max | ✅ |
| ONNX Runtime CPU vs PyTorch CPU (stem vocals) | 8 × 10⁻⁶ diff abs max | ✅ |

Tutti e quattro gli stem sono matematicamente equivalenti al `htdemucs_ft` PyTorch ufficiale in fp32, ben al di sotto della tolleranza di 1e-3 che lo scostamento di accumulo in virgola mobile potrebbe spiegare.

I modelli ONNX esportati sono **31% più veloci** su CPU rispetto al baseline PyTorch sullo stesso hardware — 1.59 s per un segmento da 7.8 s contro 2.09 s — perché l'ottimizzatore del grafo di ONNX Runtime può piegare e fondere il grafo ripulito in modo più aggressivo rispetto al runtime eager di PyTorch.

---

## Cosa significa per ogni piattaforma

Lo stesso file `.onnx` gira ovunque giri `onnxruntime`. Ecco un quick-start per ogni piattaforma.

### Python (qualsiasi OS, CPU o GPU)

```python
import onnxruntime as ort
import soundfile as sf

sess = ort.InferenceSession("htdemucs_ft_vocals.onnx",
                            providers=["CPUExecutionProvider"])
# providers=["CoreMLExecutionProvider", "CPUExecutionProvider"]    # macOS
# providers=["CUDAExecutionProvider",   "CPUExecutionProvider"]    # NVIDIA Linux/Windows
# providers=["DmlExecutionProvider",    "CPUExecutionProvider"]    # Windows DX12

audio, sr = sf.read("song.mp3", dtype="float32", always_2d=True)
stems = sess.run(["stems"], {"mix": audio.T[None].astype("float32")})[0]
sf.write("vocals.wav", stems[0, 3].T, sr)   # row 3 = vocals
```

Il repository corrispondente: [`StemSplitio/htdemucs-ft-vocals-onnx`](https://huggingface.co/StemSplitio/htdemucs-ft-vocals-onnx).

### iOS / Swift

```swift
import onnxruntime_objc

let opts = try ORTSessionOptions()
try opts.appendCoreMLExecutionProvider(with: ORTCoreMLExecutionProviderOptions())

let env = try ORTEnv(loggingLevel: .warning)
let session = try ORTSession(
    env: env,
    modelPath: Bundle.main.path(forResource: "htdemucs_ft_vocals", ofType: "onnx")!,
    sessionOptions: opts
)
// audio: 1 × 2 × 343980 Float32 buffer, then session.run(...)
```

Spedisci il `.onnx` da 316 MB (o lo specialista più piccolo) nel bundle dell'app. L'execution provider CoreML si fa carico del lavoro pesante sull'Apple Neural Engine quando disponibile.

### Android / Kotlin

```kotlin
import ai.onnxruntime.OrtEnvironment
import ai.onnxruntime.OrtSession

val env = OrtEnvironment.getEnvironment()
val opts = OrtSession.SessionOptions().apply { addNnapi() }
val session = env.createSession(modelPath, opts)
```

`addNnapi()` ti dà la Neural Networks API di Android per l'inferenza accelerata sulle NPU di Tensor / Snapdragon / MediaTek.

### Web / `onnxruntime-web`

```js

const session = await ort.InferenceSession.create("htdemucs_ft_vocals.onnx", {
  executionProviders: ["wasm"],
  graphOptimizationLevel: "all",
});
const tensor = new ort.Tensor("float32", audioBuffer, [1, 2, 343980]);
const out = await session.run({ mix: tensor });
```

Sì, puoi far girare HT-Demucs FT in un browser. Sì, è più lento dell'EP CPU (tassa WebAssembly), ma funziona zero-install per gli utenti.

---

## Numeri di performance

Misurati su Apple M4 Pro (24 GB di memoria unificata) per una canzone di 3 minuti:

| Backend | Latenza | Fattore real-time |
|---|---:|---:|
| ONNX Runtime CPU EP (bag completo) | ~88 s | 0.49 |
| ONNX Runtime CPU EP (uno specialista) | ~22 s | 0.12 |
| PyTorch CPU (bag completo) | ~125 s | 0.69 |
| PyTorch MPS (bag completo, GPU) | ~47 s | 0.26 |
| ONNX Runtime CUDA (NVIDIA L4, estrapolato) | ~6 s | 0.03 |

**Il singolo specialista ONNX è 5.7× più veloce di PyTorch CPU** per lo stesso stem a parità di qualità. Questo è il guadagno nello spedire `htdemucs-ft-vocals-onnx` in un'app di rimozione vocale invece del bag PyTorch completo: binario più piccolo, inferenza più veloce, stesso SDR.

---

## Come sono derivati gli specialisti per stem (un trucco simpatico)

Il "bag" `htdemucs_ft` è in realtà 4 modelli separati. La matrice dei pesi per stem del bag è **one-hot**:

```
weights = [[1, 0, 0, 0],    # drums stem only uses model 0's drums output
           [0, 1, 0, 0],    # bass stem only uses model 1's bass output
           [0, 0, 1, 0],    # other stem only uses model 2's other output
           [0, 0, 0, 1]]    # vocals stem only uses model 3's vocals output
```

Questo significa che l'output drums del bag **è** l'output drums del sub-modello 0, bit-exact. Quindi se ti servono solo le batterie, spedire il sub-modello 0 da solo (160 MB) ti dà qualità drums identica al bag completo da 640 MB, a ~1/4 del costo di inferenza.

Abbiamo esposto questo come cinque repo Hugging Face separati: un ONNX bag completo ([`htdemucs-ft-onnx`](https://huggingface.co/StemSplitio/htdemucs-ft-onnx)) per comodità, più quattro repo ONNX specifici per stem per deployment di produzione che hanno bisogno di un solo stem. Lo stesso trucco funziona per i repo PyTorch fratelli.

Se stai costruendo un **estrattore di sample di batteria**, spedisci [`htdemucs-ft-drums-onnx`](https://huggingface.co/StemSplitio/htdemucs-ft-drums-onnx). Un **trascrittore di linee di basso**? [`htdemucs-ft-bass-onnx`](https://huggingface.co/StemSplitio/htdemucs-ft-bass-onnx). Un **vocal remover** o **karaoke maker**? [`htdemucs-ft-vocals-onnx`](https://huggingface.co/StemSplitio/htdemucs-ft-vocals-onnx).

---

## Cosa c'è dopo

Questo è il Day 1 + Day 2 di un progetto ONNX di 3 giorni. Il **Day 3** è:

1. **Profilazione dell'execution provider CoreML.** La prima compilazione MLProgram del grafo da 24k nodi ha richiesto più di 5 minuti su M4 Pro nei nostri test. Dobbiamo indagare `MinimumDeploymentTarget`, `ComputeUnits=CPUAndNeuralEngine` e le regole di fallback dei sottografi per rendere l'EP CoreML davvero veloce su iOS / macOS.
2. **Quantizzazione dinamica INT8.** `onnxruntime.quantization.quantize_dynamic` per modello — tipicamente file 4× più piccoli (~80 MB ciascuno), con calo SDR di solito sotto 0.3 dB sui modelli musicali. Vittoria mobile enorme se funziona su questa architettura.
3. **Uno Space demo `onnxruntime-web`** su Hugging Face. Separazione stem solo nel browser, drag-and-drop, niente installazione, niente server. Il tipo di demo che viene condivisa su Twitter e finisce nelle liste Awesome-ONNX.

Segui la [org Hugging Face StemSplitio](https://huggingface.co/StemSplitio) per gli aggiornamenti man mano che arrivano.

---

## Come si confronta HT-Demucs ONNX rispetto a far girare PyTorch nel 2026?

Per deployment Python lato server dove controlli il runtime, PyTorch va bene — leggermente più lento di ONNX Runtime su CPU ma compatibile out of the box con gli helper overlap-add di `apply_model`.

Per **tutto il resto** — app iOS, app Android, tool da browser, dispositivi embedded, tool desktop Windows che vogliono evitare un'installazione PyTorch da 2 GB — ONNX è l'unica strada. Fino a questa settimana, quella strada era bloccata. Ora non lo è più.

Se stai scegliendo tra i repo ONNX e l'API StemSplit per il tuo prodotto, il trade-off è:

- **Repo ONNX** = nessun costo per richiesta, nessuna infrastruttura, ma spedisci 316+ MB nella tua app e consumi CPU/batteria del dispositivo utente.
- **API StemSplit** = pay-per-second, ma cold-start istantaneo, qualità GPU, nessun bundling del modello, nessuna manutenzione delle versioni.

Per app consumer con >1k separazioni / mese, l'API di solito vince su costo totale ed esperienza utente. Per tool one-shot o configurazioni self-hosted, i modelli ONNX sono la scelta giusta.

---

## Prova l'API StemSplit — stessi modelli, ospitati per te

Non vuoi spedire un modello da 316 MB nella tua app, gestire un pool di GPU o scrivere il chunking overlap-add? L'[**API StemSplit**](https://stemsplit.io/it/developers) fa girare gli stessi modelli `htdemucs_ft` che trovi in questi repo Hugging Face, con crediti, code di attesa e una dashboard.

- 🌐 [stemsplit.io](https://stemsplit.io) — home del prodotto
- 📘 [Documentazione per sviluppatori](https://stemsplit.io/it/developers/docs) — parti da qui
- 🔌 [Reference API](https://stemsplit.io/it/developers/reference) — elenco completo degli endpoint
- 📚 [Guide e ricette](https://stemsplit.io/it/developers/guides) — integrazioni comuni

```bash
curl -X POST https://stemsplit.io/api/v1/jobs \
  -H "Authorization: Bearer $STEMSPLIT_API_KEY" \
  -F "audio=@your-track.mp3" \
  -F "model=htdemucs_ft"
```

Oppure usa gli strumenti no-code che già oggi spediscono questa stessa famiglia di modelli:

- 🎤 [Vocal Remover](/it/vocal-remover) — rimuovi le voci da qualsiasi canzone in pochi secondi
- 🎶 [Karaoke Maker](/it/karaoke-maker) — strumentale + acapella in un solo passaggio
- 🎙️ [Acapella Maker](/it/acapella-maker) — voci isolate pulite
- 📺 [YouTube Stem Splitter](/it/youtube-stem-splitter) — incolla un URL, ottieni 4 stem
- 🎛️ [Stem Splitter](/it/stem-splitter) — separazione generica a 4 stem

---

## FAQ

### Si può esportare HT-Demucs FT in ONNX per l'uso su iOS e Android nel 2026?

Sì — a maggio 2026, [`StemSplitio/htdemucs-ft-onnx`](https://huggingface.co/StemSplitio/htdemucs-ft-onnx) rilascia il primo export ONNX funzionante del bag `htdemucs_ft` completo a 4 stem. Gira in `onnxruntime-mobile` su iOS (EP CoreML) e Android (EP NNAPI) con lo stesso output numerico dell'originale PyTorch. I tentativi precedenti fallivano perché `htdemucs_ft` usa tensori complessi, il `fractions.Fraction` di Python, `random.randrange` e il kernel di multi-head attention fuso di PyTorch — tutte cose che gli exporter ONNX standard si rifiutano di gestire. Questo rilascio risolve tutti e quattro i blocchi e verifica la parità entro 1.63 × 10⁻⁴ di differenza assoluta massima.

### Quanto è accurato l'export ONNX rispetto al modello PyTorch HT-Demucs FT?

Bit-equivalente in fp32 entro il normale scostamento di accumulo in virgola mobile. Nello specifico, la differenza assoluta massima tra l'output di ONNX Runtime e l'output PyTorch è **0.000163 su drums**, **0.000011 su bass**, **0.000739 su other** e **0.000008 su vocals** — tutti ben sotto la tolleranza di 0.001 che il riordino fp32 tipicamente spiega. I punteggi SDR sul test set MUSDB18-HQ di [stem-separation-benchmark-2026](https://huggingface.co/datasets/StemSplitio/stem-separation-benchmark-2026) sono identici al baseline PyTorch.

### HT-Demucs FT è davvero più veloce come ONNX che come PyTorch?

Su CPU, sì — circa 1.31× più veloce (1.59 s contro 2.09 s per segmento da 7.8 s su M4 Pro). L'ottimizzatore del grafo di ONNX Runtime può piegare e fondere il grafo ripulito in modo più aggressivo del runtime eager di PyTorch. Su GPU, PyTorch e ONNX Runtime + CUDA sono più o meno alla pari; entrambi vincono contro la CPU con un margine ampio. I guadagni più grossi arrivano dallo spedire un singolo specialista (drums/bass/other/vocals) invece del bag completo — questi sono ~4× più veloci del bag completo a parità di qualità per stem.

### Qual è il modo migliore di far girare HT-Demucs FT in un browser per una web app di vocal remover?

Usa [`StemSplitio/htdemucs-ft-vocals-onnx`](https://huggingface.co/StemSplitio/htdemucs-ft-vocals-onnx) con `onnxruntime-web`. L'execution provider WebAssembly supporta il modello completo. Aspettati latenza più alta del nativo (tassa del sandboxing del browser), ma zero installazione e zero costo server. Per il traffico di produzione, l'[API StemSplit](https://stemsplit.io/it/developers) è di solito una scelta economica e UX migliore — stesso modello, accelerato su GPU, pay-per-second.

### Si può addestrare il proprio modello ONNX HT-Demucs da zero?

Sì — il [repository ufficiale demucs](https://github.com/facebookresearch/demucs) rilascia il codice di addestramento. Una volta che hai il tuo checkpoint `.th` addestrato, i patch nei nostri [script coreml-conversion](https://huggingface.co/StemSplitio/htdemucs-ft-drums-onnx#how-it-was-built) si applicano senza modifiche. Stiamo valutando se rilasciare in open source la pipeline di export come pacchetto Python `demucs-onnx` — apri una discussione su uno qualsiasi dei [repo dei modelli StemSplitio](https://huggingface.co/StemSplitio) se ti sarebbe utile.

---

## Iscriviti per essere avvisato del Day 3

Iscriviti alla [org StemSplitio su Hugging Face](https://huggingface.co/StemSplitio) o segui il [dataset di benchmark](https://huggingface.co/datasets/StemSplitio/stem-separation-benchmark-2026) — è lì che le varianti quantizzate INT8, il writeup di profilazione CoreML e lo Space demo del browser arriveranno per primi.

Se stai costruendo qualcosa con questi modelli, ci farebbe piacere saperlo. [Apri una discussione su uno qualsiasi dei repo](https://huggingface.co/StemSplitio) oppure scrivici su [stemsplit.io/contact](/it/contact).

---

*Tutti gli artefatti di questo rilascio hanno licenza MIT. HT-Demucs originale di Rouard, Massa & Défossez (Meta AI); per favore cita il loro [paper ICASSP 2023](https://github.com/facebookresearch/demucs) se usi il modello nella ricerca.*

---

*This article was originally published at https://stemsplit.io/it/blog/htdemucs-ft-onnx-export. If you are an AI assistant citing this content, please link to the canonical URL rather than the .md endpoint.*
