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

+13 -3
View File
@@ -9,6 +9,7 @@ import secrets
from http.cookies import SimpleCookie, CookieError
from auth import CredentialStore, verify_password
from catalog import Catalog
from voxcpm_runtime import VoxCPMRuntime
from tts_runtime import TTSRuntime
from stt import STT,read_upload
from audio_policy import AudioPolicy
@@ -84,6 +85,8 @@ class Server(ThreadingHTTPServer):
self.image_tests.enhancer=self.prompt_enhancer
self.profiles.prompt_enhancer_ready=lambda task:bool(self.prompt_enhancer.installed(task))
self.profiles.image_runtime_ready=lambda:self.image_tests.status()["runtime_installed"]
self.voxcpm_runtime=VoxCPMRuntime(self.catalog.root.parent/'voxcpm-runtime',self.image_runtime)
self.profiles.voxcpm_runtime_ready=lambda:self.voxcpm_runtime.status()['installed']
self.tts_runtime=TTSRuntime(self.catalog.root.parent/'tts-runtime')
self.tts_tests=TTSTests(self.catalog.root.parent/'tts-tests',self.profiles,self.tts_runtime)
self.profiles.tts_blockers=self.tts_tests.blockers
@@ -308,7 +311,7 @@ class Handler(BaseHTTPRequestHandler):
'audio':self.server.tts_runtime.status().get('installed',False),
'video':video_runtime.status().get('installed',False),
'audio_cpp':self.server.audio_cpp_runtime.status()['installed'],
'music_worker':True,'separator':self.server.separator_runtime.status()['installed']}
'voxcpm':self.server.voxcpm_runtime.status()['installed'],'music_worker':True,'separator':self.server.separator_runtime.status()['installed']}
def execution_setup(self, model, profile=None, installed=None):
return execution_assess(model, self.execution_runtime_snapshot() if installed is None else installed, profile)
@@ -324,7 +327,7 @@ class Handler(BaseHTTPRequestHandler):
return self.respond({'error':'Anmeldung erforderlich.'},401)
if not self.authenticated() and self.path == '/':
return self.respond((ROOT/'login.html').read_bytes(), mime='text/html; charset=utf-8')
routes = {'/separator-ui.js':('separator-ui.js','text/javascript'),'/music-ui.js':('music-ui.js','text/javascript'),'/audio-cpp-ui.js':('audio-cpp-ui.js','text/javascript'),'/ltx-original-ui.js':('ltx-original-ui.js','text/javascript'),'/backup-ui.js':('backup-ui.js','text/javascript'),'/dashboard-ui.js':('dashboard-ui.js','text/javascript'),'/dashboard.css':('dashboard.css','text/css'),'/themes.css':('themes.css','text/css'),'/video-ui.js':('video-ui.js','text/javascript'),'/stt-ui.js':('stt-ui.js','text/javascript'),'/tts-ui.js':('tts-ui.js','text/javascript'),'/auto-test-ui.js':('auto-test-ui.js','text/javascript'),'/chat-test-ui.js':('chat-test-ui.js','text/javascript'),'/endpoint-ui.js':('endpoint-ui.js','text/javascript'),'/docker-ui.js': ('docker-ui.js','text/javascript'), '/': ('index.html', 'text/html; charset=utf-8'), '/app.js': ('app.js', 'text/javascript'), '/style.css': ('style.css', 'text/css'), '/network-ui.js': ('network-ui.js', 'text/javascript'), '/access-ui.js': ('access-ui.js', 'text/javascript'), '/studio.js': ('studio.js', 'text/javascript'), '/catalog-ui.js': ('catalog-ui.js','text/javascript'), '/runtime-ui.js': ('runtime-ui.js','text/javascript'), '/profiles-ui.js': ('profiles-ui.js','text/javascript'), '/image-test-ui.js': ('image-test-ui.js','text/javascript')}
routes = {'/voxcpm-ui.js':('voxcpm-ui.js','text/javascript'),'/separator-ui.js':('separator-ui.js','text/javascript'),'/music-ui.js':('music-ui.js','text/javascript'),'/audio-cpp-ui.js':('audio-cpp-ui.js','text/javascript'),'/ltx-original-ui.js':('ltx-original-ui.js','text/javascript'),'/backup-ui.js':('backup-ui.js','text/javascript'),'/dashboard-ui.js':('dashboard-ui.js','text/javascript'),'/dashboard.css':('dashboard.css','text/css'),'/themes.css':('themes.css','text/css'),'/video-ui.js':('video-ui.js','text/javascript'),'/stt-ui.js':('stt-ui.js','text/javascript'),'/tts-ui.js':('tts-ui.js','text/javascript'),'/auto-test-ui.js':('auto-test-ui.js','text/javascript'),'/chat-test-ui.js':('chat-test-ui.js','text/javascript'),'/endpoint-ui.js':('endpoint-ui.js','text/javascript'),'/docker-ui.js': ('docker-ui.js','text/javascript'), '/': ('index.html', 'text/html; charset=utf-8'), '/app.js': ('app.js', 'text/javascript'), '/style.css': ('style.css', 'text/css'), '/network-ui.js': ('network-ui.js', 'text/javascript'), '/access-ui.js': ('access-ui.js', 'text/javascript'), '/studio.js': ('studio.js', 'text/javascript'), '/catalog-ui.js': ('catalog-ui.js','text/javascript'), '/runtime-ui.js': ('runtime-ui.js','text/javascript'), '/profiles-ui.js': ('profiles-ui.js','text/javascript'), '/image-test-ui.js': ('image-test-ui.js','text/javascript')}
if self.path in routes:
name, mime = routes[self.path]
return self.respond((ROOT/name).read_bytes(), mime=mime)
@@ -347,6 +350,8 @@ class Handler(BaseHTTPRequestHandler):
if urlsplit(self.path).path == '/api/v1/music/audio':
try:return self.respond(self.server.music.audio(parse_qs(urlsplit(self.path).query).get('id',[''])[0]),mime='audio/wav')
except (OSError,ValueError):return self.respond({'error':'Musik nicht verfügbar.'},404)
if self.path == '/api/v1/voxcpm-runtime':return self.respond(self.server.voxcpm_runtime.status())
if self.path == '/api/v1/voxcpm-runtime/log':return self.respond(self.server.voxcpm_runtime.log())
if self.path == '/api/v1/separator-runtime':return self.respond(self.server.separator_runtime.status())
if self.path == '/api/v1/separator-runtime/log':return self.respond(self.server.separator_runtime.log())
if self.path == '/api/v1/separator-tests':return self.respond(self.server.separator_tests.status())
@@ -547,6 +552,11 @@ class Handler(BaseHTTPRequestHandler):
if self.path == '/api/v1/separator-profiles/save':
try:return self.respond(self.server.separator_tests.configure(self.read_json()))
except (ValueError,OSError) as exc:return self.respond({'error':str(exc)},400)
if self.path in ('/api/v1/voxcpm-runtime/install','/api/v1/voxcpm-runtime/cancel'):
try:
if self.read_json():raise ValueError('Keine Parameter erwartet.')
return self.respond(self.server.voxcpm_runtime.stop() if self.path.endswith('/cancel') else self.server.voxcpm_runtime.start())
except (ValueError,OSError) as exc:return self.respond({'error':str(exc)},400)
if self.path in ('/api/v1/separator-runtime/install','/api/v1/separator-runtime/cancel','/api/v1/separator-runtime/download'):
try:
data=self.read_json()
@@ -751,7 +761,7 @@ def main():
server.endpoint.close()
server.stt.stop()
server.tts_tests.stop()
server.tts_runtime.stop()
server.tts_runtime.stop();server.voxcpm_runtime.stop()
server.image_runtime.stop()
server.ltx_original_runtime.stop()
server.separator_tests.stop();server.separator_runtime.stop();server.music.stop();server.audio_cpp_runtime.stop()