Studio : lot 8f (VR) et repasse des lots 0 à 8 côté casque

Carte 315 : mention IA du lot 6 absente en VR, audio narré et casting à porter, couture ScenePersona vers Persona, Parcours probablement vide sur le casque (à vérifier). Plan et STATUS à 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:06:50 +02:00
parent 78517cb38f
commit d879766cae
4 changed files with 56 additions and 4 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, 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.
- **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, lot 8f (la narration et le casting dans l'app VR, carte 315), 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

@ -462,7 +462,7 @@
<div class="stat"><span class="n n-info">1</span><span class="k">Migration v3</span></div>
<div class="stat"><span class="n n-warn">2</span><span class="k">Bugs ouverts</span></div>
<div class="stat"><span class="n">12</span><span class="k">À tester</span></div>
<div class="stat"><span class="n">39</span><span class="k">Planifié</span></div>
<div class="stat"><span class="n">40</span><span class="k">Planifié</span></div>
<div class="stat"><span class="n n-gate">9</span><span class="k">Bascule prod</span></div>
<div class="stat"><span class="n n-good">66</span><span class="k">Fait récemment</span></div>
</section>
@ -706,7 +706,7 @@
<!-- PLANIFIÉ -->
<section class="col" style="--stripe: var(--ink-3)">
<div class="col-head"><h2>Planifié</h2><span class="count">39</span></div>
<div class="col-head"><h2>Planifié</h2><span class="count">40</span></div>
<div class="stack">
<article class="card" data-area="visitapp" data-horizon="v1">
@ -1117,6 +1117,31 @@
<span class="src">v2/studio-plan.md §3.8 — lots 7 et 8</span>
</article>
<article class="card" data-area="vr backend" data-horizon="v2">
<div class="card-meta"><span class="tag">VR</span><span class="tag">Studio IA</span><span class="flag f-warn">V2 · après le test du lot 8 sur les trois apps, avec le casque</span></div>
<h3>Studio dans l'app VR — mention IA, narration, casting (lot 8f)</h3>
<p><strong>Le lot 8 (narrateurs, audio généré, portrait, casting) a été livré sur les trois apps visiteur — web, mobile, tablette — mais pas sur l'app Quest</strong>, qui lit pourtant le contenu par l'export de configuration (<code>ConfigurationExport.cs</code>). Relevé le 2026-09-15.</p>
<p><strong>Ce que fait la VR aujourd'hui</strong> : Map et Parcours rendus en liste de points, sans lire <code>audioIds</code> ; hotspots de maquette 3D dont l'audio vient des <em>contenus</em> du point, pas de l'audio par langue ; ni portrait du narrateur, ni écran « les personnes que vous allez rencontrer ».</p>
<p><strong>À faire</strong> :</p>
<ol>
<li>Export Unity : <code>audioIds</code> des points et des étapes, <code>narratorName</code> / <code>narratorPortraitUrl</code> sur la ressource, <code>casting</code> de la configuration.</li>
<li>Lecture de l'audio narré d'un point et d'une étape, portrait à côté (audio spatialisé sur un hotspot).</li>
<li>Serveur : rendre narrables les points d'une maquette 3D — la section maquette comme conteneur dans la chaîne de <code>NarratorResolver</code> (aujourd'hui, un point sans <code>SectionMapId</code> est refusé par <code>NarrationService</code>).</li>
<li>Écran d'entrée du casting au lancement de la visite.</li>
</ol>
<p>🔎 <strong>Repasse du 2026-09-15 sur les lots Studio 0 à 8</strong> (code de <code>vr-app</code> relu) — ce qui touche le visiteur et manque au casque :</p>
<ul>
<li><strong>Lot 6, mention « image générée par IA » — manquante.</strong> <code>ConfigurationExport.Resource</code> ne lit pas <code>origin</code> : les images d'un Slider, la photo d'un point et les médias d'un hotspot s'affichent sans mention. <code>ProvenanceManifest.AiGenerated</code> existe dans le manifeste mais rien ne le remplit depuis l'export. À ajouter avec le reste — c'est l'obligation d'information de l'AI Act, pas un confort.</li>
<li><strong>Lot 8, audio narré — manquant</strong> (points 1 et 2 ci-dessus). Le commentaire d'un hotspot vient de ses <em>contenus</em> ; la narration écrit dans <code>audioIds</code>, que le casque ne lit pas.</li>
<li><strong>Lot 8bis, casting — manquant</strong> (point 4).</li>
<li><strong>Lot 7, personnages — couture prévue, pas faite.</strong> <code>ScenePersona.PersonaId</code> est « null en V1, la couture vers l'entité <code>Persona</code> » : les personnages GLB d'une scène ne sont pas reliés aux fiches Personnages (nom, portrait, voix). Relève plutôt du lot 11 (3D).</li>
<li><strong>Sans objet</strong> : lots 0 à 5 (serveur et manager), crédits et calibrage. Le correctif « audio rangé par identifiant » de 8d ne s'applique pas : le casque résout déjà ses médias par identifiant via <code>FindResource</code>.</li>
<li><strong>Hors Studio, vu en passant</strong> : un <strong>Parcours</strong> est rendu « comme une Map » à partir de <code>section.Points</code>, or ses étapes vivent dans <code>guidedPaths</code> — un Parcours s'ouvre probablement vide sur le casque. À vérifier casque en main.</li>
</ul>
<p><strong>Pas avant</strong> : que le plan de test <code>test-plan-studio-narration.md</code> soit passé sur les trois autres apps, et avec le casque en main — rien de ceci ne se vérifie sans l'éditeur Unity. Le dépôt <code>vr-app</code> n'a toujours ni remote ni commit.</p>
<span class="src">v2/studio-plan.md — lot 8f</span>
</article>
<article class="card" data-area="produit" data-horizon="v2">
<div class="card-meta"><span class="tag">studio</span><span class="tag">video</span><span class="tag">IA</span><span class="flag f-good">quelques euros, une soirée — débloque une décision produit</span></div>
<h3>Test « faire vivre un lieu » — 8 s au Fourneau</h3>

