Add separation profiles with activation and explicit GPU assignment
This commit is contained in:
1 parent
356abbeb9d
commit
932284a831
8 files changed
+82
-8
No files matched your search
+35
-3
@@ -1,14 +1,46 @@
|
||||
"""Bounded WAV tests with coordinated GPU ownership and disposable input."""
|
||||
import io,json,os,signal,subprocess,threading,time,uuid,wave
|
||||
import io,json,os,re,signal,subprocess,threading,time,uuid,wave
|
||||
from pathlib import Path
|
||||
from image_test import probe
|
||||
from separator_runtime import MODELS
|
||||
def validate_profiles(settings):
|
||||
if not isinstance(settings,dict) or set(settings)-set(MODELS):raise ValueError('Unbekanntes Audio-Trennprofil.')
|
||||
for value in settings.values():
|
||||
if not isinstance(value,dict) or set(value)!={'enabled','device'} or type(value['enabled']) is not bool or not isinstance(value['device'],str) or value['device']!='auto' and not re.fullmatch(r'GPU-[a-fA-F0-9-]{16,64}',value['device']):raise ValueError('Ungültiges Audio-Trennprofil.')
|
||||
return settings
|
||||
|
||||
class SeparatorTests:
|
||||
def __init__(self,root,runtime,scheduler):
|
||||
self.root=Path(root);self.runtime=runtime;self.scheduler=scheduler;self.lock=threading.RLock();self.job=None;self.process=None;self.cancel=threading.Event();self.thread=None
|
||||
def profiles(self):
|
||||
path=self.root.parent/'separator-profiles.json'
|
||||
settings=validate_profiles(json.loads(path.read_text())) if path.exists() else {}
|
||||
return {name:dict(settings.get(name,dict(enabled=True,device='auto'))) for name in MODELS}
|
||||
def configure(self,data):
|
||||
if not isinstance(data,dict) or set(data)!={'model','enabled','device'} or data['model'] not in MODELS:raise ValueError('Modell, Aktivierung und GPU erforderlich.')
|
||||
validate_profiles({data['model']:{k:data[k] for k in ('enabled','device')}})
|
||||
if data['device']!='auto' and not any(g['uuid']==data['device'] for g in probe()):raise ValueError('Gewählte GPU ist nicht vorhanden.')
|
||||
with self.lock:
|
||||
if self.job and self.job['state']=='running':raise ValueError('Zuerst den laufenden Trennauftrag beenden.')
|
||||
settings=self.profiles();settings[data['model']]={k:data[k] for k in ('enabled','device')}
|
||||
from auth import atomic_write
|
||||
atomic_write(self.root.parent/'separator-profiles.json',settings)
|
||||
return self.status()
|
||||
def status(self):
|
||||
with self.lock:return dict(job=dict(self.job) if self.job else None)
|
||||
try:devices=[dict(uuid=g['uuid'],name=g['name']) for g in probe()];hardware_error=None
|
||||
except (OSError,ValueError,subprocess.SubprocessError):devices=[];hardware_error='GPU-Erkennung derzeit nicht verfügbar.'
|
||||
with self.lock:return dict(job=dict(self.job) if self.job else None,profiles=self.profiles(),devices=devices,hardware_error=hardware_error)
|
||||
def select_gpu(self,model):
|
||||
settings=self.profiles()[model]
|
||||
if not settings['enabled']:raise ValueError('Dieses Audio-Trennprofil ist deaktiviert. Unter Profile aktivieren.')
|
||||
available=[g for g in probe() if not g['processes'] and g['free_mib']>4000]
|
||||
if settings['device']!='auto':
|
||||
gpu=next((g for g in available if g['uuid']==settings['device']),None)
|
||||
if not gpu:raise ValueError('Die gewählte GPU ist nicht ausreichend frei. GPU-Auswahl im Profil prüfen; kein stiller Wechsel.')
|
||||
return gpu
|
||||
return next((g for term in ('RTX 5080','RTX 3060','') for g in available if term in g['name']),None)
|
||||
def start(self,model,audio,target=None,full=False):
|
||||
if isinstance(model,str) and model in MODELS and not self.profiles()[model]['enabled']:raise ValueError('Dieses Audio-Trennprofil ist deaktiviert. Unter Profile aktivieren.')
|
||||
if full and self.scheduler.gpu_mode!='separator':raise ValueError('Bitte unter Steuerung Audio-Trennung starten.')
|
||||
targets={'vocals':'model_bs_roformer_ep_317_sdr_12.9755.ckpt','drums':'htdemucs_ft.yaml','bass':'htdemucs_ft.yaml','guitar':'htdemucs_6s.yaml','piano':'htdemucs_6s.yaml','other':'htdemucs_6s.yaml'}
|
||||
if target is not None and targets.get(target)!=model:raise ValueError('Zielspur und Modellpaket passen nicht zusammen.')
|
||||
@@ -27,7 +59,7 @@ class SeparatorTests:
|
||||
release=None;directory=self.root/self.job['id'];state='failed';phase='Trennung fehlgeschlagen.'
|
||||
try:
|
||||
release=self.scheduler.image_reservation(kind='separator')
|
||||
gpu=next((g for term in ('RTX 3060','RTX 5080') for g in probe() if term in g['name'] and not g['processes'] and g['free_mib']>4000),None)
|
||||
gpu=self.select_gpu(model)
|
||||
if not gpu:raise ValueError('Keine ausreichend freie GPU. Fremde Dienste werden nicht beendet.')
|
||||
directory.mkdir(mode=0o700);(directory/'input.wav').write_bytes(audio);diagnostics=(directory/'worker.tmp').open('wb')
|
||||
with self.lock:
|
||||
|
||||
Reference in new issue
Block a user