Offer isolated VoxCPM runtime installation from model setup

This commit is contained in:
Mikei386 committed 2026-10-02 11:55:25 +02:00
1 parent 1f0fc42344
commit aee31359b6
18 files changed
+168 -21

No files matched your search

+11 -2
View File
@@ -75,7 +75,7 @@ def validate(doc):
validate_profiles(settings['separator-profiles.json'])
validate_record(doc.get('credentials'))
runtimes=doc.get('runtimes')
if not isinstance(runtimes,dict) or set(runtimes)-{'llama','llama_builds','image','tts','enhancers','swarm_nodes','ltx_original','audio_cpp','separator'} or not {'llama','llama_builds','image','tts','enhancers','swarm_nodes'}<=set(runtimes):raise ValueError('Ungültiges Laufzeitrezept.')
if not isinstance(runtimes,dict) or set(runtimes)-{'llama','llama_builds','image','tts','enhancers','swarm_nodes','ltx_original','audio_cpp','separator','voxcpm'} or not {'llama','llama_builds','image','tts','enhancers','swarm_nodes'}<=set(runtimes):raise ValueError('Ungültiges Laufzeitrezept.')
if 'separator' in runtimes:
from separator_runtime import MODELS
value=runtimes['separator']
@@ -83,6 +83,7 @@ def validate(doc):
if 'sources' in value:
from separator_runtime import SOURCES
if value['sources']!={name:SOURCES[name] for name in value['models']}:raise ValueError('Audio-Separator-Quellen stimmen nicht mit dem geprüften Rezept überein.')
if 'voxcpm' in runtimes and type(runtimes['voxcpm']) is not bool:raise ValueError('Ungültige VoxCPM-Laufzeit.')
if 'audio_cpp' in runtimes and type(runtimes['audio_cpp']) is not bool:raise ValueError('Ungültige audio.cpp-Laufzeit.')
if 'ltx_original' in runtimes and type(runtimes['ltx_original']) is not bool:raise ValueError('Ungültige LTX-Laufzeit.')
if not isinstance(runtimes['llama_builds'],list) or len(runtimes['llama_builds'])>50 or any(not isinstance(b,dict) or set(b)!={'commit','backend'} or not re.fullmatch('[a-f0-9]{40}',b.get('commit','')) or b.get('backend') not in ('CUDA','CPU') for b in runtimes['llama_builds']):raise ValueError('Ungültige Buildrezepte.')
@@ -152,6 +153,8 @@ class Backup:
if getattr(s,'separator_runtime',None):
from separator_runtime import SOURCES
separator=s.separator_runtime.status();document['runtimes']['separator']=dict(installed=separator['installed'],models=[m['id'] for m in separator['models'] if m['installed']],sources={m['id']:SOURCES[m['id']] for m in separator['models'] if m['installed']});document['runtime_versions']['separator']=separator['version']
if getattr(s,'voxcpm_runtime',None):
document['runtimes']['voxcpm']=s.voxcpm_runtime.status()['installed'];document['runtime_versions']['voxcpm']=s.voxcpm_runtime.status()['version']
if document['runtimes']['audio_cpp']:
from audio_cpp_runtime import REVISION
document['runtime_versions']['audio_cpp']=REVISION
@@ -184,6 +187,9 @@ class Backup:
elif s.network.status().get('enabled') or s.network.status().get('mode')!='lan':blockers.append('Deck-Tunnel vor Netzwerk-Restore im bestätigten LAN-Modus deaktivieren.')
if doc['network']['mode']!='lan':warnings.append('Tunnelzugang wird mit Rückfallzeit aktiviert und muss über den Tunnel bestätigt werden.')
versions=doc.get('runtime_versions',{})
if versions.get('voxcpm'):
from voxcpm_runtime import VERSION as VOXCPM_VERSION
if versions['voxcpm']!=VOXCPM_VERSION:blockers.append('Backup verlangt eine andere VoxCPM-Version. Passende Deck-Version verwenden.')
if versions.get('separator'):
from separator_runtime import VERSION as SEPARATOR_VERSION
if versions['separator']!=SEPARATOR_VERSION:blockers.append('Backup verlangt eine andere Audio-Separator-Version.')
@@ -193,7 +199,7 @@ class Backup:
if versions.get('ltx_original'):
from ltx_original_runtime import DESKTOP_REV,LTX_REV
if versions['ltx_original']!=dict(desktop=DESKTOP_REV,inference=LTX_REV):blockers.append('Backup verlangt eine andere originale LTX-Version. Passende Deck-Version verwenden.')
if versions and {k:v for k,v in versions.items() if k not in ('ltx_original','audio_cpp','separator')}!=dict(image=dict(comfy=s.image_runtime.status()['comfy_revision'],gguf=s.image_runtime.status()['gguf_revision']),tts=s.tts_runtime.status()['revision']):blockers.append('Backup verlangt andere Bild-/TTS-Laufzeitversionen. Passende Deck-Version oder geprüftes Runtime-Upgrade verwenden.')
if versions and {k:v for k,v in versions.items() if k not in ('ltx_original','audio_cpp','separator','voxcpm')}!=dict(image=dict(comfy=s.image_runtime.status()['comfy_revision'],gguf=s.image_runtime.status()['gguf_revision']),tts=s.tts_runtime.status()['revision']):blockers.append('Backup verlangt andere Bild-/TTS-Laufzeitversionen. Passende Deck-Version oder geprüftes Runtime-Upgrade verwenden.')
for c in doc['services']:
if not c.get('registry') and not c.get('build_recipe'):warnings.append(c['name']+': Image nur lokal vorhanden; Registry-/Buildquelle fehlt.')
ports=s.endpoint.allowed_ports
@@ -246,6 +252,8 @@ class Backup:
self._phase('TTS-Laufzeit und Zusatzdateien installieren');s.tts_runtime.start();self._wait(s.tts_runtime.status)
if r.get('audio_cpp') and not s.audio_cpp_runtime.status()['installed']:
self._phase('audio.cpp-Laufzeit installieren');s.audio_cpp_runtime.start();self._wait(s.audio_cpp_runtime.status)
if r.get('voxcpm') and not s.voxcpm_runtime.status()['installed']:
self._phase('VoxCPM-Laufzeit installieren');s.voxcpm_runtime.start();self._wait(s.voxcpm_runtime.status)
if r.get('ltx_original') and not s.ltx_original_runtime.status()['installed']:
self._phase('Originale LTX-Laufzeit installieren');s.ltx_original_runtime.start();self._wait(s.ltx_original_runtime.status)
if r.get('separator',{}).get('installed'):
@@ -396,6 +404,7 @@ class Backup:
if getattr(self.server,'separator_runtime',None):self.server.separator_runtime.stop()
if getattr(self.server,'separator_tests',None):self.server.separator_tests.stop()
if getattr(self.server,'music',None):self.server.music.stop()
if getattr(self.server,'voxcpm_runtime',None):self.server.voxcpm_runtime.stop()
if getattr(self.server,'audio_cpp_runtime',None):self.server.audio_cpp_runtime.stop()
self.server.prompt_enhancer.stop()
return {'cancellation_requested':True}