Studio : lot 8d et plan de test de la narration
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011VxSQeGQYUvPmSEoGdnidA
This commit is contained in:
parent
d8d62e7713
commit
f9d5e9cb6b
131
test-plan-studio-narration.md
Normal file
131
test-plan-studio-narration.md
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
# Plan de test — Studio lots 6 à 8 (mention IA, calibrage, narration)
|
||||||
|
|
||||||
|
> É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
|
||||||
|
> 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.
|
||||||
|
> Référence : [v2/studio-plan.md](v2/studio-plan.md) § 9.4 (calibrage) et lot 8.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. Prérequis — une fois
|
||||||
|
|
||||||
|
| # | Étape | Attendu | ✓ |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 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.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) » | |
|
||||||
|
| 0.7 | Donner un **portrait** à Léon (onglet Visage → générer ou choisir une vue Portrait) | La vue Portrait est enregistrée | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Mention IA dans le fichier (lot 6)
|
||||||
|
|
||||||
|
| # | Étape | Attendu | ✓ |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1.1 | Studio : générer une image et la **valider** | L'image arrive dans la médiathèque avec la facette IA | |
|
||||||
|
| 1.2 | Télécharger le fichier validé, l'ouvrir dans un lecteur de métadonnées (ex. exiftool, ou Propriétés › Détails) | XMP `DigitalSourceType = trainedAlgorithmicMedia`, droits = nom de l'instance | |
|
||||||
|
| 1.3 | Dialogue d'instance : cocher **Graver la mention IA**, générer et valider une nouvelle image | Bandeau « Généré par IA · AI-generated » en bas à droite de l'image. L'ancienne image n'a pas changé | |
|
||||||
|
| 1.4 | ⚠️ Enregistrer l'instance **depuis un autre écran** (ex. Abonnement) | La case gravure reste cochée : un enregistrement qui ne l'envoie pas ne la remet pas à faux | |
|
||||||
|
| 1.5 | Décocher la gravure | Les images suivantes n'ont plus de bandeau | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Calibrage et unité de crédit
|
||||||
|
|
||||||
|
| # | Étape | Attendu | ✓ |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 2.1 | Studio › Identité : ouvrir la grille des styles | **8 tuiles avec un moulin**, un style chacune (plus aucune tuile vide) | |
|
||||||
|
| 2.2 | Guide IA › Personnages › Visage : grille des archétypes | **12 mannequins au trait**, un par pose | |
|
||||||
|
| 2.3 | Générer 3 variantes **sans image de référence** | Estimation et débit = **6 crédits** (2 par image) | |
|
||||||
|
| 2.4 | Ajouter 3 images de référence à l'identité, relancer 3 variantes | Estimation = **15 crédits** (3 × (2 + 3)) | |
|
||||||
|
| 2.5 | Style Gravure, gabarit « Décor d'énigme », 3 variantes | Images **noir et blanc**, **aucune légende ni signature** (c'était ~4/10 avant correction) | |
|
||||||
|
| 2.6 | Gabarit « Objet d'époque » depuis une photo d'objet **portant une date** | La date reste gravée sur l'objet | |
|
||||||
|
| 2.7 | Relire les planches `outputs/studio-calibrage-2026-09-15/` | Ton verdict « du même projet » par série, à reporter dans studio-plan § 9.4 | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Qui raconte quoi (lot 8a et 8c)
|
||||||
|
|
||||||
|
Préparer une configuration avec un **parcours de 4 étapes** (titre + description remplis en FR et NL) et un **article** avec du texte.
|
||||||
|
|
||||||
|
| # | Étape | Attendu | ✓ |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 3.1 | Écran Configuration : carte **Narration** visible | Deux champs : « Guide de cette visite » et « Narrateur par défaut de la visite » | |
|
||||||
|
| 3.2 | Guide de la visite = *Guide de l'instance*, narrateur par défaut = *Le guide raconte*, **Enregistrer** | Enregistré ; recharger l'écran garde les valeurs | |
|
||||||
|
| 3.3 | Ouvrir le parcours : dans le rail, une entrée **Narrateurs** sous « Parcours » | L'onglet s'ouvre, une ligne par étape | |
|
||||||
|
| 3.4 | Sans rien choisir | Chaque étape affiche en gris « ↳ » + le guide de l'instance, ou « Aucun narrateur » s'il n'y en a pas | |
|
||||||
|
| 3.5 | Narrateur par défaut du parcours = **Léon** | Toutes les lignes passent à « ↳ Léon » en gris | |
|
||||||
|
| 3.6 | Étape 3 : choisir **La sentinelle** | La ligne 3 affiche La sentinelle **en gras** ; les autres restent « ↳ Léon » | |
|
||||||
|
| 3.7 | Fermer et rouvrir le parcours | Le choix de l'étape 3 et le défaut sont conservés | |
|
||||||
|
| 3.8 | **Toutes les étapes suivent le défaut** | Confirmation « Retirer le narrateur choisi sur 1 étape(s) ? », puis l'étape 3 repasse à « ↳ Léon » | |
|
||||||
|
| 3.9 | Remettre La sentinelle sur l'étape 3 (pour la suite) | — | |
|
||||||
|
| 3.10 | ⚠️ Archiver La sentinelle (Personnages) puis revenir à l'onglet | L'étape 3 retombe sur « ↳ Léon » : un personnage archivé ne parle plus | |
|
||||||
|
| 3.11 | Désarchiver La sentinelle | L'étape 3 la retrouve | |
|
||||||
|
| 3.12 | Instance **sans Studio** (décocher dans le dialogue) | L'entrée Narrateurs disparaît du rail et le bloc Narration de l'article aussi. Réactiver ensuite | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Générer l'audio (lot 8b et 8c)
|
||||||
|
|
||||||
|
| # | Étape | Attendu | ✓ |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 4.1 | Onglet Narrateurs : colonne Audio | « 2 à générer · N crédits » par étape (FR + NL) ; barre du bas « X fichier(s) audio à générer · Y crédits » | |
|
||||||
|
| 4.2 | **Générer l'audio** | Confirmation qui répète le total. Rien ne part avant « Oui » | |
|
||||||
|
| 4.3 | Confirmer | Notification « Génération lancée » ; en moins d'une minute les lignes passent à **Audio à jour** sans rien toucher (relecture toutes les 5 s) | |
|
||||||
|
| 4.4 | Jauge de crédits | Débit ≈ **1 crédit par minute d'audio par langue**, jamais plus que l'estimation affichée | |
|
||||||
|
| 4.5 | Médiathèque, filtre Audio | Un MP3 par étape et par langue, libellé « Léon · titre (FR) », facette IA | |
|
||||||
|
| 4.6 | Écouter un MP3 (étape 3) | Voix de **La sentinelle**, dans la bonne langue, avec l'intonation du personnage | |
|
||||||
|
| 4.7 | ⚠️ **Piège corrigé** : modifier le **titre** d'une étape juste après la génération, attendre l'enregistrement, rouvrir | L'audio de l'étape est **toujours rattaché** (avant correction, l'enregistrement le détachait) | |
|
||||||
|
| 4.8 | Revenir à l'onglet Narrateurs | L'étape modifiée est « 2 à régénérer » : son texte a changé | |
|
||||||
|
| 4.9 | Changer la voix de Léon (Personnages › Voix) | Toutes les étapes de Léon passent « à régénérer » ; celle de La sentinelle reste à jour | |
|
||||||
|
| 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.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 » | |
|
||||||
|
| 4.16 | Couper le réseau du **serveur** vers Gemini (ou mauvaise clé), Générer | Les lignes ne passent jamais à jour, et les crédits réservés sont **remboursés** (jauge) | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Côté visiteur — le portrait du narrateur (lot 8d)
|
||||||
|
|
||||||
|
Même configuration, avec l'audio généré en § 4. Léon a un portrait, La sentinelle non.
|
||||||
|
|
||||||
|
| # | App | Étape | Attendu | ✓ |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| 5.1 | visitapp-web | Ouvrir l'**article** | Le lecteur audio joue ; à la place de « GUIDE AUDIO », **portrait + « Léon »** | |
|
||||||
|
| 5.2 | visitapp-web | Parcours **en liste**, étapes 1 et 3 | L'audio **joue** (avant, un audio rangé par identifiant n'avait pas de lecteur) ; portrait de Léon à l'étape 1, disque neutre + « La sentinelle » à l'étape 3 | |
|
||||||
|
| 5.3 | visitapp-web | Parcours **en carte** (`showMap`) | Même chose dans la vue carte | |
|
||||||
|
| 5.4 | visitapp-web | Changer la langue en NL | L'audio NL joue, même narrateur | |
|
||||||
|
| 5.5 | mymuseum-visitapp (en ligne) | Article | Lecteur replié à droite ; déplié, le **portrait** ouvre la ligne | |
|
||||||
|
| 5.6 | mymuseum-visitapp (en ligne) | Parcours, vue contenu **et** vue carte | L'audio de l'étape joue, portrait + nom au-dessus du lecteur | |
|
||||||
|
| 5.7 | mymuseum-visitapp (**hors ligne**) | Article téléchargé, mode avion | L'audio joue ; **pas de portrait** (limite connue, il n'est pas téléchargé) | |
|
||||||
|
| 5.8 | tablet-app | Article | Portrait + nom à gauche du bouton de lecture | |
|
||||||
|
| 5.9 | Les trois | Un audio **déposé à la main** (pas une narration) | Lecteur habituel, **aucun** portrait | |
|
||||||
|
| 5.10 | Les trois | Une ancienne étape dont l'audio est une **URL** | L'audio joue toujours | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Non-régression
|
||||||
|
|
||||||
|
| # | Étape | Attendu | ✓ |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 6.1 | Guide IA (assistant) : poser une question sur un contenu dont le **titre** contient du gras ou un `&` | Réponse normale, titre cité sans balises ni `&` (le nettoyage HTML de l'assistant est désormais partagé avec la narration) | |
|
||||||
|
| 6.2 | Image générée côté visiteur | Mention « Image générée par IA » toujours présente (lot 6) | |
|
||||||
|
| 6.3 | Enregistrer un article **sans** toucher à la narration | Rien ne change dans ses audios | |
|
||||||
|
| 6.4 | Modifier un point de carte dans l'ancienne fenêtre | Enregistrement OK ; son audio éventuel n'est pas effacé | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Limites connues (pas des bugs)
|
||||||
|
|
||||||
|
- Les **points de carte** n'ont pas encore d'assignation de narrateur ni de bouton Générer dans le manager.
|
||||||
|
- Hors ligne, mymuseum-visitapp ne montre pas le portrait.
|
||||||
|
- Le portrait affiché est le portrait **actuel** du personnage ; le nom et la voix sont ceux de l'audio entendu.
|
||||||
|
- Les extraits d'écoute des voix (lot 7) ne sont pas encore produits.
|
||||||
@ -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.
|
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.
|
- 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** — portrait canon côté visiteur, 3 fronts.
|
> **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).
|
||||||
|
|
||||||
### Lot 8bis — Casting visiteur *(petit, juste après le lot 8)*
|
### Lot 8bis — Casting visiteur *(petit, juste après le lot 8)*
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user