docs: clarifie VOICE_DEPLOYMENT_SPEC §1 — /voices scanne WAV (à convertir) + cvps (prête)

Recadrage suite échange : pas un blocage fonctionnel ; c'est l'inventaire voulu
(distinguer voix à convertir vs prêtes, garder les prêtes visibles après suppression WAV).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
alf 2026-06-19 20:17:43 +02:00
parent 94f8dc0993
commit 342966e867
1 changed files with 20 additions and 17 deletions

View File

@ -29,26 +29,29 @@
--- ---
## 1. Adaptation **BLOQUANTE**`/voices` doit refléter les `.cvps` déployés ## 1. Adaptation `/voices` scanne WAV **et** `.cvps` (inventaire à-convertir / prête)
**Problème** : Kazeia-central supprime le WAV de la tablette après enrôlement (le WAV **Intention** : `/voices` doit refléter le cycle de vie d'une voix en scannant **les
est archivé sur le PC). Une voix qui n'a plus que son `.cvps` n'a **ni `.wav` ni deux** dossiers, chacun pour un état :
embedding Qwen3** → l'`ids = wav prefix` actuel **l'omet**. La voix est déployée et - **WAV présent, pas de `.cvps`** → voix **« à convertir »** (enregistrée, en attente
fonctionnelle, mais **invisible** de `/voices` (donc du picker admin et de d'enrôlement par Kazeia-central).
Kazeia-central). Incident « zelda » généralisé. - **`.cvps` présent** → voix **« prête »** (enrôlée + déployée).
**Demande** : étendre `voicesCursor()` pour **inclure les basenames de Conséquence voulue : après conversion+déploiement puis suppression du WAV (le WAV est
`<modelsDir>/cosyvoice/*.cvps`** dans l'union d'ids, et exposer leur présence. archivé côté PC), la voix **reste affichée « prête »** grâce au scan `.cvps` — elle ne
disparaît pas de l'inventaire. (Aujourd'hui `voicesCursor()` ne scanne que
`WAV embeddings Qwen3` → une voix `.cvps`-seule serait omise.)
- Union d'ids = `basenames(*.wav) basenames(prefix.bin) basenames(*.cvps)`. **Demande** : étendre `voicesCursor()`
- Nouvelle colonne **`cvps_exists`** (0/1) à `/voices`. - Union d'ids = `basenames(*.wav) basenames(prefix.bin) basenames(cosyvoice/*.cvps)`.
- `state` : une voix avec `.cvps` présent est **`ready`** (CosyVoice = TTS de prod). - Nouvelle colonne **`cvps_exists`** (0/1).
Proposition de cascade : `ready` si `cvps_exists` **ou** (prefix+suffix Qwen3) ; - `state` (cascade) : **`ready`** si `cvps_exists` (ou prefix+suffix Qwen3 legacy) ;
`recorded` si seul le WAV ; `error` sinon. **`recorded`** (= « à convertir ») si seul le WAV ; `error` sinon.
- Colonnes inchangées par ailleurs (compat ascendante : ajout additif d'une colonne). - Ajout additif (colonne en plus) → compat ascendante.
> Sans cette adaptation, le reste du workflow « enrôle → déploie → supprime le WAV » > Pas un prérequis fonctionnel (la synthèse charge le `.cvps` par son nom, sans cette
> casse l'inventaire. C'est le **prérequis n°1**. > liste), mais c'est l'**inventaire voulu** : distinguer voix à convertir vs prêtes, et
> garder les voix prêtes visibles une fois le WAV supprimé.
--- ---
@ -111,7 +114,7 @@ Deux options :
| # | Adaptation | Criticité | Forme | | # | Adaptation | Criticité | Forme |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| 1 | `/voices` inclut les `.cvps` (`cvps_exists`, `state=ready`, ids cvps) | **bloquant** | curseur `voicesCursor()` | | 1 | `/voices` scanne WAV (« à convertir ») **et** `.cvps` (« prête »), col. `cvps_exists` | inventaire voulu | curseur `voicesCursor()` |
| 2 | `voices_reload` (rescan + `RELOAD_VOICES`, constante `ACTION_RELOAD_VOICES`) | important | méthode `call()` | | 2 | `voices_reload` (rescan + `RELOAD_VOICES`, constante `ACTION_RELOAD_VOICES`) | important | méthode `call()` |
| 4 | exclusivité on-device | conditionnel (si multi-patients/tablette) | à décider §4 | | 4 | exclusivité on-device | conditionnel (si multi-patients/tablette) | à décider §4 |