Studio : lot 8e ajouté au plan, STATUS, kanban et plan de test à jour

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011VxSQeGQYUvPmSEoGdnidA
This commit is contained in:
Thomas Fransolet 2026-09-15 23:00:46 +02:00
parent dff2f6ba37
commit 78517cb38f
5 changed files with 11 additions and 8 deletions

View File

@ -156,7 +156,7 @@ Dix-neuf chantiers de canaux et d'IA, chacun avec son plan détaillé. État au
- **V1****visiteur web** : `visitapp-web` build ✅, les 13 types de section rendus, assistant IA inclus ; **il ne manque que le Dockerfile et l'entrée `app.myinfomate.be` au compose**. Bloquant, le plan Essentiel vendu par l'onboarding est web-only. Plus l'**écran Guide IA**. La **Médiathèque** (basculée en V1 le 2026-09-02) est **codée de bout en bout le même jour** — index inverse des usages, panneau de détail, facettes, suppression protégée, les deux bugs corrigés ; `dotnet test` 236/236 et `flutter build web` verts, **mais la checklist de 15 points reste à passer dans un navigateur** (colonne « À tester » du kanban). Voir [v1-mediatheque-plan.md](v1-mediatheque-plan.md).
- **Livrés** — export PDF des stats à la demande, historique 13 mois pour tous les plans, refonte de l'écran Statistiques (⚠️ jamais ouvert dans un navigateur).
- **V2** — module Studio (génération IA d'images), Personnages (une entité `Persona` unifiant trois plans), TTS pré-généré, kiosk web, VR Meta Quest, import IA + RAG. 🛠️ **Studio : lots 0 à 6 codés et commités (branche `studio`, pas encore poussée), calibrage §9.4 fait le 2026-09-15** (≈ 3 $ réels, unité de crédit arrêtée : 1 crédit = 0,015 $ de coût fal, prix de vente avec marge). Lot 7 : échantillons de style et figures d'archétypes embarqués, reste l'écoute des voix. **Lots 8 et 8bis codés et commités le 2026-09-15, jamais exécutés en réel** — narrateurs assignables et chaîne de résolution, génération audio Gemini TTS → MP3 (1 crédit par minute, état « à régénérer »), onglet Narrateurs du parcours, blocs sur l'article et le point de carte, cartes Narration et Personnages dans l'écran Configuration, portrait du narrateur et écran « les personnes que vous allez rencontrer » sur les trois apps visiteur. ⚠️ Au passage, les apps visiteur ne jouaient pas un audio rangé par identifiant de ressource — corrigé. **À faire** : passer [test-plan-studio-narration.md](test-plan-studio-narration.md) (clé Gemini + ffmpeg), extraits d'écoute des voix, lecteur audio d'un point de carte côté visiteur, test du conservateur (gate lot 4), push de la branche `studio`. Le prérequis « le backend ne sait pas écrire dans le bucket » est levé depuis le lot 0.
- **V2** — module Studio (génération IA d'images), Personnages (une entité `Persona` unifiant trois plans), TTS pré-généré, kiosk web, VR Meta Quest, import IA + RAG. 🛠️ **Studio : lots 0 à 6 codés et commités (branche `studio`, pas encore poussée), calibrage §9.4 fait le 2026-09-15** (≈ 3 $ réels, unité de crédit arrêtée : 1 crédit = 0,015 $ de coût fal, prix de vente avec marge). Lot 7 : échantillons de style et figures d'archétypes embarqués, reste l'écoute des voix. **Lots 8 et 8bis codés et commités le 2026-09-15, jamais exécutés en réel** — narrateurs assignables et chaîne de résolution, génération audio Gemini TTS → MP3 (1 crédit par minute, état « à régénérer »), onglet Narrateurs du parcours, blocs sur l'article et le point de carte, cartes Narration et Personnages dans l'écran Configuration, portrait du narrateur et écran « les personnes que vous allez rencontrer » sur les trois apps visiteur, lecteur audio dans la fiche d'un point de carte (lot 8e, ajouté le même soir). ⚠️ Au passage, les apps visiteur ne jouaient pas un audio rangé par identifiant de ressource — corrigé. **À faire** : passer [test-plan-studio-narration.md](test-plan-studio-narration.md) (clé Gemini + ffmpeg), extraits d'écoute des voix, test du conservateur (gate lot 4), push de la branche `studio`. Le prérequis « le backend ne sait pas écrire dans le bucket » est levé depuis le lot 0.
- 📄 **La frontière entre le Studio IA et le canal XR est tranchée depuis le 2026-09-11** : [v2/immersif-frontiere-plan.md](v2/immersif-frontiere-plan.md). Les deux plans se renvoyaient la balle (le Studio mettait la 3D en « dépend du chantier VR », le plan VR décrivait les POI sur GLB sans dire d'où venait le GLB). Trois couches : ressources immersives (360/GLB, **se vendent sans casque**), consommation, et le Studio comme *source d'approvisionnement* de la première. **Cinq décisions de rétro-compat touchent des lots antérieurs à la 3D** — à lire avant la première migration du Studio, pas en arrivant au lot 11.
- ✅ **Le backend du canal XR est fait le 2026-09-11** (lot `XR-1` de [v2/vr-quest-unity-plan.md](v2/vr-quest-unity-plan.md)) : `Device.AppType` + migration, `DeviceController` résout l'`ApplicationInstance` sur le canal au lieu de `Tablet` en dur, `Get` filtre par canal, `ApiKeyAppType.VrApp`, `appType` dans `manager_api_new`. 224 tests au vert. Et **`XR-3` était déjà fait** — l'export est ouvert aux apps depuis `9cc45c5`, le plan était en retard sur le code.
- ✅ **`XR-2` fait le 2026-09-12 — le canal VR est administrable.** L'écran XR est une coquille à deux sous-onglets : « Configuration » réutilise `AppConfigurationLinkScreen` tel quel (déjà générique sur l'`appType`, zéro code neuf), « Casques » est la grille avec pincode d'appairage, état connecté, batterie, version et dernier vu. i18n FR/EN/NL. ⚠️ Deux affirmations du plan étaient fausses : la grille kiosk liste des `AppConfigurationLink`, pas des `Device` (le filtre par canal était déjà implicite, et le paramètre `appType` de `/api/device` ne sert pas à cet écran), et batterie/version/dernier vu ne sont que dans `DeviceDetailDTO` — donc un appel de détail par casque, assumé sur une flotte qui se compte en unités. Ne restent que deux puces documentaires de `XR-3` (contrat d'export versionné, décision multilingue).

View File

@ -1102,7 +1102,7 @@
<article class="card" data-area="visitapp backend" data-horizon="v2">
<div class="card-meta"><span class="tag">3 repos</span><span class="tag">Studio IA</span><span class="flag f-good">V2 · lots 8 et 8bis codés le 15/09, à tester</span></div>
<h3>Personnages — un objet, quatre facettes</h3>
<p><strong>Lot 8 et 8bis codés le 15/09, à tester</strong> (plan : <code>test-plan-studio-narration.md</code>). Narrateurs assignables (étape, point, article ; défaut parcours, carte, visite ; guide par visite) avec la chaîne de § 3.8 ; génération audio Gemini TTS → MP3, 1 crédit par minute, état « à régénérer » sur changement de texte ou de voix ; onglet Narrateurs du parcours, blocs sur l'article et le point, carte Narration et casting dans l'écran Configuration ; portrait du narrateur à côté du lecteur et écran « les personnes que vous allez rencontrer » sur les trois apps visiteur. <strong>Reste</strong> : les extraits d'écoute des voix (clé Gemini), le lecteur audio d'un point de carte côté visiteur.</p>
<p><strong>Lot 8 et 8bis codés le 15/09, à tester</strong> (plan : <code>test-plan-studio-narration.md</code>). Narrateurs assignables (étape, point, article ; défaut parcours, carte, visite ; guide par visite) avec la chaîne de § 3.8 ; génération audio Gemini TTS → MP3, 1 crédit par minute, état « à régénérer » sur changement de texte ou de voix ; onglet Narrateurs du parcours, blocs sur l'article et le point, carte Narration et casting dans l'écran Configuration ; portrait du narrateur à côté du lecteur et écran « les personnes que vous allez rencontrer » sur les trois apps visiteur. <strong>Reste</strong> : les extraits d'écoute des voix (clé Gemini). Le lecteur audio d'un point de carte côté visiteur a été ajouté au lot (8e).</p>
<p>🛠️ <strong>Lot 7 en cours (15/09).</strong> Entité <code>Persona</code>, écran Personnages, <code>TtsVoice</code> en base, migration des colonnes <code>Instance.Guide*</code> faits. Figures des 12 archétypes générées et embarquées. <strong>Reste</strong> : l'écoute des voix (échantillons audio à produire, pas de clé Gemini en local), puis le lot 8 (narration attribuée).</p>
<p><strong>Trois plans décrivaient le même objet sans se croiser</strong> (relevé le 01-02/09) : le canon visuel (<code>studio-plan.md</code>), les 3 frames de lipsync (<code>talking-head-plan.md</code>) et <code>PersonaConfig { WakewordId, GuideName, PersonaPrompt, VoiceName }</code> (<code>tts-pregenerated-plan.md</code>). Une entité <code>Persona</code> les remplace : identité, visage (canon en <em>jeu de vues</em>), voix + intonation, parole.</p>
<p><strong>Le talking head est abandonné, sa dépendance était déjà cassée.</strong> <code>talking-head-plan.md:11</code> anime ses frames « selon les timestamps retournés par <strong>Google Cloud TTS</strong> » (<code>enable_time_pointing</code>) — or le code livré tourne sur <strong>Gemini TTS</strong> (<code>GeminiTtsEngine</code>, <code>gemini-2.5-flash-preview-tts</code>) : aucune source de timestamps. Remplacé par le <strong>portrait canon statique</strong> à côté du lecteur audio, puis une boucle vidéo 6-8 s si du mouvement est voulu. En-tête d'abandon posé sur le fichier.</p>

View File

@ -6,7 +6,7 @@ tags: 3 repos, Studio IA
flag: good | V2 · lots 8 et 8bis codés le 15/09, à tester
src: v2/studio-plan.md §3.8 — lots 7 et 8
---
<p><strong>Lot 8 et 8bis codés le 15/09, à tester</strong> (plan : <code>test-plan-studio-narration.md</code>). Narrateurs assignables (étape, point, article ; défaut parcours, carte, visite ; guide par visite) avec la chaîne de § 3.8 ; génération audio Gemini TTS → MP3, 1 crédit par minute, état « à régénérer » sur changement de texte ou de voix ; onglet Narrateurs du parcours, blocs sur l'article et le point, carte Narration et casting dans l'écran Configuration ; portrait du narrateur à côté du lecteur et écran « les personnes que vous allez rencontrer » sur les trois apps visiteur. <strong>Reste</strong> : les extraits d'écoute des voix (clé Gemini), le lecteur audio d'un point de carte côté visiteur.</p>
<p><strong>Lot 8 et 8bis codés le 15/09, à tester</strong> (plan : <code>test-plan-studio-narration.md</code>). Narrateurs assignables (étape, point, article ; défaut parcours, carte, visite ; guide par visite) avec la chaîne de § 3.8 ; génération audio Gemini TTS → MP3, 1 crédit par minute, état « à régénérer » sur changement de texte ou de voix ; onglet Narrateurs du parcours, blocs sur l'article et le point, carte Narration et casting dans l'écran Configuration ; portrait du narrateur à côté du lecteur et écran « les personnes que vous allez rencontrer » sur les trois apps visiteur. <strong>Reste</strong> : les extraits d'écoute des voix (clé Gemini). Le lecteur audio d'un point de carte côté visiteur a été ajouté au lot (8e).</p>
<p>🛠️ <strong>Lot 7 en cours (15/09).</strong> Entité <code>Persona</code>, écran Personnages, <code>TtsVoice</code> en base, migration des colonnes <code>Instance.Guide*</code> faits. Figures des 12 archétypes générées et embarquées. <strong>Reste</strong> : l'écoute des voix (échantillons audio à produire, pas de clé Gemini en local), puis le lot 8 (narration attribuée).</p>
<p><strong>Trois plans décrivaient le même objet sans se croiser</strong> (relevé le 01-02/09) : le canon visuel (<code>studio-plan.md</code>), les 3 frames de lipsync (<code>talking-head-plan.md</code>) et <code>PersonaConfig { WakewordId, GuideName, PersonaPrompt, VoiceName }</code> (<code>tts-pregenerated-plan.md</code>). Une entité <code>Persona</code> les remplace : identité, visage (canon en <em>jeu de vues</em>), voix + intonation, parole.</p>
<p><strong>Le talking head est abandonné, sa dépendance était déjà cassée.</strong> <code>talking-head-plan.md:11</code> anime ses frames « selon les timestamps retournés par <strong>Google Cloud TTS</strong> » (<code>enable_time_pointing</code>) — or le code livré tourne sur <strong>Gemini TTS</strong> (<code>GeminiTtsEngine</code>, <code>gemini-2.5-flash-preview-tts</code>) : aucune source de timestamps. Remplacé par le <strong>portrait canon statique</strong> à côté du lecteur audio, puis une boucle vidéo 6-8 s si du mouvement est voulu. En-tête d'abandon posé sur le fichier.</p>

View File

@ -1,7 +1,7 @@
# Plan de test — Studio lots 6 à 8 (mention IA, calibrage, narration)
# Plan de test — Studio lots 6 à 8 (mention IA, calibrage, narration, casting)
> Écrit le 2026-09-15, pour une première passe le 16/09. **Rien de ce plan n'a encore tourné en réel** :
> tout est couvert par des tests unitaires (353 verts côté service) et l'analyse Flutter / TypeScript, mais
> tout est couvert par des tests unitaires (357 verts côté service) et l'analyse Flutter / TypeScript, mais
> aucun écran n'a été affiché et aucun audio n'a été généré. Les résultats viennent de Thomas, pas du code.
>
> Légende : colonne ✓ à remplir (✅ / ❌ + une note). Un ❌ dans § 0 arrête la suite.
@ -15,7 +15,7 @@
|---|---|---|---|
| 0.1 | `winget install Gyan.FFmpeg`, rouvrir le terminal, `ffmpeg -version` | Une version s'affiche. Sans ffmpeg, la génération audio échoue et les crédits sont remboursés | |
| 0.2 | `dotnet user-secrets set "AI:ApiKey" "<clé Gemini>" --project manager-service/ManagerService` | `dotnet user-secrets list` montre `AI:ApiKey` (et `Studio:Fal:Key`) | |
| 0.3 | Lancer Postgres puis `dotnet ef database update` avec `MIGRATIONS_CONNECTION` (voir la note mémoire EF) | Migrations appliquées : `AddAiWatermarkBurned`, `StudioCalibrationEngravingStyle`, `StudioCreditUnitPerReference`, `AddNarrators`, `AddGeoPointAudio` | |
| 0.3 | Lancer Postgres puis `dotnet ef database update` avec `MIGRATIONS_CONNECTION` (voir la note mémoire EF) | Migrations appliquées : `AddAiWatermarkBurned`, `StudioCalibrationEngravingStyle`, `StudioCreditUnitPerReference`, `AddNarrators`, `AddGeoPointAudio`, `AddCasting` | |
| 0.4 | `dotnet run` (manager-service), `flutter run -d chrome` (manager-app) | Les deux démarrent, connexion SuperAdmin OK | |
| 0.5 | Dialogue d'instance (SuperAdmin) : assistant **et** Studio activés, **100 crédits** accordés | Solde 100 dans la jauge du menu | |
| 0.6 | Guide IA Personnages : un personnage **Léon** avec une **voix** (Umbriel) et une intonation, un second **La sentinelle** avec une autre voix (Kore) | Les deux apparaissent dans la liste, sans « (sans voix) » | |
@ -89,7 +89,10 @@ Préparer une configuration avec un **parcours de 4 étapes** (titre + descripti
| 4.12b | Carte : réglages de la section, **Narrateur par défaut des points** = La sentinelle, enregistrer la section | Chaque fiche de point affiche « ↳ La sentinelle » dans son bloc Narration audio | |
| 4.12c | Carte : ouvrir un point, choisir **Léon** dans son bloc Narration audio | Le point s'enregistre seul ; moins d'une seconde après, l'état se relit (Léon, « à générer ») | |
| 4.12d | Carte : générer l'audio d'un point, puis modifier son titre | L'audio reste rattaché au point après rechargement ; l'état passe « à régénérer » | |
| 4.12e | web + mymuseum-visitapp : ouvrir ce point | ⚠️ Non prévu en 8d : le visiteur n'a pas encore de lecteur audio sur un point de carte — noter ce que tu vois | |
| 4.12e | web : ouvrir ce point sur la carte | Lecteur audio en tête de la fiche, portrait + nom du narrateur au-dessus (lot 8e) | |
| 4.12f | mymuseum-visitapp : ouvrir ce point | Lecteur audio au-dessus de la description, portrait + nom | |
| 4.12g | tablet-app : ouvrir ce point | Portrait + nom à gauche du bouton de lecture | |
| 4.12h | Les trois : langue sans audio pour ce point | Pas de lecteur sur mobile et tablette (pas de repli de langue) ; le web retombe sur la première langue, comme pour l'article | |
| 4.13 | Article : générer, puis **Enregistrer** la section après le passage à « Audio à jour » | L'audio reste sur l'article après rechargement | |
| 4.14 | Personnage **sans voix** en narrateur, Générer | Message « Ce narrateur n'a pas de voix », aucun crédit réservé | |
| 4.15 | Solde à 0, Générer | Message « Crédits Studio insuffisants » | |

View File

@ -1468,7 +1468,7 @@ Le lot « Bastogne » : plusieurs personnages qui racontent chacun leurs station
coût de régénération par ligne, rien de régénéré avant validation.
- Côté visiteur : portrait canon statique à côté du lecteur audio.
> **Découpage du 2026-09-15.** **8a — fait** : `NarratorPersonaId` (étape, point, article), `DefaultNarratorPersonaId` (parcours, carte, configuration), `Configuration.GuidePersonaId`, `NarratorResolver` (chaîne de §3.8, source renvoyée pour distinguer hérité / choisi, personnage archivé sauté), migration `AddNarrators`, DTO serveur et Dart. **8b — fait** (décisions de Thomas du 15/09 : bouton explicite, crédits Studio, MP3 via ffmpeg) : `NarrationService` + `api/Narration/{kind}/{id}` (état par langue : absent / à jour / à régénérer / déposé à la main) et `/generate` (réserve, job Hangfire, `Resource` audio `Generated`, ancienne narration supprimée, fichier déposé gardé). Gemini 2.5 Flash TTS ≈ 0,015 $/min = **1 crédit par minute entamée**, par langue. Empreinte texte + personnage + version de voix dans `AiProvenance`. `GeoPoint.AudioIds` ajouté. ⚠️ Jamais exécuté contre Gemini ni ffmpeg réels : pas de clé ni de ffmpeg en local. **8c — fait côté parcours** : onglet « Narrateurs » dans l'éditeur de parcours (défaut du parcours, surcharge par étape en gris hérité / gras choisi, « toutes les étapes suivent le défaut » confirmé, état et coût par ligne, total confirmé avant génération), `NarrationApi` écrit à la main. Puis, même jour : bloc « Narration audio » sur l'article (narrateur, état, génération), carte « Narration » de l'écran Configuration (guide de la visite, narrateur par défaut), onglet et bloc masqués sans Studio. ⚠️ Piège corrigé : l'étape et l'article gardent leur liste d'audios en local, un enregistrement après génération détachait la narration — le client recopie les audios rangés par le serveur à chaque relecture et relit toutes les 5 s après une génération (3 min max). Puis **les points de carte** : narrateur par défaut dans les réglages de la carte, bloc Narration audio dans la fiche du point (éditeur `GeoPointEditor`, l'ancienne fenêtre n'est plus utilisée) ; les audios rangés sont recopiés en local sans relancer d'enregistrement. ⚠️ **Côté visiteur, un point de carte n'a pas de lecteur audio** : l'audio généré existe mais ne s'entend pas encore sur les trois apps. ⚠️ Écran jamais affiché : analysé, pas lancé. **8d — fait** : `ResourceDTO.narratorName` / `narratorPortraitUrl` remplis pour un audio narré (depuis sa provenance, donc la voix réellement entendue) sur le détail de ressource et l'export ; portrait + nom à côté du lecteur sur web (article, parcours liste et carte), mymuseum-visitapp (article en ligne, parcours contenu et carte) et tablet-app (article). ⚠️ Bug trouvé au passage : les deux apps visiteur ne lisaient l'audio d'une étape que si `audioIds` portait une **URL**, et le web lisait l'article de même — un audio rangé par identifiant n'avait jamais de lecteur. Résolu par l'identifiant de ressource. Hors ligne : pas de portrait. Plan de test : [../test-plan-studio-narration.md](../test-plan-studio-narration.md).
> **Découpage du 2026-09-15.** **8a — fait** : `NarratorPersonaId` (étape, point, article), `DefaultNarratorPersonaId` (parcours, carte, configuration), `Configuration.GuidePersonaId`, `NarratorResolver` (chaîne de §3.8, source renvoyée pour distinguer hérité / choisi, personnage archivé sauté), migration `AddNarrators`, DTO serveur et Dart. **8b — fait** (décisions de Thomas du 15/09 : bouton explicite, crédits Studio, MP3 via ffmpeg) : `NarrationService` + `api/Narration/{kind}/{id}` (état par langue : absent / à jour / à régénérer / déposé à la main) et `/generate` (réserve, job Hangfire, `Resource` audio `Generated`, ancienne narration supprimée, fichier déposé gardé). Gemini 2.5 Flash TTS ≈ 0,015 $/min = **1 crédit par minute entamée**, par langue. Empreinte texte + personnage + version de voix dans `AiProvenance`. `GeoPoint.AudioIds` ajouté. ⚠️ Jamais exécuté contre Gemini ni ffmpeg réels : pas de clé ni de ffmpeg en local. **8c — fait côté parcours** : onglet « Narrateurs » dans l'éditeur de parcours (défaut du parcours, surcharge par étape en gris hérité / gras choisi, « toutes les étapes suivent le défaut » confirmé, état et coût par ligne, total confirmé avant génération), `NarrationApi` écrit à la main. Puis, même jour : bloc « Narration audio » sur l'article (narrateur, état, génération), carte « Narration » de l'écran Configuration (guide de la visite, narrateur par défaut), onglet et bloc masqués sans Studio. ⚠️ Piège corrigé : l'étape et l'article gardent leur liste d'audios en local, un enregistrement après génération détachait la narration — le client recopie les audios rangés par le serveur à chaque relecture et relit toutes les 5 s après une génération (3 min max). Puis **les points de carte** : narrateur par défaut dans les réglages de la carte, bloc Narration audio dans la fiche du point (éditeur `GeoPointEditor`, l'ancienne fenêtre n'est plus utilisée) ; les audios rangés sont recopiés en local sans relancer d'enregistrement. ⚠️ **Côté visiteur, un point de carte n'avait pas de lecteur audio** : l'audio généré existait sans s'entendre. **8e — ajouté au lot le 2026-09-15** : lecteur audio (et portrait du narrateur) dans la fiche d'un point sur les trois apps visiteur, dans la langue de visite, par l'identifiant de ressource. ⚠️ Écran jamais affiché : analysé, pas lancé. **8d — fait** : `ResourceDTO.narratorName` / `narratorPortraitUrl` remplis pour un audio narré (depuis sa provenance, donc la voix réellement entendue) sur le détail de ressource et l'export ; portrait + nom à côté du lecteur sur web (article, parcours liste et carte), mymuseum-visitapp (article en ligne, parcours contenu et carte) et tablet-app (article). ⚠️ Bug trouvé au passage : les deux apps visiteur ne lisaient l'audio d'une étape que si `audioIds` portait une **URL**, et le web lisait l'article de même — un audio rangé par identifiant n'avait jamais de lecteur. Résolu par l'identifiant de ressource. Hors ligne : pas de portrait. Plan de test : [../test-plan-studio-narration.md](../test-plan-studio-narration.md).
### Lot 8bis — Casting visiteur *(petit, juste après le lot 8)*