From dff2f6ba3726b2b2795be28ef23de91c042ebb91 Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Tue, 15 Sep 2026 22:47:20 +0200 Subject: [PATCH] =?UTF-8?q?Studio=20:=20lot=208=20boucl=C3=A9=20c=C3=B4t?= =?UTF-8?q?=C3=A9=20manager,=20STATUS,=20kanban=20et=20plan=20de=20test=20?= =?UTF-8?q?=C3=A0=20jour?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_011VxSQeGQYUvPmSEoGdnidA --- STATUS.md | 2 +- kanban.html | 3 ++- .../310-personnages-un-guide-adressable-n-narrateurs.md | 3 ++- test-plan-studio-narration.md | 4 ++++ v2/studio-plan.md | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/STATUS.md b/STATUS.md index 078b075..a0a85a4 100644 --- a/STATUS.md +++ b/STATUS.md @@ -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 en cours : échantillons de style et figures d'archétypes embarqués ; reste l'écoute des voix (clé Gemini absente en local). 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. ⚠️ 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. - 📄 **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). diff --git a/kanban.html b/kanban.html index e2f8851..6b99a5d 100644 --- a/kanban.html +++ b/kanban.html @@ -1100,8 +1100,9 @@
-
3 reposStudio IAV2 · remplace le talking head
+
3 reposStudio IAV2 · lots 8 et 8bis codés le 15/09, à tester

Personnages — un objet, quatre facettes

+

Lot 8 et 8bis codés le 15/09, à tester (plan : test-plan-studio-narration.md). 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. Reste : les extraits d'écoute des voix (clé Gemini), le lecteur audio d'un point de carte côté visiteur.

🛠️ Lot 7 en cours (15/09). Entité Persona, écran Personnages, TtsVoice en base, migration des colonnes Instance.Guide* faits. Figures des 12 archétypes générées et embarquées. Reste : l'écoute des voix (échantillons audio à produire, pas de clé Gemini en local), puis le lot 8 (narration attribuée).

Trois plans décrivaient le même objet sans se croiser (relevé le 01-02/09) : le canon visuel (studio-plan.md), les 3 frames de lipsync (talking-head-plan.md) et PersonaConfig { WakewordId, GuideName, PersonaPrompt, VoiceName } (tts-pregenerated-plan.md). Une entité Persona les remplace : identité, visage (canon en jeu de vues), voix + intonation, parole.

Le talking head est abandonné, sa dépendance était déjà cassée. talking-head-plan.md:11 anime ses frames « selon les timestamps retournés par Google Cloud TTS » (enable_time_pointing) — or le code livré tourne sur Gemini TTS (GeminiTtsEngine, gemini-2.5-flash-preview-tts) : aucune source de timestamps. Remplacé par le portrait canon statique à 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.

diff --git a/kanban/cards/5-planifie/310-personnages-un-guide-adressable-n-narrateurs.md b/kanban/cards/5-planifie/310-personnages-un-guide-adressable-n-narrateurs.md index 3f8e853..2e12671 100644 --- a/kanban/cards/5-planifie/310-personnages-un-guide-adressable-n-narrateurs.md +++ b/kanban/cards/5-planifie/310-personnages-un-guide-adressable-n-narrateurs.md @@ -3,9 +3,10 @@ title: Personnages — un objet, quatre facettes area: visitapp backend horizon: v2 tags: 3 repos, Studio IA -flag: warn | V2 · remplace le talking head +flag: good | V2 · lots 8 et 8bis codés le 15/09, à tester src: v2/studio-plan.md §3.8 — lots 7 et 8 --- +

Lot 8 et 8bis codés le 15/09, à tester (plan : test-plan-studio-narration.md). 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. Reste : les extraits d'écoute des voix (clé Gemini), le lecteur audio d'un point de carte côté visiteur.

🛠️ Lot 7 en cours (15/09). Entité Persona, écran Personnages, TtsVoice en base, migration des colonnes Instance.Guide* faits. Figures des 12 archétypes générées et embarquées. Reste : l'écoute des voix (échantillons audio à produire, pas de clé Gemini en local), puis le lot 8 (narration attribuée).

Trois plans décrivaient le même objet sans se croiser (relevé le 01-02/09) : le canon visuel (studio-plan.md), les 3 frames de lipsync (talking-head-plan.md) et PersonaConfig { WakewordId, GuideName, PersonaPrompt, VoiceName } (tts-pregenerated-plan.md). Une entité Persona les remplace : identité, visage (canon en jeu de vues), voix + intonation, parole.

Le talking head est abandonné, sa dépendance était déjà cassée. talking-head-plan.md:11 anime ses frames « selon les timestamps retournés par Google Cloud TTS » (enable_time_pointing) — or le code livré tourne sur Gemini TTS (GeminiTtsEngine, gemini-2.5-flash-preview-tts) : aucune source de timestamps. Remplacé par le portrait canon statique à 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.

diff --git a/test-plan-studio-narration.md b/test-plan-studio-narration.md index f61899d..b8de9c4 100644 --- a/test-plan-studio-narration.md +++ b/test-plan-studio-narration.md @@ -86,6 +86,10 @@ Préparer une configuration avec un **parcours de 4 étapes** (titre + descripti | 4.10 | Régénérer | L'ancien MP3 **disparaît** de la médiathèque, le nouveau le remplace | | | 4.11 | Étape avec un **audio déposé à la main** en FR, puis générer FR | L'audio généré prend sa place dans l'étape, **le fichier déposé reste** dans la médiathèque | | | 4.12 | Article : bloc **Narration audio** sous les réglages audio | Narrateur « ↳ Léon » (hérité), état, bouton Générer | | +| 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.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 » | | diff --git a/v2/studio-plan.md b/v2/studio-plan.md index 1355533..ef6a7e3 100644 --- a/v2/studio-plan.md +++ b/v2/studio-plan.md @@ -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). **Reste** : les points de carte (fenêtre ancienne, sans champ audio). ⚠️ É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'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). ### Lot 8bis — Casting visiteur *(petit, juste après le lot 8)*