View File

@ -0,0 +1,27 @@
---
title: Studio dans l'app VR — mention IA, narration, casting (lot 8f)
area: vr backend
horizon: v2
tags: VR, Studio IA
flag: warn | V2 · après le test du lot 8 sur les trois apps, avec le casque
src: v2/studio-plan.md — lot 8f
---
<p><strong>Le lot 8 (narrateurs, audio généré, portrait, casting) a été livré sur les trois apps visiteur — web, mobile, tablette — mais pas sur l'app Quest</strong>, qui lit pourtant le contenu par l'export de configuration (<code>ConfigurationExport.cs</code>). Relevé le 2026-09-15.</p>
<p><strong>Ce que fait la VR aujourd'hui</strong> : Map et Parcours rendus en liste de points, sans lire <code>audioIds</code> ; hotspots de maquette 3D dont l'audio vient des <em>contenus</em> du point, pas de l'audio par langue ; ni portrait du narrateur, ni écran « les personnes que vous allez rencontrer ».</p>
<p><strong>À faire</strong> :</p>
<ol>
<li>Export Unity : <code>audioIds</code> des points et des étapes, <code>narratorName</code> / <code>narratorPortraitUrl</code> sur la ressource, <code>casting</code> de la configuration.</li>
<li>Lecture de l'audio narré d'un point et d'une étape, portrait à côté (audio spatialisé sur un hotspot).</li>
<li>Serveur : rendre narrables les points d'une maquette 3D — la section maquette comme conteneur dans la chaîne de <code>NarratorResolver</code> (aujourd'hui, un point sans <code>SectionMapId</code> est refusé par <code>NarrationService</code>).</li>
<li>Écran d'entrée du casting au lancement de la visite.</li>
</ol>
<p>🔎 <strong>Repasse du 2026-09-15 sur les lots Studio 0 à 8</strong> (code de <code>vr-app</code> relu) — ce qui touche le visiteur et manque au casque :</p>
<ul>
<li><strong>Lot 6, mention « image générée par IA » — manquante.</strong> <code>ConfigurationExport.Resource</code> ne lit pas <code>origin</code> : les images d'un Slider, la photo d'un point et les médias d'un hotspot s'affichent sans mention. <code>ProvenanceManifest.AiGenerated</code> existe dans le manifeste mais rien ne le remplit depuis l'export. À ajouter avec le reste — c'est l'obligation d'information de l'AI Act, pas un confort.</li>
<li><strong>Lot 8, audio narré — manquant</strong> (points 1 et 2 ci-dessus). Le commentaire d'un hotspot vient de ses <em>contenus</em> ; la narration écrit dans <code>audioIds</code>, que le casque ne lit pas.</li>
<li><strong>Lot 8bis, casting — manquant</strong> (point 4).</li>
<li><strong>Lot 7, personnages — couture prévue, pas faite.</strong> <code>ScenePersona.PersonaId</code> est « null en V1, la couture vers l'entité <code>Persona</code> » : les personnages GLB d'une scène ne sont pas reliés aux fiches Personnages (nom, portrait, voix). Relève plutôt du lot 11 (3D).</li>
<li><strong>Sans objet</strong> : lots 0 à 5 (serveur et manager), crédits et calibrage. Le correctif « audio rangé par identifiant » de 8d ne s'applique pas : le casque résout déjà ses médias par identifiant via <code>FindResource</code>.</li>
<li><strong>Hors Studio, vu en passant</strong> : un <strong>Parcours</strong> est rendu « comme une Map » à partir de <code>section.Points</code>, or ses étapes vivent dans <code>guidedPaths</code> — un Parcours s'ouvre probablement vide sur le casque. À vérifier casque en main.</li>
</ul>
<p><strong>Pas avant</strong> : que le plan de test <code>test-plan-studio-narration.md</code> soit passé sur les trois autres apps, et avec le casque en main — rien de ceci ne se vérifie sans l'éditeur Unity. Le dépôt <code>vr-app</code> n'a toujours ni remote ni commit.</p>

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'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).
> **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. **8f — à faire, ajouté le 2026-09-15** : la même chose dans l'app VR, oubliée par le lot (le plan ne visait que trois fronts) — export Unity (`audioIds`, narrateur de la ressource, casting), lecture de l'audio narré d'un point et d'une étape avec le portrait, points de maquette 3D rendus narrables côté serveur (la section maquette comme conteneur), écran d'entrée du casting. **Repasse des lots 0 à 8 le même soir** : manque aussi la **mention IA du lot 6** (l'export Unity ne lit pas `origin`, les images générées s'affichent sans mention) ; la couture `ScenePersona.PersonaId``Persona` (lot 7) reste à faire, plutôt au lot 11 ; et un Parcours semble s'ouvrir vide sur le casque (étapes dans `guidedPaths`, pas dans `points`). Après le test du lot 8 sur les trois apps, avec le casque : carte kanban 315. ⚠️ É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)*