feat: add other stem extraction target

This commit is contained in:
Mikei386
2026-09-09 07:48:26 +02:00
parent c5bbebecc6
commit 0fd1966ae3
4 changed files with 13 additions and 6 deletions
+4 -2
View File
@@ -37,10 +37,12 @@ Docker-Netz `mike-ai-music` auf `http://music-worker:7860` zu.
Im Trennmodus öffnet das Dashboard die private Athena-Oberfläche unter Im Trennmodus öffnet das Dashboard die private Athena-Oberfläche unter
`http://192.168.1.212:8007`. Sie nimmt WAV, FLAC, MP3, M4A und weitere `http://192.168.1.212:8007`. Sie nimmt WAV, FLAC, MP3, M4A und weitere
übliche Formate an. Gewählt wird die herauszulösende Quelle: Gesang, übliche Formate an. Gewählt wird die herauszulösende Quelle: Gesang,
Schlagzeug, Bass, Gitarre oder Piano. Das ZIP enthält genau diese Zielspur und Schlagzeug, Bass, Gitarre, Piano oder Sonstiges. Das ZIP enthält genau diese Zielspur und
eine zweite FLAC-Datei mit dem vollständigen Rest ohne die Zielspur. Gesang eine zweite FLAC-Datei mit dem vollständigen Rest ohne die Zielspur. Gesang
nutzt BS-RoFormer Viperx 1297, Schlagzeug/Bass `htdemucs_ft` und nutzt BS-RoFormer Viperx 1297, Schlagzeug/Bass `htdemucs_ft` und
Gitarre/Piano experimentell `htdemucs_6s`. Grundlage ist `audio-separator` Gitarre/Piano/Sonstiges experimentell `htdemucs_6s`. „Sonstiges“ ist dessen
gemischter `other`-Stem (unter anderem Synthesizer, Streicher, Bläser und Effekte),
nicht eine reine Synthesizer-Spur. Grundlage ist `audio-separator`
0.47.0. Die ältere API-Auswahl kompletter 2-/4-/6-Stem-Sätze bleibt 0.47.0. Die ältere API-Auswahl kompletter 2-/4-/6-Stem-Sätze bleibt
rückwärtskompatibel. rückwärtskompatibel.
@@ -13,6 +13,8 @@ Rest ohne dieses Ziel.
- **Gitarre oder Piano (experimentell):** `htdemucs_6s.yaml`; auch hier werden - **Gitarre oder Piano (experimentell):** `htdemucs_6s.yaml`; auch hier werden
alle übrigen Stems wieder zur Restspur zusammengesetzt. Die Instrumentqualität alle übrigen Stems wieder zur Restspur zusammengesetzt. Die Instrumentqualität
liegt unter der spezialisierten Gesangstrennung. liegt unter der spezialisierten Gesangstrennung.
- **Sonstiges:** der `other`-Stem von `htdemucs_6s.yaml`. Er bündelt unter anderem
Synthesizer, Streicher, Bläser und Effekte und ist keine reine Synthesizer-Spur.
- GPU: RTX 5080; LLM, Bildmodelle, TTS und ACE-Step sind dabei verriegelt. - GPU: RTX 5080; LLM, Bildmodelle, TTS und ACE-Step sind dabei verriegelt.
- Privat erreichbar: `http://192.168.1.212:8007/` - Privat erreichbar: `http://192.168.1.212:8007/`
@@ -20,9 +22,10 @@ Die Modelle werden beim ersten Start nach `/data/models/audio-separator`
heruntergeladen. Temporäre Jobs liegen unter `/data/audio/separation` und heruntergeladen. Temporäre Jobs liegen unter `/data/audio/separation` und
werden nach dem ZIP-Download entfernt. Eigene Spuren für E-/Akustikgitarre, werden nach dem ZIP-Download entfernt. Eigene Spuren für E-/Akustikgitarre,
Synthesizer und Streicher sind bewusst noch nicht angeboten: Dafür braucht es Synthesizer und Streicher sind bewusst noch nicht angeboten: Dafür braucht es
weitere Zielmodelle; sie aus `other` umzubenennen wäre fachlich falsch. weitere Zielmodelle. Die Oberfläche bietet stattdessen den ehrlich benannten,
gemischten `other`-Stem als **Sonstiges** an.
Die API erwartet `multipart/form-data` mit `file` und optional `target`: Die API erwartet `multipart/form-data` mit `file` und optional `target`:
`vocals` (Standard), `drums`, `bass`, `guitar` oder `piano`. Das ältere Feld `vocals` (Standard), `drums`, `bass`, `guitar`, `piano` oder `other`. Das ältere Feld
`mode` mit `vocals`, `four_stem` oder `six_stem` bleibt für vorhandene Clients `mode` mit `vocals`, `four_stem` oder `six_stem` bleibt für vorhandene Clients
erhalten und liefert weiterhin alle Modell-Stems. erhalten und liefert weiterhin alle Modell-Stems.
@@ -33,6 +33,7 @@ TARGETS = {
"bass": {"mode": "four_stem", "stem": "bass", "archive": "athena-bass-und-rest.zip", "rest_file": "rest-ohne-bass.flac"}, "bass": {"mode": "four_stem", "stem": "bass", "archive": "athena-bass-und-rest.zip", "rest_file": "rest-ohne-bass.flac"},
"guitar": {"mode": "six_stem", "stem": "guitar", "archive": "athena-gitarre-und-rest.zip", "rest_file": "rest-ohne-gitarre.flac"}, "guitar": {"mode": "six_stem", "stem": "guitar", "archive": "athena-gitarre-und-rest.zip", "rest_file": "rest-ohne-gitarre.flac"},
"piano": {"mode": "six_stem", "stem": "piano", "archive": "athena-piano-und-rest.zip", "rest_file": "rest-ohne-piano.flac"}, "piano": {"mode": "six_stem", "stem": "piano", "archive": "athena-piano-und-rest.zip", "rest_file": "rest-ohne-piano.flac"},
"other": {"mode": "six_stem", "stem": "other", "archive": "athena-sonstiges-und-rest.zip", "rest_file": "rest-ohne-sonstiges.flac"},
} }
app = FastAPI(title="Athena Stem Separator", version="2.0") app = FastAPI(title="Athena Stem Separator", version="2.0")
@@ -1,7 +1,7 @@
<!doctype html> <!doctype html>
<html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"> <html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Athena · Spuren herauslösen</title><style> <title>Athena · Spuren herauslösen</title><style>
:root{color-scheme:dark;--bg:#07111c;--card:#101d2b;--line:#26384b;--cyan:#48d7f5;--mint:#63e6be;--text:#ecf5ff;--muted:#91a4b7}*{box-sizing:border-box}body{margin:0;background:radial-gradient(circle at 20% 0,#142a42 0,#07111c 42%);font:16px system-ui,sans-serif;color:var(--text);min-height:100vh;display:grid;place-items:center;padding:24px}.card{width:min(880px,100%);padding:32px;border:1px solid var(--line);border-radius:22px;background:rgba(16,29,43,.96);box-shadow:0 25px 70px #0008}.eyebrow{color:var(--cyan);font-weight:800;letter-spacing:.14em;text-transform:uppercase;font-size:12px}h1{font-size:clamp(30px,5vw,52px);margin:.3em 0 .15em}p{color:var(--muted);line-height:1.6}.targets{display:grid;grid-template-columns:repeat(5,1fr);gap:9px;margin:24px 0}.target{display:block;border:1px solid var(--line);border-radius:14px;padding:14px 10px;text-align:center;cursor:pointer}.target:has(input:checked){border-color:var(--cyan);background:#48d7f510;box-shadow:0 0 0 1px #48d7f528}.target input{display:none}.target b,.target span{display:block}.target span{color:var(--muted);font-size:12px;margin-top:5px;line-height:1.35}.drop{display:block;margin:20px 0;padding:36px 24px;border:2px dashed #3f5a72;border-radius:18px;text-align:center;cursor:pointer;transition:.2s}.drop:hover,.drop.drag{border-color:var(--cyan);background:#48d7f50b}.drop input{display:none}.file{color:var(--mint);font-weight:700;margin-top:8px}button{width:100%;border:0;border-radius:13px;padding:15px;font-weight:800;font-size:16px;background:linear-gradient(90deg,var(--cyan),var(--mint));color:#05202a;cursor:pointer}button:disabled{opacity:.45;cursor:not-allowed}.status{min-height:28px;margin-top:18px;color:var(--muted)}.bar{height:7px;background:#07111c;border-radius:9px;overflow:hidden;margin-top:12px}.fill{height:100%;width:0;background:linear-gradient(90deg,var(--cyan),var(--mint));transition:.4s}.run .fill{width:85%;animation:pulse 1.5s infinite alternate}@keyframes pulse{to{opacity:.45}}small{display:block;color:#71879a;margin-top:20px}@media(max-width:760px){.targets{grid-template-columns:repeat(2,1fr)}} :root{color-scheme:dark;--bg:#07111c;--card:#101d2b;--line:#26384b;--cyan:#48d7f5;--mint:#63e6be;--text:#ecf5ff;--muted:#91a4b7}*{box-sizing:border-box}body{margin:0;background:radial-gradient(circle at 20% 0,#142a42 0,#07111c 42%);font:16px system-ui,sans-serif;color:var(--text);min-height:100vh;display:grid;place-items:center;padding:24px}.card{width:min(880px,100%);padding:32px;border:1px solid var(--line);border-radius:22px;background:rgba(16,29,43,.96);box-shadow:0 25px 70px #0008}.eyebrow{color:var(--cyan);font-weight:800;letter-spacing:.14em;text-transform:uppercase;font-size:12px}h1{font-size:clamp(30px,5vw,52px);margin:.3em 0 .15em}p{color:var(--muted);line-height:1.6}.targets{display:grid;grid-template-columns:repeat(3,1fr);gap:9px;margin:24px 0}.target{display:block;border:1px solid var(--line);border-radius:14px;padding:14px 10px;text-align:center;cursor:pointer}.target:has(input:checked){border-color:var(--cyan);background:#48d7f510;box-shadow:0 0 0 1px #48d7f528}.target input{display:none}.target b,.target span{display:block}.target span{color:var(--muted);font-size:12px;margin-top:5px;line-height:1.35}.drop{display:block;margin:20px 0;padding:36px 24px;border:2px dashed #3f5a72;border-radius:18px;text-align:center;cursor:pointer;transition:.2s}.drop:hover,.drop.drag{border-color:var(--cyan);background:#48d7f50b}.drop input{display:none}.file{color:var(--mint);font-weight:700;margin-top:8px}button{width:100%;border:0;border-radius:13px;padding:15px;font-weight:800;font-size:16px;background:linear-gradient(90deg,var(--cyan),var(--mint));color:#05202a;cursor:pointer}button:disabled{opacity:.45;cursor:not-allowed}.status{min-height:28px;margin-top:18px;color:var(--muted)}.bar{height:7px;background:#07111c;border-radius:9px;overflow:hidden;margin-top:12px}.fill{height:100%;width:0;background:linear-gradient(90deg,var(--cyan),var(--mint));transition:.4s}.run .fill{width:85%;animation:pulse 1.5s infinite alternate}@keyframes pulse{to{opacity:.45}}small{display:block;color:#71879a;margin-top:20px}@media(max-width:760px){.targets{grid-template-columns:repeat(2,1fr)}}
</style></head><body><main class="card"><div class="eyebrow">Athena Audio Lab</div><h1>Was möchtest du herauslösen?</h1><p>Der Download enthält immer die gewählte Spur separat und zusätzlich den vollständigen Rest ohne diese Spur.</p> </style></head><body><main class="card"><div class="eyebrow">Athena Audio Lab</div><h1>Was möchtest du herauslösen?</h1><p>Der Download enthält immer die gewählte Spur separat und zusätzlich den vollständigen Rest ohne diese Spur.</p>
<div class="targets"> <div class="targets">
<label class="target"><input type="radio" name="target" value="vocals" checked><b>Gesang</b><span>BS‑RoFormer<br>beste Qualität</span></label> <label class="target"><input type="radio" name="target" value="vocals" checked><b>Gesang</b><span>BS‑RoFormer<br>beste Qualität</span></label>
@@ -9,7 +9,8 @@
<label class="target"><input type="radio" name="target" value="bass"><b>Bass</b><span>HTDemucs FT</span></label> <label class="target"><input type="radio" name="target" value="bass"><b>Bass</b><span>HTDemucs FT</span></label>
<label class="target"><input type="radio" name="target" value="guitar"><b>Gitarre</b><span>HTDemucs 6s<br>experimentell</span></label> <label class="target"><input type="radio" name="target" value="guitar"><b>Gitarre</b><span>HTDemucs 6s<br>experimentell</span></label>
<label class="target"><input type="radio" name="target" value="piano"><b>Piano</b><span>HTDemucs 6s<br>experimentell</span></label> <label class="target"><input type="radio" name="target" value="piano"><b>Piano</b><span>HTDemucs 6s<br>experimentell</span></label>
<label class="target"><input type="radio" name="target" value="other"><b>Sonstiges</b><span>Synths, Streicher etc.<br>gemischte Spur</span></label>
</div> </div>
<label class="drop" id="drop">Audio auswählen oder hier ablegen<input id="file" type="file" accept="audio/*"><div class="file" id="name">Noch keine Datei gewählt</div></label><button id="start" disabled>Ausgewählte Spur und Rest erzeugen</button><div class="status" id="status">Bereit.</div><div class="bar" id="bar"><div class="fill"></div></div><small>Alles läuft lokal auf Athena. Synthesizer, Streicher sowie elektrische und akustische Gitarre separat benötigen zusätzliche Spezialmodelle.</small></main><script> <label class="drop" id="drop">Audio auswählen oder hier ablegen<input id="file" type="file" accept="audio/*"><div class="file" id="name">Noch keine Datei gewählt</div></label><button id="start" disabled>Ausgewählte Spur und Rest erzeugen</button><div class="status" id="status">Bereit.</div><div class="bar" id="bar"><div class="fill"></div></div><small>Alles läuft lokal auf Athena. Synthesizer, Streicher sowie elektrische und akustische Gitarre separat benötigen zusätzliche Spezialmodelle.</small></main><script>
const file=document.querySelector('#file'),drop=document.querySelector('#drop'),name=document.querySelector('#name'),start=document.querySelector('#start'),status=document.querySelector('#status'),bar=document.querySelector('#bar');let selected;const names={vocals:'gesang',drums:'schlagzeug',bass:'bass',guitar:'gitarre',piano:'piano'};function choose(f){selected=f;name.textContent=f?`${f.name} · ${(f.size/1048576).toFixed(1)} MiB`:'Noch keine Datei gewählt';start.disabled=!f}file.onchange=()=>choose(file.files[0]);drop.ondragover=e=>{e.preventDefault();drop.classList.add('drag')};drop.ondragleave=()=>drop.classList.remove('drag');drop.ondrop=e=>{e.preventDefault();drop.classList.remove('drag');choose(e.dataTransfer.files[0])};start.onclick=async()=>{const target=document.querySelector('input[name=target]:checked').value;start.disabled=true;bar.classList.add('run');status.textContent='Modell löst die gewählte Spur heraus – das kann einige Minuten dauern …';let body=new FormData();body.append('file',selected);body.append('target',target);try{let r=await fetch('/v1/separate',{method:'POST',body});if(!r.ok)throw Error((await r.json()).detail||`HTTP ${r.status}`);let blob=await r.blob(),a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download=`athena-${names[target]}-und-rest.zip`;a.click();setTimeout(()=>URL.revokeObjectURL(a.href),5000);status.textContent='Fertig – ZIP mit der ausgewählten Spur und dem Rest wurde geladen.'}catch(e){status.textContent=`Fehler: ${e.message}`}finally{bar.classList.remove('run');start.disabled=false}}; const file=document.querySelector('#file'),drop=document.querySelector('#drop'),name=document.querySelector('#name'),start=document.querySelector('#start'),status=document.querySelector('#status'),bar=document.querySelector('#bar');let selected;const names={vocals:'gesang',drums:'schlagzeug',bass:'bass',guitar:'gitarre',piano:'piano',other:'sonstiges'};function choose(f){selected=f;name.textContent=f?`${f.name} · ${(f.size/1048576).toFixed(1)} MiB`:'Noch keine Datei gewählt';start.disabled=!f}file.onchange=()=>choose(file.files[0]);drop.ondragover=e=>{e.preventDefault();drop.classList.add('drag')};drop.ondragleave=()=>drop.classList.remove('drag');drop.ondrop=e=>{e.preventDefault();drop.classList.remove('drag');choose(e.dataTransfer.files[0])};start.onclick=async()=>{const target=document.querySelector('input[name=target]:checked').value;start.disabled=true;bar.classList.add('run');status.textContent='Modell löst die gewählte Spur heraus – das kann einige Minuten dauern …';let body=new FormData();body.append('file',selected);body.append('target',target);try{let r=await fetch('/v1/separate',{method:'POST',body});if(!r.ok)throw Error((await r.json()).detail||`HTTP ${r.status}`);let blob=await r.blob(),a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download=`athena-${names[target]}-und-rest.zip`;a.click();setTimeout(()=>URL.revokeObjectURL(a.href),5000);status.textContent='Fertig – ZIP mit der ausgewählten Spur und dem Rest wurde geladen.'}catch(e){status.textContent=`Fehler: ${e.message}`}finally{bar.classList.remove('run');start.disabled=false}};
</script></body></html> </script></body></html>