Remove Seed-VC after failed German quality test
This commit is contained in:
@@ -16,7 +16,7 @@ Bild- und Sprachausgabe. **Hermes und die Fach-MCPs laufen auf Unraid.**
|
|||||||
- Whisper.cpp `ggml-small` auf der CPU für lokale deutsche Spracherkennung
|
- Whisper.cpp `ggml-small` auf der CPU für lokale deutsche Spracherkennung
|
||||||
- Live-Dashboard mit 21 Tagen Detailhistorie auf Port 8099
|
- Live-Dashboard mit 21 Tagen Detailhistorie auf Port 8099
|
||||||
- Dashboard-Umschaltung zwischen LLM-Betrieb, ACE-Step-Musikstudio,
|
- Dashboard-Umschaltung zwischen LLM-Betrieb, ACE-Step-Musikstudio,
|
||||||
BS-RoFormer-Stimmtrennung, OmniVoice, X-VC, Seed-VC und Applio/RVC
|
BS-RoFormer-Stimmtrennung, OmniVoice, X-VC und Applio/RVC
|
||||||
- Portainer CE als optionale Container-Ansicht auf Port 9443
|
- Portainer CE als optionale Container-Ansicht auf Port 9443
|
||||||
- WireGuard-Gateway, Datenbackup und Athena-Operator
|
- WireGuard-Gateway, Datenbackup und Athena-Operator
|
||||||
- keine produktive Hermes-, OpenWebUI- oder portable Fach-MCP-Instanz
|
- keine produktive Hermes-, OpenWebUI- oder portable Fach-MCP-Instanz
|
||||||
@@ -127,12 +127,11 @@ Details, Installation, Prüfung und Rollback stehen in
|
|||||||
- Spuren trennen (BS-RoFormer + Demucs, 2/4/6 Stems): `http://192.168.1.212:8007`
|
- Spuren trennen (BS-RoFormer + Demucs, 2/4/6 Stems): `http://192.168.1.212:8007`
|
||||||
- Voice Studio (OmniVoice, Text zu Stimme): `http://192.168.1.212:8008`
|
- Voice Studio (OmniVoice, Text zu Stimme): `http://192.168.1.212:8008`
|
||||||
- Voice Changer (X-VC, Audio zu Audio; native 16 kHz plus optional restaurierte 44,1 kHz): `http://192.168.1.212:8009`
|
- Voice Changer (X-VC, Audio zu Audio; native 16 kHz plus optional restaurierte 44,1 kHz): `http://192.168.1.212:8009`
|
||||||
- Seed-VC (Zero-Shot Sprache/Gesang zu Referenzstimme): `http://192.168.1.212:8010`
|
|
||||||
- Applio (RVC-Inferenz, Modelle und Training): `http://192.168.1.212:8011`
|
- Applio (RVC-Inferenz, Modelle und Training): `http://192.168.1.212:8011`
|
||||||
|
|
||||||
Der Betriebsmodus lässt sich dort direkt umschalten. In Hermes funktionieren
|
Der Betriebsmodus lässt sich dort direkt umschalten. In Hermes funktionieren
|
||||||
außerdem `/athena music`, `/athena stems`, `/athena voice`,
|
außerdem `/athena music`, `/athena stems`, `/athena voice`,
|
||||||
`/athena voicechange`, `/athena seedvc`, `/athena applio`, `/athena llm` und `/athena status`; Details stehen in
|
`/athena voicechange`, `/athena applio`, `/athena llm` und `/athena status`; Details stehen in
|
||||||
[docs/OPERATING_MODES.md](docs/OPERATING_MODES.md).
|
[docs/OPERATING_MODES.md](docs/OPERATING_MODES.md).
|
||||||
|
|
||||||
Der Router stellt Sprache OpenAI-kompatibel bereit: Sprachausgabe über
|
Der Router stellt Sprache OpenAI-kompatibel bereit: Sprachausgabe über
|
||||||
|
|||||||
@@ -573,7 +573,6 @@ services:
|
|||||||
SEPARATOR_WORKER: bs-roformer
|
SEPARATOR_WORKER: bs-roformer
|
||||||
VOICE_WORKER: vevo2
|
VOICE_WORKER: vevo2
|
||||||
VOICE_CHANGE_WORKER: xvc
|
VOICE_CHANGE_WORKER: xvc
|
||||||
SEED_VC_WORKER: seed-vc
|
|
||||||
APPLIO_WORKER: applio
|
APPLIO_WORKER: applio
|
||||||
networks: [control]
|
networks: [control]
|
||||||
security_opt: ["no-new-privileges:true"]
|
security_opt: ["no-new-privileges:true"]
|
||||||
@@ -634,7 +633,6 @@ services:
|
|||||||
ENABLE_MUSIC_MODE: "true"
|
ENABLE_MUSIC_MODE: "true"
|
||||||
MUSIC_START_TIMEOUT: "600"
|
MUSIC_START_TIMEOUT: "600"
|
||||||
VOICE_CHANGE_START_TIMEOUT: "600"
|
VOICE_CHANGE_START_TIMEOUT: "600"
|
||||||
SEED_VC_START_TIMEOUT: "900"
|
|
||||||
APPLIO_START_TIMEOUT: "900"
|
APPLIO_START_TIMEOUT: "900"
|
||||||
STT_WORKER_URL: http://whisper:8084
|
STT_WORKER_URL: http://whisper:8084
|
||||||
STT_TIMEOUT: "300"
|
STT_TIMEOUT: "300"
|
||||||
@@ -869,7 +867,6 @@ services:
|
|||||||
SEPARATOR_UI_URL: "${SEPARATOR_UI_URL:-http://192.168.1.212:8007/}"
|
SEPARATOR_UI_URL: "${SEPARATOR_UI_URL:-http://192.168.1.212:8007/}"
|
||||||
VOICE_UI_URL: "${VOICE_UI_URL:-http://192.168.1.212:8008/}"
|
VOICE_UI_URL: "${VOICE_UI_URL:-http://192.168.1.212:8008/}"
|
||||||
VOICE_CHANGE_UI_URL: "${VOICE_CHANGE_UI_URL:-http://192.168.1.212:8009/}"
|
VOICE_CHANGE_UI_URL: "${VOICE_CHANGE_UI_URL:-http://192.168.1.212:8009/}"
|
||||||
SEED_VC_UI_URL: "${SEED_VC_UI_URL:-http://192.168.1.212:8010/}"
|
|
||||||
APPLIO_UI_URL: "${APPLIO_UI_URL:-http://192.168.1.212:8011/}"
|
APPLIO_UI_URL: "${APPLIO_UI_URL:-http://192.168.1.212:8011/}"
|
||||||
HOST_PROC: /host/proc
|
HOST_PROC: /host/proc
|
||||||
HOST_DATA: /host/data
|
HOST_DATA: /host/data
|
||||||
|
|||||||
@@ -70,13 +70,6 @@ class DashboardModeTests(unittest.TestCase):
|
|||||||
request = urlopen.call_args.args[0]
|
request = urlopen.call_args.args[0]
|
||||||
self.assertEqual(json.loads(request.data), {"mode": "voicechange"})
|
self.assertEqual(json.loads(request.data), {"mode": "voicechange"})
|
||||||
|
|
||||||
def test_seed_vc_mode_is_forwarded_to_router(self):
|
|
||||||
with patch.object(self.dashboard.urllib.request, "urlopen", return_value=_Response()) as urlopen:
|
|
||||||
status, body = self.dashboard.change_mode("seedvc")
|
|
||||||
self.assertEqual(status, 202)
|
|
||||||
self.assertEqual(body, {"status": "accepted"})
|
|
||||||
self.assertEqual(json.loads(urlopen.call_args.args[0].data), {"mode": "seedvc"})
|
|
||||||
|
|
||||||
def test_applio_mode_is_forwarded_to_router(self):
|
def test_applio_mode_is_forwarded_to_router(self):
|
||||||
with patch.object(self.dashboard.urllib.request, "urlopen", return_value=_Response()) as urlopen:
|
with patch.object(self.dashboard.urllib.request, "urlopen", return_value=_Response()) as urlopen:
|
||||||
status, body = self.dashboard.change_mode("applio")
|
status, body = self.dashboard.change_mode("applio")
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ nicht automatisch ein ungenutzter Rest.
|
|||||||
| `mike-ai-profile-controller` | kein Modell | Startet und stoppt ausschließlich freigegebene Modellprofile und Spezialworker in einer sicheren Reihenfolge. |
|
| `mike-ai-profile-controller` | kein Modell | Startet und stoppt ausschließlich freigegebene Modellprofile und Spezialworker in einer sicheren Reihenfolge. |
|
||||||
| `mike-ai-qwen3-tts` | `Qwen/Qwen3-TTS-12Hz-1.7B-Base`, Stimme Serena | Hochwertige deutsche Sprachausgabe auf der RTX 3060 im LLM-Betrieb. |
|
| `mike-ai-qwen3-tts` | `Qwen/Qwen3-TTS-12Hz-1.7B-Base`, Stimme Serena | Hochwertige deutsche Sprachausgabe auf der RTX 3060 im LLM-Betrieb. |
|
||||||
| `mike-ai-router` | kein eigenes Modell | Einzige OpenAI-kompatible Modelladresse; koordiniert Profile, Bildaufträge, Sprache und Betriebsarten. |
|
| `mike-ai-router` | kein eigenes Modell | Einzige OpenAI-kompatible Modelladresse; koordiniert Profile, Bildaufträge, Sprache und Betriebsarten. |
|
||||||
| `mike-ai-seed-vc-studio` | Seed-VC V1; Gewichte werden beim ersten Modusstart vollständig geladen | Zero-Shot-Sprach- und Gesangswandlung anhand einer Referenzaufnahme auf der RTX 5080. Der Dienst gilt erst nach geladenen Teilmodellen als bereit; Gewichte bleiben persistent. |
|
|
||||||
| `mike-ai-stem-separator` | BS-RoFormer Viperx 1297, `htdemucs_ft`, `htdemucs_6s`, `MossFormer2_SE_48K` | Trennt Gesang, Instrumente oder Sprache/Hintergrundgeräusche im exklusiven Separationsmodus. |
|
| `mike-ai-stem-separator` | BS-RoFormer Viperx 1297, `htdemucs_ft`, `htdemucs_6s`, `MossFormer2_SE_48K` | Trennt Gesang, Instrumente oder Sprache/Hintergrundgeräusche im exklusiven Separationsmodus. |
|
||||||
| `mike-ai-tts-gateway` | kein eigenes Modell | Normalisiert Text, leitet TTS an Qwen3-TTS weiter und fällt bei Bedarf auf Piper zurück. |
|
| `mike-ai-tts-gateway` | kein eigenes Modell | Normalisiert Text, leitet TTS an Qwen3-TTS weiter und fällt bei Bedarf auf Piper zurück. |
|
||||||
| `mike-ai-voice-studio` | `k2-fsa/OmniVoice` 0.2.1 mit Whisper-ASR | Erzeugt Text-to-Speech mit einer Referenzstimme; kein Audio-to-Audio-Voice-Changer. |
|
| `mike-ai-voice-studio` | `k2-fsa/OmniVoice` 0.2.1 mit Whisper-ASR | Erzeugt Text-to-Speech mit einer Referenzstimme; kein Audio-to-Audio-Voice-Changer. |
|
||||||
|
|||||||
+3
-13
@@ -1,6 +1,6 @@
|
|||||||
# Athena-Betriebsmodi
|
# Athena-Betriebsmodi
|
||||||
|
|
||||||
Athena besitzt sieben gegenseitig exklusive Betriebsmodi:
|
Athena besitzt sechs gegenseitig exklusive Betriebsmodi:
|
||||||
|
|
||||||
- `llm`: ein llama.cpp-Profil und Qwen3-TTS laufen; Spezialdienste sind gestoppt.
|
- `llm`: ein llama.cpp-Profil und Qwen3-TTS laufen; Spezialdienste sind gestoppt.
|
||||||
- `music`: ACE-Step 1.5 XL-SFT läuft; alle LLM-, Bild-, TTS- und Separator-Worker sind gestoppt.
|
- `music`: ACE-Step 1.5 XL-SFT läuft; alle LLM-, Bild-, TTS- und Separator-Worker sind gestoppt.
|
||||||
@@ -11,8 +11,6 @@ Athena besitzt sieben gegenseitig exklusive Betriebsmodi:
|
|||||||
- `voicechange`: X-VC überträgt eine vorhandene Sprachaufnahme auf eine
|
- `voicechange`: X-VC überträgt eine vorhandene Sprachaufnahme auf eine
|
||||||
Referenzstimme und bewahrt dabei Inhalt und Timing. Alle anderen
|
Referenzstimme und bewahrt dabei Inhalt und Timing. Alle anderen
|
||||||
GPU-Dienste sind gestoppt.
|
GPU-Dienste sind gestoppt.
|
||||||
- `seedvc`: Seed-VC V1 wandelt Sprache oder Gesang ohne Training anhand einer
|
|
||||||
Referenzaufnahme um. Alle anderen GPU-Dienste sind gestoppt.
|
|
||||||
- `applio`: Applio stellt RVC-Inferenz, Modellverwaltung und Training bereit.
|
- `applio`: Applio stellt RVC-Inferenz, Modellverwaltung und Training bereit.
|
||||||
Alle anderen GPU-Dienste sind gestoppt.
|
Alle anderen GPU-Dienste sind gestoppt.
|
||||||
|
|
||||||
@@ -23,7 +21,7 @@ wird persistent gespeichert und beim Verlassen eines Spezialmodus wieder geladen
|
|||||||
## Bedienung
|
## Bedienung
|
||||||
|
|
||||||
Im Athena-Dashboard stehen **LLM-Betrieb**, **Musikstudio**, **Audio trennen**,
|
Im Athena-Dashboard stehen **LLM-Betrieb**, **Musikstudio**, **Audio trennen**,
|
||||||
**Voice Studio**, **X-VC**, **Seed-VC** und **Applio / RVC** bereit. Im Musikmodus werden zwei Oberflächen angeboten:
|
**Voice Studio**, **X-VC** und **Applio / RVC** bereit. Im Musikmodus werden zwei Oberflächen angeboten:
|
||||||
|
|
||||||
- **Original UI · stabil** öffnet die zum laufenden ACE-Step-Image gehörende
|
- **Original UI · stabil** öffnet die zum laufenden ACE-Step-Image gehörende
|
||||||
Gradio-Oberfläche. Sie ist für Cover, Remix und erweiterte Workflows der
|
Gradio-Oberfläche. Sie ist für Cover, Remix und erweiterte Workflows der
|
||||||
@@ -75,11 +73,6 @@ des verwendeten GLM-4-Voice-Tokenizers ist Chinesisch und Englisch; Deutsch
|
|||||||
bleibt deshalb bis zur Hörabnahme ein Qualitätstest und kein zugesagter
|
bleibt deshalb bis zur Hörabnahme ein Qualitätstest und kein zugesagter
|
||||||
Produktionspfad. X-VC läuft ausschließlich auf der RTX 5080.
|
Produktionspfad. X-VC läuft ausschließlich auf der RTX 5080.
|
||||||
|
|
||||||
Seed-VC ist unter `http://192.168.1.212:8010` erreichbar. Die gepinnte V1-
|
|
||||||
Oberfläche unterstützt Zero-Shot-Sprach- und Gesangswandlung. Der Code ist auf
|
|
||||||
den archivierten Upstream-Commit `51383efd921027683c89e5348211d93ff12ac2a8`
|
|
||||||
fixiert; Gewichte werden beim ersten Auftrag persistent zwischengespeichert.
|
|
||||||
|
|
||||||
Applio ist unter `http://192.168.1.212:8011` erreichbar. Der RVC-Pfad besitzt
|
Applio ist unter `http://192.168.1.212:8011` erreichbar. Der RVC-Pfad besitzt
|
||||||
eine eigene Modellbibliothek, Inferenz und Training. Hochwertige Inferenz
|
eine eigene Modellbibliothek, Inferenz und Training. Hochwertige Inferenz
|
||||||
benötigt zwingend ein zuvor importiertes oder trainiertes RVC-Stimmenmodell
|
benötigt zwingend ein zuvor importiertes oder trainiertes RVC-Stimmenmodell
|
||||||
@@ -95,7 +88,6 @@ Router lokal beantwortet, auch wenn gerade kein LLM geladen ist:
|
|||||||
/athena stems
|
/athena stems
|
||||||
/athena voice
|
/athena voice
|
||||||
/athena voicechange
|
/athena voicechange
|
||||||
/athena seedvc
|
|
||||||
/athena applio
|
/athena applio
|
||||||
/athena llm
|
/athena llm
|
||||||
/athena status
|
/athena status
|
||||||
@@ -109,7 +101,6 @@ POST /mode {"mode":"music"}
|
|||||||
POST /mode {"mode":"separation"}
|
POST /mode {"mode":"separation"}
|
||||||
POST /mode {"mode":"voice"}
|
POST /mode {"mode":"voice"}
|
||||||
POST /mode {"mode":"voicechange"}
|
POST /mode {"mode":"voicechange"}
|
||||||
POST /mode {"mode":"seedvc"}
|
|
||||||
POST /mode {"mode":"applio"}
|
POST /mode {"mode":"applio"}
|
||||||
POST /mode {"mode":"llm"}
|
POST /mode {"mode":"llm"}
|
||||||
```
|
```
|
||||||
@@ -119,8 +110,7 @@ Der Wechsel läuft asynchron. Fortschritt und Fehler stehen unter `mode` in
|
|||||||
`com.mike-ai.music-worker=acestep` beziehungsweise
|
`com.mike-ai.music-worker=acestep` beziehungsweise
|
||||||
`com.mike-ai.stem-separator=bs-roformer` oder
|
`com.mike-ai.stem-separator=bs-roformer` oder
|
||||||
`com.mike-ai.voice-worker=vevo2` beziehungsweise
|
`com.mike-ai.voice-worker=vevo2` beziehungsweise
|
||||||
`com.mike-ai.voice-change-worker=xvc`,
|
`com.mike-ai.voice-change-worker=xvc` oder
|
||||||
`com.mike-ai.seed-vc-worker=seed-vc` oder
|
|
||||||
`com.mike-ai.applio-worker=applio` markierten Container; freie
|
`com.mike-ai.applio-worker=applio` markierten Container; freie
|
||||||
Container- oder Docker-Befehle werden nicht entgegengenommen.
|
Container- oder Docker-Befehle werden nicht entgegengenommen.
|
||||||
|
|
||||||
|
|||||||
@@ -61,8 +61,7 @@ Titelgenerierung und Kontextkompression in Hermes.
|
|||||||
| 09.09.2026 | `k2-fsa/OmniVoice` 0.2.1 | Offizielle Gradio-UI auf RTX 5080 gestartet; Modell plus Whisper-ASR belegen rund 3,7 GiB VRAM. `omnivoice-triton` 0.1.0 ist kompatibel im Image vorhanden, für den ersten Hörtest aber bewusst noch nicht aktiviert | **technischer Starttest bestanden**, Hörabnahme und Basis-vs.-Triton-Messung offen; Gewichte CC BY-NC und daher nur nichtkommerziell einsetzen |
|
| 09.09.2026 | `k2-fsa/OmniVoice` 0.2.1 | Offizielle Gradio-UI auf RTX 5080 gestartet; Modell plus Whisper-ASR belegen rund 3,7 GiB VRAM. `omnivoice-triton` 0.1.0 ist kompatibel im Image vorhanden, für den ersten Hörtest aber bewusst noch nicht aktiviert | **technischer Starttest bestanden**, Hörabnahme und Basis-vs.-Triton-Messung offen; Gewichte CC BY-NC und daher nur nichtkommerziell einsetzen |
|
||||||
| 09.09.2026 | `chenxie95/X-VC`, Code `49df8c591eafc48b096e466d96f9839f9c0dd739`, UI-Basis `d761cd6421e85376b2656dfefd8471d7f35a42be` | Offizielles Beispiel Ende-zu-Ende gewandelt: 5,20 s Audio in 1,07 s (RTF 0,21), gültiges 16-kHz-Mono-PCM-WAV; Modell belegt rund 2,9 GiB auf der RTX 5080. GLM-4-Voice-Tokenizer dokumentiert Chinesisch und Englisch | **technischer Start- und Konvertierungstest bestanden**; deutsche Hörabnahme offen |
|
| 09.09.2026 | `chenxie95/X-VC`, Code `49df8c591eafc48b096e466d96f9839f9c0dd739`, UI-Basis `d761cd6421e85376b2656dfefd8471d7f35a42be` | Offizielles Beispiel Ende-zu-Ende gewandelt: 5,20 s Audio in 1,07 s (RTF 0,21), gültiges 16-kHz-Mono-PCM-WAV; Modell belegt rund 2,9 GiB auf der RTX 5080. GLM-4-Voice-Tokenizer dokumentiert Chinesisch und Englisch | **technischer Start- und Konvertierungstest bestanden**; deutsche Hörabnahme offen |
|
||||||
| 09.09.2026 | Resemble Enhance 0.0.1, Modellrevision `4e3510ce4a8391159f665903544c5150bee7b2cb` | 14,56 s native X-VC-Ausgabe bei 16 kHz wurden auf der RTX 5080 in 3,55 s zu 44,1-kHz-PCM-WAV restauriert. 3,27 % der gemessenen Signalenergie lagen danach oberhalb 8 kHz; damit ist der Pfad keine bloße Neuabtastung. Wegen der alten Upstream-Pins läuft die reine Inferenz mit NumPy 1.26.4/SciPy 1.11.4 auf dem bestehenden Torch-2.8/CUDA-12.8-Unterbau | **technisch produktiv als optionaler A/B-Pfad**; Hörabnahme entscheidet, ob die rekonstruierten Höhen subjektiv besser oder künstlicher klingen |
|
| 09.09.2026 | Resemble Enhance 0.0.1, Modellrevision `4e3510ce4a8391159f665903544c5150bee7b2cb` | 14,56 s native X-VC-Ausgabe bei 16 kHz wurden auf der RTX 5080 in 3,55 s zu 44,1-kHz-PCM-WAV restauriert. 3,27 % der gemessenen Signalenergie lagen danach oberhalb 8 kHz; damit ist der Pfad keine bloße Neuabtastung. Wegen der alten Upstream-Pins läuft die reine Inferenz mit NumPy 1.26.4/SciPy 1.11.4 auf dem bestehenden Torch-2.8/CUDA-12.8-Unterbau | **technisch produktiv als optionaler A/B-Pfad**; Hörabnahme entscheidet, ob die rekonstruierten Höhen subjektiv besser oder künstlicher klingen |
|
||||||
| 09.09.2026 | `Plachtaa/seed-vc` V1, Code `51383efd921027683c89e5348211d93ff12ac2a8` | Gepinntes CUDA-12.8-/Torch-2.7.1-Image auf RTX 5080 gestartet; offizielle Gradio-Oberfläche und Healthcheck antworten. Gewichte folgen beim ersten echten Auftrag in den persistenten Hugging-Face-Cache | **technischer Starttest bestanden**; Konvertierungs- und Hörtest offen |
|
| 09.09.2026 | `Plachtaa/seed-vc` V1, Code `51383efd921027683c89e5348211d93ff12ac2a8` | Technisch vollständig lauffähig: gepinntes CUDA-Image, persistente Gewichte und reale WAV-Konvertierung mit etwa 3,6 GiB VRAM. Im deutschen Hörtest erhielt die Ausgabe jedoch einen deutlich chinesischen Akzent | **qualitativ verworfen und vollständig entfernt**; nicht erneut für deutsche Sprachwandlung einplanen |
|
||||||
| 09.09.2026 | Seed-VC V1, Code `51383efd921027683c89e5348211d93ff12ac2a8` | Sämtliche V1-Teilmodelle werden nun vor Freigabe der Oberfläche geladen und persistent gespeichert. Reale Beispielwandlung mit 10 Diffusionsschritten auf der RTX 5080 abgeschlossen; vollständige WAV erzeugt, etwa 3,6 GiB VRAM belegt | **technischer Start-, Persistenz- und Konvertierungstest bestanden**; der erste Start benötigt wegen der Downloads mehrere Minuten, spätere Starts verwenden den Cache |
|
|
||||||
| 09.09.2026 | `IAHispano/Applio`, Code `7fa68ec2166ab1331c539704159fa14901e94e5a` | Gepinntes CUDA-12.8-fähiges Image auf RTX 5080 gestartet; vollständige Applio/RVC-Oberfläche antwortet und CUDA ist verfügbar. Rund 1,8 GiB Basisgewichte und die Konfiguration wurden persistent ausgelagert. Es ist kein Zielstimmenmodell installiert; Applio kann aus einer Referenzaufnahme allein kein Modell ableiten | **technischer Start- und Persistenztest bestanden**; Konvertierung erst nach Import oder Training einer `.pth`-Stimme möglich |
|
| 09.09.2026 | `IAHispano/Applio`, Code `7fa68ec2166ab1331c539704159fa14901e94e5a` | Gepinntes CUDA-12.8-fähiges Image auf RTX 5080 gestartet; vollständige Applio/RVC-Oberfläche antwortet und CUDA ist verfügbar. Rund 1,8 GiB Basisgewichte und die Konfiguration wurden persistent ausgelagert. Es ist kein Zielstimmenmodell installiert; Applio kann aus einer Referenzaufnahme allein kein Modell ableiten | **technischer Start- und Persistenztest bestanden**; Konvertierung erst nach Import oder Training einer `.pth`-Stimme möglich |
|
||||||
|
|
||||||
## Musikgenerierung
|
## Musikgenerierung
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
FROM nvidia/cuda:12.8.1-cudnn-runtime-ubuntu22.04
|
|
||||||
|
|
||||||
ARG SEED_VC_COMMIT=51383efd921027683c89e5348211d93ff12ac2a8
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive \
|
|
||||||
PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
|
||||||
HF_HOME=/models/huggingface \
|
|
||||||
PYTHONUNBUFFERED=1
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
||||||
build-essential ca-certificates curl ffmpeg git libsndfile1 python3 python3-dev python3-pip \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
RUN git clone https://github.com/Plachtaa/seed-vc.git . \
|
|
||||||
&& git checkout "$SEED_VC_COMMIT" \
|
|
||||||
&& sed -i '/^torch\($\|[= <>=]\)/d;/^torchvision\($\|[= <>=]\)/d;/^torchaudio\($\|[= <>=]\)/d' requirements.txt \
|
|
||||||
&& python3 -m pip install --no-cache-dir \
|
|
||||||
torch==2.7.1 torchvision==0.22.1 torchaudio==2.7.1 \
|
|
||||||
--index-url https://download.pytorch.org/whl/cu128 \
|
|
||||||
&& python3 -m pip install --no-cache-dir -r requirements.txt \
|
|
||||||
&& sed -i 's/demo\.launch()/demo.launch(server_name="0.0.0.0", server_port=7860)/' app.py \
|
|
||||||
&& sed -i '/if args.enable_v1:/a\ print("Loading V1 models...", flush=True)\n from seed_vc_wrapper import SeedVCWrapper\n vc_wrapper_v1 = SeedVCWrapper()\n print("V1 models ready.", flush=True)' app.py
|
|
||||||
|
|
||||||
EXPOSE 7860
|
|
||||||
CMD ["python3", "app.py", "--enable-v1"]
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# Seed-VC Studio
|
|
||||||
|
|
||||||
Reproduzierbarer, experimenteller Seed-VC-v2-Worker mit der offiziellen
|
|
||||||
Gradio-Oberfläche. Der Build ist auf Upstream-Commit
|
|
||||||
`51383efd921027683c89e5348211d93ff12ac2a8` festgeschrieben.
|
|
||||||
|
|
||||||
- Dashboard-Modus: `Seed-VC`
|
|
||||||
- WireGuard-URL: `http://192.168.1.212:8010/`
|
|
||||||
- GPU: RTX 5080, exklusiv zu LLM, Musik- und anderen Voice-Modi
|
|
||||||
- Persistenz: Hugging-Face-Cache unter `/data/huggingface`
|
|
||||||
|
|
||||||
Das Image enthält den Programmcode. Beim Moduswechsel werden sämtliche
|
|
||||||
V1-Teilmodelle geladen, bevor der Healthcheck den Dienst als bereit meldet. Die
|
|
||||||
benötigten Modellgewichte bleiben unter `/data/voice/seed-vc/checkpoints`
|
|
||||||
erhalten; dadurch blockiert nicht mehr der erste Konvertierungsauftrag scheinbar
|
|
||||||
ohne Fortschritt.
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
services:
|
|
||||||
seed-vc-studio:
|
|
||||||
build: .
|
|
||||||
image: mike-ai/seed-vc-studio:51383efd
|
|
||||||
container_name: mike-ai-seed-vc-studio
|
|
||||||
restart: "no"
|
|
||||||
labels:
|
|
||||||
com.mike-ai.seed-vc-worker: seed-vc
|
|
||||||
environment:
|
|
||||||
NVIDIA_VISIBLE_DEVICES: ${VOICE_GPU_UUID:?set VOICE_GPU_UUID to the RTX 5080 UUID}
|
|
||||||
NVIDIA_DRIVER_CAPABILITIES: compute,utility
|
|
||||||
HF_HOME: /models/huggingface
|
|
||||||
PYTORCH_CUDA_ALLOC_CONF: expandable_segments:True
|
|
||||||
ports:
|
|
||||||
- "127.0.0.1:8010:7860"
|
|
||||||
volumes:
|
|
||||||
- /data/voice/seed-vc/huggingface:/models/huggingface
|
|
||||||
- /data/voice/seed-vc/checkpoints:/app/checkpoints
|
|
||||||
- /data/voice/seed-vc/output:/app/results
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:7860/ >/dev/null"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 3s
|
|
||||||
start_period: 900s
|
|
||||||
retries: 3
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
device_ids: ["${VOICE_GPU_UUID:?set VOICE_GPU_UUID to the RTX 5080 UUID}"]
|
|
||||||
capabilities: [gpu]
|
|
||||||
networks:
|
|
||||||
frontend:
|
|
||||||
aliases: [seed-vc-studio]
|
|
||||||
|
|
||||||
networks:
|
|
||||||
frontend:
|
|
||||||
name: mike-ai_frontend
|
|
||||||
external: true
|
|
||||||
@@ -36,8 +36,6 @@ VOICE_LABEL_KEY = "com.mike-ai.voice-worker"
|
|||||||
VOICE_WORKER = os.environ.get("VOICE_WORKER", "").strip()
|
VOICE_WORKER = os.environ.get("VOICE_WORKER", "").strip()
|
||||||
VOICE_CHANGE_LABEL_KEY = "com.mike-ai.voice-change-worker"
|
VOICE_CHANGE_LABEL_KEY = "com.mike-ai.voice-change-worker"
|
||||||
VOICE_CHANGE_WORKER = os.environ.get("VOICE_CHANGE_WORKER", "").strip()
|
VOICE_CHANGE_WORKER = os.environ.get("VOICE_CHANGE_WORKER", "").strip()
|
||||||
SEED_VC_LABEL_KEY = "com.mike-ai.seed-vc-worker"
|
|
||||||
SEED_VC_WORKER = os.environ.get("SEED_VC_WORKER", "").strip()
|
|
||||||
APPLIO_LABEL_KEY = "com.mike-ai.applio-worker"
|
APPLIO_LABEL_KEY = "com.mike-ai.applio-worker"
|
||||||
APPLIO_WORKER = os.environ.get("APPLIO_WORKER", "").strip()
|
APPLIO_WORKER = os.environ.get("APPLIO_WORKER", "").strip()
|
||||||
LOCK = threading.Lock()
|
LOCK = threading.Lock()
|
||||||
@@ -152,17 +150,6 @@ def voice_change_container() -> dict:
|
|||||||
return matches[0]
|
return matches[0]
|
||||||
|
|
||||||
|
|
||||||
def seed_vc_container() -> dict:
|
|
||||||
if not SEED_VC_WORKER:
|
|
||||||
raise RuntimeError("Seed-VC worker is not configured")
|
|
||||||
matches = [item for item in labelled_containers(SEED_VC_LABEL_KEY)
|
|
||||||
if item.get("Labels", {}).get(SEED_VC_LABEL_KEY) == SEED_VC_WORKER]
|
|
||||||
if len(matches) != 1:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"expected exactly one Seed-VC worker {SEED_VC_WORKER!r}, found {len(matches)}")
|
|
||||||
return matches[0]
|
|
||||||
|
|
||||||
|
|
||||||
def applio_container() -> dict:
|
def applio_container() -> dict:
|
||||||
if not APPLIO_WORKER:
|
if not APPLIO_WORKER:
|
||||||
raise RuntimeError("Applio worker is not configured")
|
raise RuntimeError("Applio worker is not configured")
|
||||||
@@ -194,11 +181,6 @@ def stop_voice_change_if_configured() -> None:
|
|||||||
stop_container(voice_change_container(), timeout=30)
|
stop_container(voice_change_container(), timeout=30)
|
||||||
|
|
||||||
|
|
||||||
def stop_seed_vc_if_configured() -> None:
|
|
||||||
if SEED_VC_WORKER:
|
|
||||||
stop_container(seed_vc_container(), timeout=30)
|
|
||||||
|
|
||||||
|
|
||||||
def stop_applio_if_configured() -> None:
|
def stop_applio_if_configured() -> None:
|
||||||
if APPLIO_WORKER:
|
if APPLIO_WORKER:
|
||||||
stop_container(applio_container(), timeout=30)
|
stop_container(applio_container(), timeout=30)
|
||||||
@@ -209,8 +191,6 @@ def stop_voice_tools(except_kind: str | None = None) -> None:
|
|||||||
stop_voice_if_configured()
|
stop_voice_if_configured()
|
||||||
if except_kind != "voicechange":
|
if except_kind != "voicechange":
|
||||||
stop_voice_change_if_configured()
|
stop_voice_change_if_configured()
|
||||||
if except_kind != "seedvc":
|
|
||||||
stop_seed_vc_if_configured()
|
|
||||||
if except_kind != "applio":
|
if except_kind != "applio":
|
||||||
stop_applio_if_configured()
|
stop_applio_if_configured()
|
||||||
|
|
||||||
@@ -348,26 +328,6 @@ def set_voice_change_worker(running: bool) -> dict:
|
|||||||
"state": "running" if running else "stopped"}
|
"state": "running" if running else "stopped"}
|
||||||
|
|
||||||
|
|
||||||
def set_seed_vc_worker(running: bool) -> dict:
|
|
||||||
"""Start Seed-VC exclusively, or stop it before another mode is loaded."""
|
|
||||||
with LOCK:
|
|
||||||
item = seed_vc_container()
|
|
||||||
if running:
|
|
||||||
for profile_item in containers().values():
|
|
||||||
stop_container(profile_item)
|
|
||||||
for worker in image_containers():
|
|
||||||
stop_container(worker, timeout=20)
|
|
||||||
stop_container(tts_container(), timeout=30)
|
|
||||||
stop_music_if_configured()
|
|
||||||
stop_separator_if_configured()
|
|
||||||
stop_voice_tools("seedvc")
|
|
||||||
start_container(item)
|
|
||||||
else:
|
|
||||||
stop_container(item, timeout=30)
|
|
||||||
return {"seed_vc_worker": SEED_VC_WORKER,
|
|
||||||
"state": "running" if running else "stopped"}
|
|
||||||
|
|
||||||
|
|
||||||
def set_applio_worker(running: bool) -> dict:
|
def set_applio_worker(running: bool) -> dict:
|
||||||
"""Start Applio exclusively, or stop it before another mode is loaded."""
|
"""Start Applio exclusively, or stop it before another mode is loaded."""
|
||||||
with LOCK:
|
with LOCK:
|
||||||
@@ -498,13 +458,6 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
"unhealthy" if "(unhealthy)" in voice_change_status else
|
"unhealthy" if "(unhealthy)" in voice_change_status else
|
||||||
"starting" if voice_change.get("State") == "running" else
|
"starting" if voice_change.get("State") == "running" else
|
||||||
"stopped")
|
"stopped")
|
||||||
seed_vc = seed_vc_container() if SEED_VC_WORKER else {}
|
|
||||||
seed_vc_status = seed_vc.get("Status", "")
|
|
||||||
seed_vc_health = ("disabled" if not SEED_VC_WORKER else
|
|
||||||
"healthy" if "(healthy)" in seed_vc_status else
|
|
||||||
"unhealthy" if "(unhealthy)" in seed_vc_status else
|
|
||||||
"starting" if seed_vc.get("State") == "running" else
|
|
||||||
"stopped")
|
|
||||||
applio = applio_container() if APPLIO_WORKER else {}
|
applio = applio_container() if APPLIO_WORKER else {}
|
||||||
applio_status = applio.get("Status", "")
|
applio_status = applio.get("Status", "")
|
||||||
applio_health = ("disabled" if not APPLIO_WORKER else
|
applio_health = ("disabled" if not APPLIO_WORKER else
|
||||||
@@ -521,8 +474,6 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
"voice_health": voice_health,
|
"voice_health": voice_health,
|
||||||
"voice_change_worker": voice_change.get("State", "disabled"),
|
"voice_change_worker": voice_change.get("State", "disabled"),
|
||||||
"voice_change_health": voice_change_health,
|
"voice_change_health": voice_change_health,
|
||||||
"seed_vc_worker": seed_vc.get("State", "disabled"),
|
|
||||||
"seed_vc_health": seed_vc_health,
|
|
||||||
"applio_worker": applio.get("State", "disabled"),
|
"applio_worker": applio.get("State", "disabled"),
|
||||||
"applio_health": applio_health,
|
"applio_health": applio_health,
|
||||||
"profiles": {name: items.get(name, {}).get(
|
"profiles": {name: items.get(name, {}).get(
|
||||||
@@ -570,13 +521,6 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
log.exception("voice-change worker transition failed")
|
log.exception("voice-change worker transition failed")
|
||||||
self.reply(503, {"error": str(exc)})
|
self.reply(503, {"error": str(exc)})
|
||||||
return
|
return
|
||||||
if self.path in {"/workers/seed-vc/start", "/workers/seed-vc/stop"}:
|
|
||||||
try:
|
|
||||||
self.reply(200, set_seed_vc_worker(self.path.endswith("/start")))
|
|
||||||
except Exception as exc:
|
|
||||||
log.exception("Seed-VC worker transition failed")
|
|
||||||
self.reply(503, {"error": str(exc)})
|
|
||||||
return
|
|
||||||
if self.path in {"/workers/applio/start", "/workers/applio/stop"}:
|
if self.path in {"/workers/applio/start", "/workers/applio/stop"}:
|
||||||
try:
|
try:
|
||||||
self.reply(200, set_applio_worker(self.path.endswith("/start")))
|
self.reply(200, set_applio_worker(self.path.endswith("/start")))
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ start_proxy 7862 music-worker:7860
|
|||||||
start_proxy 8007 stem-separator:8080
|
start_proxy 8007 stem-separator:8080
|
||||||
start_proxy 8008 voice-studio:8008
|
start_proxy 8008 voice-studio:8008
|
||||||
start_proxy 8009 xvc-studio:8009
|
start_proxy 8009 xvc-studio:8009
|
||||||
start_proxy 8010 seed-vc-studio:7860
|
|
||||||
start_proxy 8011 applio-studio:6969
|
start_proxy 8011 applio-studio:6969
|
||||||
start_proxy 8202 mcp-athena-operator:8000
|
start_proxy 8202 mcp-athena-operator:8000
|
||||||
start_proxy 9443 portainer:9443
|
start_proxy 9443 portainer:9443
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ MUSIC_ORIGINAL_UI_URL = os.getenv(
|
|||||||
SEPARATOR_UI_URL = os.getenv("SEPARATOR_UI_URL", "http://192.168.1.212:8007/")
|
SEPARATOR_UI_URL = os.getenv("SEPARATOR_UI_URL", "http://192.168.1.212:8007/")
|
||||||
VOICE_UI_URL = os.getenv("VOICE_UI_URL", "http://192.168.1.212:8008/")
|
VOICE_UI_URL = os.getenv("VOICE_UI_URL", "http://192.168.1.212:8008/")
|
||||||
VOICE_CHANGE_UI_URL = os.getenv("VOICE_CHANGE_UI_URL", "http://192.168.1.212:8009/")
|
VOICE_CHANGE_UI_URL = os.getenv("VOICE_CHANGE_UI_URL", "http://192.168.1.212:8009/")
|
||||||
SEED_VC_UI_URL = os.getenv("SEED_VC_UI_URL", "http://192.168.1.212:8010/")
|
|
||||||
APPLIO_UI_URL = os.getenv("APPLIO_UI_URL", "http://192.168.1.212:8011/")
|
APPLIO_UI_URL = os.getenv("APPLIO_UI_URL", "http://192.168.1.212:8011/")
|
||||||
HOST_PROC = Path(os.getenv("HOST_PROC", "/host/proc"))
|
HOST_PROC = Path(os.getenv("HOST_PROC", "/host/proc"))
|
||||||
HOST_DATA = os.getenv("HOST_DATA", "/host/data")
|
HOST_DATA = os.getenv("HOST_DATA", "/host/data")
|
||||||
@@ -281,7 +280,7 @@ def router_status() -> tuple[dict[str, Any], str | None]:
|
|||||||
|
|
||||||
|
|
||||||
def change_mode(mode: str) -> tuple[int, dict[str, Any]]:
|
def change_mode(mode: str) -> tuple[int, dict[str, Any]]:
|
||||||
if mode not in {"llm", "music", "separation", "voice", "voicechange", "seedvc", "applio"}:
|
if mode not in {"llm", "music", "separation", "voice", "voicechange", "applio"}:
|
||||||
return 400, {"error": "invalid mode"}
|
return 400, {"error": "invalid mode"}
|
||||||
headers = {"Accept": "application/json", "Content-Type": "application/json"}
|
headers = {"Accept": "application/json", "Content-Type": "application/json"}
|
||||||
if ROUTER_API_KEY:
|
if ROUTER_API_KEY:
|
||||||
@@ -639,7 +638,7 @@ HTML = r'''<!doctype html>
|
|||||||
</style></head><body><main>
|
</style></head><body><main>
|
||||||
<div class="top"><div><div class="eyebrow">Mike AI · Live Telemetry</div><h1>Athena llama.cpp Dashboard</h1></div><div class="live"><span class="dot" id="dot"></span><span id="updated">verbinde …</span></div></div>
|
<div class="top"><div><div class="eyebrow">Mike AI · Live Telemetry</div><h1>Athena llama.cpp Dashboard</h1></div><div class="live"><span class="dot" id="dot"></span><span id="updated">verbinde …</span></div></div>
|
||||||
<section class="grid">
|
<section class="grid">
|
||||||
<article class="card span12"><div class="mode-row"><div><div class="label">Athena Betriebsmodus</div><div class="value" id="operatingMode">–</div><div class="sub" id="modeStatus">Status wird geladen …</div></div><div class="mode-buttons"><button id="llmMode" onclick="setMode('llm')">LLM-Betrieb</button><button id="musicMode" onclick="setMode('music')">Musikstudio</button><button id="separationMode" onclick="setMode('separation')">Audio trennen</button><button id="voiceMode" onclick="setMode('voice')">Voice Studio</button><button id="voiceChangeMode" onclick="setMode('voicechange')">X-VC</button><button id="seedVcMode" onclick="setMode('seedvc')">Seed-VC</button><button id="applioMode" onclick="setMode('applio')">Applio / RVC · Modell nötig</button><span id="musicOpen" hidden><a class="stable" href="__MUSIC_ORIGINAL_UI_URL__" target="_blank" rel="noopener">Original UI · stabil</a><a class="experimental" href="__MUSIC_COMMUNITY_UI_URL__" target="_blank" rel="noopener">Community UI · experimentell</a></span><span id="separatorOpen" hidden><a class="stable" href="__SEPARATOR_UI_URL__" target="_blank" rel="noopener">Separator öffnen</a></span><span id="voiceOpen" hidden><a class="stable" href="__VOICE_UI_URL__" target="_blank" rel="noopener">Voice Studio öffnen</a></span><span id="voiceChangeOpen" hidden><a class="experimental" href="__VOICE_CHANGE_UI_URL__" target="_blank" rel="noopener">X-VC öffnen</a></span><span id="seedVcOpen" hidden><a class="experimental" href="__SEED_VC_UI_URL__" target="_blank" rel="noopener">Seed-VC öffnen</a></span><span id="applioOpen" hidden><a class="experimental" href="__APPLIO_UI_URL__" target="_blank" rel="noopener">Applio öffnen · RVC-Modell erforderlich</a></span></div></div></article>
|
<article class="card span12"><div class="mode-row"><div><div class="label">Athena Betriebsmodus</div><div class="value" id="operatingMode">–</div><div class="sub" id="modeStatus">Status wird geladen …</div></div><div class="mode-buttons"><button id="llmMode" onclick="setMode('llm')">LLM-Betrieb</button><button id="musicMode" onclick="setMode('music')">Musikstudio</button><button id="separationMode" onclick="setMode('separation')">Audio trennen</button><button id="voiceMode" onclick="setMode('voice')">Voice Studio</button><button id="voiceChangeMode" onclick="setMode('voicechange')">X-VC</button><button id="applioMode" onclick="setMode('applio')">Applio / RVC · Modell nötig</button><span id="musicOpen" hidden><a class="stable" href="__MUSIC_ORIGINAL_UI_URL__" target="_blank" rel="noopener">Original UI · stabil</a><a class="experimental" href="__MUSIC_COMMUNITY_UI_URL__" target="_blank" rel="noopener">Community UI · experimentell</a></span><span id="separatorOpen" hidden><a class="stable" href="__SEPARATOR_UI_URL__" target="_blank" rel="noopener">Separator öffnen</a></span><span id="voiceOpen" hidden><a class="stable" href="__VOICE_UI_URL__" target="_blank" rel="noopener">Voice Studio öffnen</a></span><span id="voiceChangeOpen" hidden><a class="experimental" href="__VOICE_CHANGE_UI_URL__" target="_blank" rel="noopener">X-VC öffnen</a></span><span id="applioOpen" hidden><a class="experimental" href="__APPLIO_UI_URL__" target="_blank" rel="noopener">Applio öffnen · RVC-Modell erforderlich</a></span></div></div></article>
|
||||||
<article class="card span3"><div class="label">Aktives Profil</div><div class="value" id="profile">–</div><div class="sub" id="profileSub">Router wird abgefragt</div></article>
|
<article class="card span3"><div class="label">Aktives Profil</div><div class="value" id="profile">–</div><div class="sub" id="profileSub">Router wird abgefragt</div></article>
|
||||||
<article class="card span3"><div class="label">Modell</div><div class="value" id="model">–</div><div class="sub" id="modelSub">–</div></article>
|
<article class="card span3"><div class="label">Modell</div><div class="value" id="model">–</div><div class="sub" id="modelSub">–</div></article>
|
||||||
<article class="card span3"><div class="label">CPU</div><div class="value" id="cpu">–</div><div class="bar"><div class="fill" id="cpuBar"></div></div><div class="sub" id="load">–</div></article>
|
<article class="card span3"><div class="label">CPU</div><div class="value" id="cpu">–</div><div class="bar"><div class="fill" id="cpuBar"></div></div><div class="sub" id="load">–</div></article>
|
||||||
@@ -678,20 +677,20 @@ const $=id=>document.getElementById(id); const pct=n=>n==null?'–':`${n.toFixed
|
|||||||
function gpuCard(g){let total=g.memory_total_mib||0,used=g.memory_used_mib||0,p=total?used/total*100:0,load=Math.max(0,Math.min(100,g.gpu_percent||0));return `<article class="card span6"><div class="gpu-title"><div><div class="label">GPU ${g.index}</div><div class="value">${g.name}</div></div><span class="badge">${g.pstate||'–'}</span></div><div class="metrics"><div class="metric"><b>${pct(g.gpu_percent)}</b><span>GPU-Kern</span></div><div class="metric"><b>${(used/1024).toFixed(1)} / ${(total/1024).toFixed(1)} GiB</b><span>VRAM</span></div><div class="metric"><b>${g.temperature_c??'–'} °C</b><span>Temperatur</span></div><div class="metric"><b>${g.power_w??'–'} / ${g.power_limit_w??'–'} W</b><span>Leistung</span></div><div class="metric"><b>${g.graphics_clock_mhz??'–'} MHz</b><span>Grafiktakt</span></div><div class="metric"><b>${g.memory_clock_mhz??'–'} MHz</b><span>Speichertakt</span></div><div class="metric"><b>${pct(g.memory_controller_percent)}</b><span>Memory Controller</span></div><div class="metric"><b>${pct(g.fan_percent)}</b><span>Lüfter</span></div></div><div class="bar-label"><span>GPU-Auslastung</span><span>${load.toFixed(1)} %</span></div><div class="bar"><div class="fill gpu-load" style="width:${load}%"></div></div><div class="bar-label"><span>VRAM-Belegung</span><span>${p.toFixed(1)} %</span></div><div class="bar"><div class="fill" style="width:${Math.min(100,p)}%"></div></div><div class="sub">${(g.memory_free_mib/1024).toFixed(1)} GiB VRAM frei</div></article>`}
|
function gpuCard(g){let total=g.memory_total_mib||0,used=g.memory_used_mib||0,p=total?used/total*100:0,load=Math.max(0,Math.min(100,g.gpu_percent||0));return `<article class="card span6"><div class="gpu-title"><div><div class="label">GPU ${g.index}</div><div class="value">${g.name}</div></div><span class="badge">${g.pstate||'–'}</span></div><div class="metrics"><div class="metric"><b>${pct(g.gpu_percent)}</b><span>GPU-Kern</span></div><div class="metric"><b>${(used/1024).toFixed(1)} / ${(total/1024).toFixed(1)} GiB</b><span>VRAM</span></div><div class="metric"><b>${g.temperature_c??'–'} °C</b><span>Temperatur</span></div><div class="metric"><b>${g.power_w??'–'} / ${g.power_limit_w??'–'} W</b><span>Leistung</span></div><div class="metric"><b>${g.graphics_clock_mhz??'–'} MHz</b><span>Grafiktakt</span></div><div class="metric"><b>${g.memory_clock_mhz??'–'} MHz</b><span>Speichertakt</span></div><div class="metric"><b>${pct(g.memory_controller_percent)}</b><span>Memory Controller</span></div><div class="metric"><b>${pct(g.fan_percent)}</b><span>Lüfter</span></div></div><div class="bar-label"><span>GPU-Auslastung</span><span>${load.toFixed(1)} %</span></div><div class="bar"><div class="fill gpu-load" style="width:${load}%"></div></div><div class="bar-label"><span>VRAM-Belegung</span><span>${p.toFixed(1)} %</span></div><div class="bar"><div class="fill" style="width:${Math.min(100,p)}%"></div></div><div class="sub">${(g.memory_free_mib/1024).toFixed(1)} GiB VRAM frei</div></article>`}
|
||||||
const imagePhaseLabel=p=>({"stopping-qwen":"Qwen wird entladen","loading-image":"Bildmodell wird geladen","generating":"Bild wird generiert","unloading-image":"Bildmodell wird entladen","restoring-qwen":"Qwen wird wiederhergestellt"}[p]||p||'bereit');
|
const imagePhaseLabel=p=>({"stopping-qwen":"Qwen wird entladen","loading-image":"Bildmodell wird geladen","generating":"Bild wird generiert","unloading-image":"Bildmodell wird entladen","restoring-qwen":"Qwen wird wiederhergestellt"}[p]||p||'bereit');
|
||||||
let modeBusy=false;
|
let modeBusy=false;
|
||||||
async function setMode(mode){if(modeBusy)return;modeBusy=true;for(const id of ['llmMode','musicMode','separationMode','voiceMode','voiceChangeMode','seedVcMode','applioMode'])$(id).disabled=true;$('modeStatus').textContent='Umschaltung angefordert …';try{let r=await fetch('/api/mode',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({mode})});let d=await r.json();if(!r.ok)throw Error(d?.error?.message||d?.error||`HTTP ${r.status}`);$('modeStatus').textContent='Umschaltung läuft …'}catch(e){$('modeStatus').textContent=e.message;$('modeStatus').classList.add('mode-error')}finally{modeBusy=false;setTimeout(refresh,250)}}
|
async function setMode(mode){if(modeBusy)return;modeBusy=true;for(const id of ['llmMode','musicMode','separationMode','voiceMode','voiceChangeMode','applioMode'])$(id).disabled=true;$('modeStatus').textContent='Umschaltung angefordert …';try{let r=await fetch('/api/mode',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({mode})});let d=await r.json();if(!r.ok)throw Error(d?.error?.message||d?.error||`HTTP ${r.status}`);$('modeStatus').textContent='Umschaltung läuft …'}catch(e){$('modeStatus').textContent=e.message;$('modeStatus').classList.add('mode-error')}finally{modeBusy=false;setTimeout(refresh,250)}}
|
||||||
async function refresh(){try{let r=await fetch('/api/status',{cache:'no-store'});if(!r.ok)throw Error(`HTTP ${r.status}`);let d=await r.json(),c=d.cpu||{},m=c.memory||{},rt=d.router||{},up=rt.upstream||{},q=rt.qwen||{},lr=d.llama_runtime||{},img=rt.image||{},imageActive=img.phase&&img.phase!=='idle';let md=rt.mode||{},switchingMode=md.phase&&md.phase!=='ready',modeName=md.active==='music'?'Musikstudio':md.active==='separation'?'Stimmtrennung':md.active==='voice'?'Voice Studio':'LLM-Betrieb';$('operatingMode').textContent=modeName;$('modeStatus').textContent=switchingMode?`Umschaltung: ${md.phase}`:(md.last_error||`Musik: ${md.music_worker||'–'} · Separator: ${md.separator_worker||'–'} · Voice: ${md.voice_worker||'–'}${md.return_profile?` · Rückkehr zu ${md.return_profile}`:''}`);$('modeStatus').classList.toggle('mode-error',!!md.last_error);$('llmMode').classList.toggle('active',md.active==='llm');$('musicMode').classList.toggle('active',md.active==='music');$('separationMode').classList.toggle('active',md.active==='separation');$('voiceMode').classList.toggle('active',md.active==='voice');$('llmMode').disabled=$('musicMode').disabled=$('separationMode').disabled=$('voiceMode').disabled=modeBusy||switchingMode||!md.enabled;$('musicOpen').hidden=md.active!=='music';$('separatorOpen').hidden=md.active!=='separation';$('voiceOpen').hidden=md.active!=='voice';$('profile').textContent=imageActive?'Bildgenerierung':(rt.current_profile||'nicht geladen');$('profileSub').textContent=imageActive?imagePhaseLabel(img.phase):(rt.switching?`Wechsel zu ${rt.switching}`:`Kontext: ${up.ctx?up.ctx.toLocaleString('de-DE'):'–'} Token`);$('model').textContent=imageActive?(img.model||'Bildmodell'):(up.model||'–');$('modelSub').textContent=imageActive?`${img.model_loaded?'geladen':'wird vorbereitet'} · Worker ${img.worker||'–'}`:(lr.model_file|| (up.reachable?'llama.cpp erreichbar':'llama.cpp nicht erreichbar'));$('cpu').textContent=pct(c.usage_percent);$('cpuBar').style.width=`${c.usage_percent||0}%`;$('load').textContent=`${c.logical_cpus||'–'} Threads · Load ${(c.load||[]).join(' / ')}`;let rp=m.total?m.used/m.total*100:0;$('ram').textContent=pct(rp);$('ramBar').style.width=`${rp}%`;$('ramSub').textContent=`${gib(m.used)} / ${gib(m.total)}`;$('gpuCards').innerHTML=(d.gpus||[]).map(gpuCard).join('')||'<article class="card span12 error">Keine GPU-Daten verfügbar</article>';$('availability').textContent=imageActive?imagePhaseLabel(img.phase):(q.available?'bereit':'nicht bereit');$('availability').className=`value status ${(imageActive||q.available)?'':'bad'}`;$('activeChats').textContent=q.active_chats??'–';$('routerUptime').textContent=dur(rt.uptime_seconds);$('switching').textContent=imageActive?imagePhaseLabel(img.phase):(rt.switching||'nein');let disk=c.disk_data||{},dp=disk.total?disk.used/disk.total*100:null;$('dataDisk').textContent=pct(dp);$('processes').innerHTML=(d.gpu_processes||[]).map(p=>`<tr><td>${(d.gpus||[]).find(g=>g.uuid===p.gpu_uuid)?.index??'–'}</td><td>${p.name}</td><td>${p.pid}</td><td>${p.memory_mib??'–'} MiB</td></tr>`).join('')||'<tr><td colspan="4">Keine Compute-Prozesse gemeldet</td></tr>';let runtime=[['Modell-Datei',lr.model_file],['PID',lr.pid],['Kontext',lr.context_size?lr.context_size.toLocaleString('de-DE'):'–'],['Batch / µBatch',`${lr.batch_size??'–'} / ${lr.ubatch_size??'–'}`],['Parallel',lr.parallel],['Threads',`${lr.threads??'–'} / ${lr.threads_batch??'–'}`],['Geräte',lr.device],['Tensor-Split',lr.tensor_split],['KV-Cache',`${lr.cache_k??'–'} / ${lr.cache_v??'–'}`],['Flash Attention',lr.flash_attention?'an':'aus'],['Prompt-Cache',lr.prompt_cache?'an':'aus'],['MTP Draft',lr.mtp_draft_tokens]];$('runtime').innerHTML=runtime.map(([k,v])=>`<div class="metric"><b>${v??'–'}</b><span>${k}</span></div>`).join('');let es=Object.entries(d.errors||{}).filter(([,v])=>v);$('errors').hidden=!es.length;$('errors').textContent=es.map(([k,v])=>`${k}: ${v}`).join('\n');$('updated').textContent=`Live · ${new Date(d.timestamp*1000).toLocaleTimeString('de-DE')}`;$('dot').style.background='var(--green)'}catch(e){$('updated').textContent=`Verbindung gestört: ${e.message}`;$('dot').style.background='var(--red)'}}refresh();setInterval(refresh,1000);
|
async function refresh(){try{let r=await fetch('/api/status',{cache:'no-store'});if(!r.ok)throw Error(`HTTP ${r.status}`);let d=await r.json(),c=d.cpu||{},m=c.memory||{},rt=d.router||{},up=rt.upstream||{},q=rt.qwen||{},lr=d.llama_runtime||{},img=rt.image||{},imageActive=img.phase&&img.phase!=='idle';let md=rt.mode||{},switchingMode=md.phase&&md.phase!=='ready',modeName=md.active==='music'?'Musikstudio':md.active==='separation'?'Stimmtrennung':md.active==='voice'?'Voice Studio':'LLM-Betrieb';$('operatingMode').textContent=modeName;$('modeStatus').textContent=switchingMode?`Umschaltung: ${md.phase}`:(md.last_error||`Musik: ${md.music_worker||'–'} · Separator: ${md.separator_worker||'–'} · Voice: ${md.voice_worker||'–'}${md.return_profile?` · Rückkehr zu ${md.return_profile}`:''}`);$('modeStatus').classList.toggle('mode-error',!!md.last_error);$('llmMode').classList.toggle('active',md.active==='llm');$('musicMode').classList.toggle('active',md.active==='music');$('separationMode').classList.toggle('active',md.active==='separation');$('voiceMode').classList.toggle('active',md.active==='voice');$('llmMode').disabled=$('musicMode').disabled=$('separationMode').disabled=$('voiceMode').disabled=modeBusy||switchingMode||!md.enabled;$('musicOpen').hidden=md.active!=='music';$('separatorOpen').hidden=md.active!=='separation';$('voiceOpen').hidden=md.active!=='voice';$('profile').textContent=imageActive?'Bildgenerierung':(rt.current_profile||'nicht geladen');$('profileSub').textContent=imageActive?imagePhaseLabel(img.phase):(rt.switching?`Wechsel zu ${rt.switching}`:`Kontext: ${up.ctx?up.ctx.toLocaleString('de-DE'):'–'} Token`);$('model').textContent=imageActive?(img.model||'Bildmodell'):(up.model||'–');$('modelSub').textContent=imageActive?`${img.model_loaded?'geladen':'wird vorbereitet'} · Worker ${img.worker||'–'}`:(lr.model_file|| (up.reachable?'llama.cpp erreichbar':'llama.cpp nicht erreichbar'));$('cpu').textContent=pct(c.usage_percent);$('cpuBar').style.width=`${c.usage_percent||0}%`;$('load').textContent=`${c.logical_cpus||'–'} Threads · Load ${(c.load||[]).join(' / ')}`;let rp=m.total?m.used/m.total*100:0;$('ram').textContent=pct(rp);$('ramBar').style.width=`${rp}%`;$('ramSub').textContent=`${gib(m.used)} / ${gib(m.total)}`;$('gpuCards').innerHTML=(d.gpus||[]).map(gpuCard).join('')||'<article class="card span12 error">Keine GPU-Daten verfügbar</article>';$('availability').textContent=imageActive?imagePhaseLabel(img.phase):(q.available?'bereit':'nicht bereit');$('availability').className=`value status ${(imageActive||q.available)?'':'bad'}`;$('activeChats').textContent=q.active_chats??'–';$('routerUptime').textContent=dur(rt.uptime_seconds);$('switching').textContent=imageActive?imagePhaseLabel(img.phase):(rt.switching||'nein');let disk=c.disk_data||{},dp=disk.total?disk.used/disk.total*100:null;$('dataDisk').textContent=pct(dp);$('processes').innerHTML=(d.gpu_processes||[]).map(p=>`<tr><td>${(d.gpus||[]).find(g=>g.uuid===p.gpu_uuid)?.index??'–'}</td><td>${p.name}</td><td>${p.pid}</td><td>${p.memory_mib??'–'} MiB</td></tr>`).join('')||'<tr><td colspan="4">Keine Compute-Prozesse gemeldet</td></tr>';let runtime=[['Modell-Datei',lr.model_file],['PID',lr.pid],['Kontext',lr.context_size?lr.context_size.toLocaleString('de-DE'):'–'],['Batch / µBatch',`${lr.batch_size??'–'} / ${lr.ubatch_size??'–'}`],['Parallel',lr.parallel],['Threads',`${lr.threads??'–'} / ${lr.threads_batch??'–'}`],['Geräte',lr.device],['Tensor-Split',lr.tensor_split],['KV-Cache',`${lr.cache_k??'–'} / ${lr.cache_v??'–'}`],['Flash Attention',lr.flash_attention?'an':'aus'],['Prompt-Cache',lr.prompt_cache?'an':'aus'],['MTP Draft',lr.mtp_draft_tokens]];$('runtime').innerHTML=runtime.map(([k,v])=>`<div class="metric"><b>${v??'–'}</b><span>${k}</span></div>`).join('');let es=Object.entries(d.errors||{}).filter(([,v])=>v);$('errors').hidden=!es.length;$('errors').textContent=es.map(([k,v])=>`${k}: ${v}`).join('\n');$('updated').textContent=`Live · ${new Date(d.timestamp*1000).toLocaleTimeString('de-DE')}`;$('dot').style.background='var(--green)'}catch(e){$('updated').textContent=`Verbindung gestört: ${e.message}`;$('dot').style.background='var(--red)'}}refresh();setInterval(refresh,1000);
|
||||||
</script><script>
|
</script><script>
|
||||||
const baseSetMode=setMode;
|
const baseSetMode=setMode;
|
||||||
setMode=async function(mode){
|
setMode=async function(mode){
|
||||||
if(modeBusy)return;
|
if(modeBusy)return;
|
||||||
for(const id of ['llmMode','musicMode','separationMode','voiceMode','voiceChangeMode','seedVcMode','applioMode'])$(id).disabled=true;
|
for(const id of ['llmMode','musicMode','separationMode','voiceMode','voiceChangeMode','applioMode'])$(id).disabled=true;
|
||||||
await baseSetMode(mode);
|
await baseSetMode(mode);
|
||||||
};
|
};
|
||||||
async function refreshVoiceChange(){
|
async function refreshVoiceChange(){
|
||||||
try{
|
try{
|
||||||
const response=await fetch('/api/status',{cache:'no-store'}); if(!response.ok)return;
|
const response=await fetch('/api/status',{cache:'no-store'}); if(!response.ok)return;
|
||||||
const data=await response.json(),mode=data.router?.mode||{},busy=modeBusy||(mode.phase&&mode.phase!=='ready')||!mode.enabled;
|
const data=await response.json(),mode=data.router?.mode||{},busy=modeBusy||(mode.phase&&mode.phase!=='ready')||!mode.enabled;
|
||||||
const modes=[['voicechange','voiceChangeMode','voiceChangeOpen','X-VC Voice Changer'],['seedvc','seedVcMode','seedVcOpen','Seed-VC'],['applio','applioMode','applioOpen','Applio / RVC']];
|
const modes=[['voicechange','voiceChangeMode','voiceChangeOpen','X-VC Voice Changer'],['applio','applioMode','applioOpen','Applio / RVC']];
|
||||||
for(const [name,button,link,label] of modes){const active=mode.active===name;$(button).classList.toggle('active',active);$(button).disabled=busy;$(link).hidden=!active;if(active)$('operatingMode').textContent=label;}
|
for(const [name,button,link,label] of modes){const active=mode.active===name;$(button).classList.toggle('active',active);$(button).disabled=busy;$(link).hidden=!active;if(active)$('operatingMode').textContent=label;}
|
||||||
}catch(_error){}
|
}catch(_error){}
|
||||||
}
|
}
|
||||||
@@ -701,8 +700,7 @@ setTimeout(()=>{refreshVoiceChange();setInterval(refreshVoiceChange,1000)},150);
|
|||||||
).replace("__MUSIC_COMMUNITY_UI_URL__", MUSIC_COMMUNITY_UI_URL
|
).replace("__MUSIC_COMMUNITY_UI_URL__", MUSIC_COMMUNITY_UI_URL
|
||||||
).replace("__SEPARATOR_UI_URL__", SEPARATOR_UI_URL
|
).replace("__SEPARATOR_UI_URL__", SEPARATOR_UI_URL
|
||||||
).replace("__VOICE_UI_URL__", VOICE_UI_URL
|
).replace("__VOICE_UI_URL__", VOICE_UI_URL
|
||||||
).replace("__VOICE_CHANGE_UI_URL__", VOICE_CHANGE_UI_URL).replace(
|
).replace("__VOICE_CHANGE_UI_URL__", VOICE_CHANGE_UI_URL
|
||||||
"__SEED_VC_UI_URL__", SEED_VC_UI_URL
|
|
||||||
).replace("__APPLIO_UI_URL__", APPLIO_UI_URL)
|
).replace("__APPLIO_UI_URL__", APPLIO_UI_URL)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ MUSIC_START_TIMEOUT = float(os.environ.get("MUSIC_START_TIMEOUT", "600"))
|
|||||||
SEPARATOR_START_TIMEOUT = float(os.environ.get("SEPARATOR_START_TIMEOUT", "600"))
|
SEPARATOR_START_TIMEOUT = float(os.environ.get("SEPARATOR_START_TIMEOUT", "600"))
|
||||||
VOICE_START_TIMEOUT = float(os.environ.get("VOICE_START_TIMEOUT", "600"))
|
VOICE_START_TIMEOUT = float(os.environ.get("VOICE_START_TIMEOUT", "600"))
|
||||||
VOICE_CHANGE_START_TIMEOUT = float(os.environ.get("VOICE_CHANGE_START_TIMEOUT", "600"))
|
VOICE_CHANGE_START_TIMEOUT = float(os.environ.get("VOICE_CHANGE_START_TIMEOUT", "600"))
|
||||||
SEED_VC_START_TIMEOUT = float(os.environ.get("SEED_VC_START_TIMEOUT", "900"))
|
|
||||||
APPLIO_START_TIMEOUT = float(os.environ.get("APPLIO_START_TIMEOUT", "900"))
|
APPLIO_START_TIMEOUT = float(os.environ.get("APPLIO_START_TIMEOUT", "900"))
|
||||||
|
|
||||||
# Optional worker APIs. The clean Docker baseline deliberately ships only
|
# Optional worker APIs. The clean Docker baseline deliberately ships only
|
||||||
@@ -487,11 +486,6 @@ def _wait_aux_voice_ready(worker_field: str, health_field: str,
|
|||||||
raise RuntimeError(f"{label} nach {timeout:.0f} s nicht bereit")
|
raise RuntimeError(f"{label} nach {timeout:.0f} s nicht bereit")
|
||||||
|
|
||||||
|
|
||||||
def _wait_seed_vc_ready() -> None:
|
|
||||||
_wait_aux_voice_ready("seed_vc_worker", "seed_vc_health",
|
|
||||||
"Seed-VC", SEED_VC_START_TIMEOUT)
|
|
||||||
|
|
||||||
|
|
||||||
def _wait_applio_ready() -> None:
|
def _wait_applio_ready() -> None:
|
||||||
_wait_aux_voice_ready("applio_worker", "applio_health",
|
_wait_aux_voice_ready("applio_worker", "applio_health",
|
||||||
"Applio", APPLIO_START_TIMEOUT)
|
"Applio", APPLIO_START_TIMEOUT)
|
||||||
@@ -507,9 +501,6 @@ def _special_worker(mode: str) -> tuple[str, str, callable]:
|
|||||||
if mode == "voicechange":
|
if mode == "voicechange":
|
||||||
return ("/workers/voice-change/start", _voice_change_worker_state(),
|
return ("/workers/voice-change/start", _voice_change_worker_state(),
|
||||||
_wait_voice_change_ready)
|
_wait_voice_change_ready)
|
||||||
if mode == "seedvc":
|
|
||||||
return ("/workers/seed-vc/start", _worker_field("seed_vc_worker"),
|
|
||||||
_wait_seed_vc_ready)
|
|
||||||
if mode == "applio":
|
if mode == "applio":
|
||||||
return ("/workers/applio/start", _worker_field("applio_worker"),
|
return ("/workers/applio/start", _worker_field("applio_worker"),
|
||||||
_wait_applio_ready)
|
_wait_applio_ready)
|
||||||
@@ -520,7 +511,7 @@ def set_operating_mode(mode: str) -> dict:
|
|||||||
"""Atomarer Wechsel zwischen LLM und den exklusiven GPU-Werkzeugen."""
|
"""Atomarer Wechsel zwischen LLM und den exklusiven GPU-Werkzeugen."""
|
||||||
if not ENABLE_MUSIC_MODE or not PROFILE_CONTROL_URL:
|
if not ENABLE_MUSIC_MODE or not PROFILE_CONTROL_URL:
|
||||||
raise RuntimeError("Musikmodus ist nicht konfiguriert")
|
raise RuntimeError("Musikmodus ist nicht konfiguriert")
|
||||||
special_modes = {"music", "separation", "voice", "voicechange", "seedvc", "applio"}
|
special_modes = {"music", "separation", "voice", "voicechange", "applio"}
|
||||||
if mode not in {"llm", *special_modes}:
|
if mode not in {"llm", *special_modes}:
|
||||||
raise ValueError("unbekannter Betriebsmodus")
|
raise ValueError("unbekannter Betriebsmodus")
|
||||||
with STATE.lock:
|
with STATE.lock:
|
||||||
@@ -568,7 +559,6 @@ def set_operating_mode(mode: str) -> dict:
|
|||||||
_profile_controller_request("POST", "/workers/separator/stop")
|
_profile_controller_request("POST", "/workers/separator/stop")
|
||||||
_profile_controller_request("POST", "/workers/voice/stop")
|
_profile_controller_request("POST", "/workers/voice/stop")
|
||||||
_profile_controller_request("POST", "/workers/voice-change/stop")
|
_profile_controller_request("POST", "/workers/voice-change/stop")
|
||||||
_profile_controller_request("POST", "/workers/seed-vc/stop")
|
|
||||||
_profile_controller_request("POST", "/workers/applio/stop")
|
_profile_controller_request("POST", "/workers/applio/stop")
|
||||||
_restore_qwen(profile)
|
_restore_qwen(profile)
|
||||||
STATE.mode = "llm"
|
STATE.mode = "llm"
|
||||||
@@ -588,7 +578,7 @@ def schedule_operating_mode(mode: str) -> tuple[bool, str]:
|
|||||||
"""Start a transition in the background so chat/UI acknowledgement is instant."""
|
"""Start a transition in the background so chat/UI acknowledgement is instant."""
|
||||||
if not ENABLE_MUSIC_MODE or not PROFILE_CONTROL_URL:
|
if not ENABLE_MUSIC_MODE or not PROFILE_CONTROL_URL:
|
||||||
raise RuntimeError("Musikmodus ist nicht konfiguriert")
|
raise RuntimeError("Musikmodus ist nicht konfiguriert")
|
||||||
if mode not in {"llm", "music", "separation", "voice", "voicechange", "seedvc", "applio"}:
|
if mode not in {"llm", "music", "separation", "voice", "voicechange", "applio"}:
|
||||||
raise ValueError("unbekannter Betriebsmodus")
|
raise ValueError("unbekannter Betriebsmodus")
|
||||||
with STATE.lock:
|
with STATE.lock:
|
||||||
if STATE.mode_phase not in {"ready", "error"}:
|
if STATE.mode_phase not in {"ready", "error"}:
|
||||||
@@ -627,7 +617,7 @@ def _control_command(data: dict, path: str) -> str | None:
|
|||||||
"/athena separation", "/athena llm",
|
"/athena separation", "/athena llm",
|
||||||
"/athena voice",
|
"/athena voice",
|
||||||
"/athena voicechange", "/athena changer",
|
"/athena voicechange", "/athena changer",
|
||||||
"/athena seedvc", "/athena applio",
|
"/athena applio",
|
||||||
"/athena status"} else None
|
"/athena status"} else None
|
||||||
|
|
||||||
|
|
||||||
@@ -2107,8 +2097,6 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
"voice_health": _voice_worker_health(),
|
"voice_health": _voice_worker_health(),
|
||||||
"voice_change_worker": _voice_change_worker_state(),
|
"voice_change_worker": _voice_change_worker_state(),
|
||||||
"voice_change_health": _voice_change_worker_health(),
|
"voice_change_health": _voice_change_worker_health(),
|
||||||
"seed_vc_worker": _worker_field("seed_vc_worker"),
|
|
||||||
"seed_vc_health": _worker_field("seed_vc_health"),
|
|
||||||
"applio_worker": _worker_field("applio_worker"),
|
"applio_worker": _worker_field("applio_worker"),
|
||||||
"applio_health": _worker_field("applio_health"),
|
"applio_health": _worker_field("applio_health"),
|
||||||
"return_profile": state.get("return_profile"),
|
"return_profile": state.get("return_profile"),
|
||||||
@@ -2120,7 +2108,7 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
try:
|
try:
|
||||||
data = json.loads(self._read_body() or b"{}")
|
data = json.loads(self._read_body() or b"{}")
|
||||||
mode = data.get("mode") if isinstance(data, dict) else None
|
mode = data.get("mode") if isinstance(data, dict) else None
|
||||||
if mode not in {"llm", "music", "separation", "voice", "voicechange", "seedvc", "applio"}:
|
if mode not in {"llm", "music", "separation", "voice", "voicechange", "applio"}:
|
||||||
raise ValueError("Feld 'mode' enthält einen unbekannten Betriebsmodus")
|
raise ValueError("Feld 'mode' enthält einen unbekannten Betriebsmodus")
|
||||||
started, phase = schedule_operating_mode(mode)
|
started, phase = schedule_operating_mode(mode)
|
||||||
self._send_json(202 if started else 200, {
|
self._send_json(202 if started else 200, {
|
||||||
@@ -2792,7 +2780,6 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
"separation" if command in {"/athena stems", "/athena separation"}
|
"separation" if command in {"/athena stems", "/athena separation"}
|
||||||
else "voice" if command == "/athena voice"
|
else "voice" if command == "/athena voice"
|
||||||
else "voicechange" if command in {"/athena voicechange", "/athena changer"}
|
else "voicechange" if command in {"/athena voicechange", "/athena changer"}
|
||||||
else "seedvc" if command == "/athena seedvc"
|
|
||||||
else "applio" if command == "/athena applio"
|
else "applio" if command == "/athena applio"
|
||||||
else "llm")
|
else "llm")
|
||||||
try:
|
try:
|
||||||
@@ -2806,8 +2793,6 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
if target == "voice" else
|
if target == "voice" else
|
||||||
"Voice Changer wird gestartet. LLM und TTS werden entladen."
|
"Voice Changer wird gestartet. LLM und TTS werden entladen."
|
||||||
if target == "voicechange" else
|
if target == "voicechange" else
|
||||||
"Seed-VC wird gestartet. LLM und TTS werden entladen."
|
|
||||||
if target == "seedvc" else
|
|
||||||
"Applio wird gestartet. LLM und TTS werden entladen."
|
"Applio wird gestartet. LLM und TTS werden entladen."
|
||||||
if target == "applio" else
|
if target == "applio" else
|
||||||
"Spezialmodus wird beendet und das vorherige LLM-Profil wiederhergestellt.")
|
"Spezialmodus wird beendet und das vorherige LLM-Profil wiederhergestellt.")
|
||||||
|
|||||||
Reference in New Issue
Block a user