Studio : lots 5-6 et calibrage §9.4 consignés, unité de crédit, lot 7 en cours
Résultats du calibrage (61 générations, coûts recoupés sur l'export fal), trois corrections de prompt, unité 1 crédit = 0,015 $ vendue avec marge, échantillons et figures d'archétypes embarqués ; planches contact dans outputs/studio-calibrage-2026-09-15. STATUS, roadmap, cartes 280 et 310 à jour. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011VxSQeGQYUvPmSEoGdnidA
@ -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).
|
- **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).
|
- **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. ⛔ **Prérequis dur commun au Studio et au TTS** : le backend ne sait pas écrire dans le bucket (`IResourceBlobService` n'a que `DeleteAsync`).
|
- **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.
|
||||||
- 📄 **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.
|
- 📄 **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.
|
- ✅ **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).
|
- ✅ **`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).
|
||||||
|
|||||||
@ -984,8 +984,9 @@
|
|||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article class="card" data-area="backend manager" data-horizon="v2">
|
<article class="card" data-area="backend manager" data-horizon="v2">
|
||||||
<div class="card-meta"><span class="tag">Studio IA</span><span class="flag f-good">V2 · lots 0-4 codés le 13/09, gate à passer</span></div>
|
<div class="card-meta"><span class="tag">Studio IA</span><span class="flag f-good">V2 · lots 0-6 codés, calibrage fait le 15/09, gate conservateur à passer</span></div>
|
||||||
<h3>Module Studio — génération d'images sous identité visuelle</h3>
|
<h3>Module Studio — génération d'images sous identité visuelle</h3>
|
||||||
|
<p>✅ <strong>15/09 : lots 5 et 6 codés, calibrage §9.4 fait.</strong> Mention IA dans le fichier (XMP IPTC) + gravure en option. Calibrage sur 61 générations (Fourneau en gravure, Fort en aquarelle) : trois défauts corrigés avant tout client — négatif en double négation, titre de fiche recopié en légende, date d'un objet effacée. Coût réel fal : 0,03 $ l'image + 0,015 $ par référence ; <strong>unité arrêtée : 1 crédit = 0,015 $ de coût</strong>, vendu avec marge (≈ 0,05 €). Planches dans <code>outputs/studio-calibrage-2026-09-15/</code>. <strong>Reste</strong> : jugement visuel de Thomas, test du conservateur (gate lot 4), push de la branche.</p>
|
||||||
<p>🛠️ <strong>Lots 0 à 4 codés le 13/09</strong> sur la branche <code>studio</code> (manager-service, manager-app, mymuseum-visitapp) : ingestion serveur, crédits, identité visuelle (menu <strong>Studio</strong>), génération fal.ai derrière <code>IGenerationProvider</code> (fournisseur interchangeable), onglet <strong>Générer</strong> dans le sélecteur de ressource, image d'étape rattachée à une ressource. <strong>Reste avant le gate</strong> : bucket de dev + CORS, clé fal.ai (<code>Studio__Fal__Key</code>), migrations appliquées, calibrage et prix (§9.4), puis le test du conservateur.</p>
|
<p>🛠️ <strong>Lots 0 à 4 codés le 13/09</strong> sur la branche <code>studio</code> (manager-service, manager-app, mymuseum-visitapp) : ingestion serveur, crédits, identité visuelle (menu <strong>Studio</strong>), génération fal.ai derrière <code>IGenerationProvider</code> (fournisseur interchangeable), onglet <strong>Générer</strong> dans le sélecteur de ressource, image d'étape rattachée à une ressource. <strong>Reste avant le gate</strong> : bucket de dev + CORS, clé fal.ai (<code>Studio__Fal__Key</code>), migrations appliquées, calibrage et prix (§9.4), puis le test du conservateur.</p>
|
||||||
<p>✅ <strong>Plan consolidé le 13/09.</strong> Le §8 donne, pour les lots 0 à 4, les prérequis, les étapes, les vérifications et le gate. Le §9 contient un catalogue v0 (8 styles, règle de préambule, 3 gabarits) à calibrer en fin de lot 3. Six décisions ont été prises : <strong>upload par URL signée + ingestion serveur</strong> (bucket fermé aux clients, gros fichiers hors VPS), MVP limité à « depuis le texte » et « depuis une image » (objets et lieux), prix différés avec <code>Grant</code> manuel, une recharge qui prolonge tout le solde, plafonds d'upload prudents, catalogue calibré au lot 3. Le webhook fal.ai est signé en <strong>ED25519, pas en HMAC</strong>.</p>
|
<p>✅ <strong>Plan consolidé le 13/09.</strong> Le §8 donne, pour les lots 0 à 4, les prérequis, les étapes, les vérifications et le gate. Le §9 contient un catalogue v0 (8 styles, règle de préambule, 3 gabarits) à calibrer en fin de lot 3. Six décisions ont été prises : <strong>upload par URL signée + ingestion serveur</strong> (bucket fermé aux clients, gros fichiers hors VPS), MVP limité à « depuis le texte » et « depuis une image » (objets et lieux), prix différés avec <code>Grant</code> manuel, une recharge qui prolonge tout le solde, plafonds d'upload prudents, catalogue calibré au lot 3. Le webhook fal.ai est signé en <strong>ED25519, pas en HMAC</strong>.</p>
|
||||||
<p><strong>Le produit n'est pas l'accès aux modèles, c'est la cohérence.</strong> N'importe qui peut générer une image ailleurs. La valeur : qu'un conservateur qui ne sait pas prompter obtienne, en trois champs, une image raccord avec les quarante autres du même parcours. Une <code>VisualIdentity</code> par instance (style verrouillé, époque, palette, exclusions, 1-5 images de référence) + <strong>surcharge optionnelle par configuration</strong> — le parcours Halloween a sa propre identité, exactement comme <code>Configuration</code> porte déjà ses <code>PrimaryColor</code>/<code>Languages</code>. Injectée côté serveur dans chaque prompt, <strong>jamais retapée</strong>. Boutons « Générer » dans l'éditeur de contenu, pas dans un playground ; gabarits métier, prompt libre en mode avancé seulement.</p>
|
<p><strong>Le produit n'est pas l'accès aux modèles, c'est la cohérence.</strong> N'importe qui peut générer une image ailleurs. La valeur : qu'un conservateur qui ne sait pas prompter obtienne, en trois champs, une image raccord avec les quarante autres du même parcours. Une <code>VisualIdentity</code> par instance (style verrouillé, époque, palette, exclusions, 1-5 images de référence) + <strong>surcharge optionnelle par configuration</strong> — le parcours Halloween a sa propre identité, exactement comme <code>Configuration</code> porte déjà ses <code>PrimaryColor</code>/<code>Languages</code>. Injectée côté serveur dans chaque prompt, <strong>jamais retapée</strong>. Boutons « Générer » dans l'éditeur de contenu, pas dans un playground ; gabarits métier, prompt libre en mode avancé seulement.</p>
|
||||||
@ -1101,6 +1102,7 @@
|
|||||||
<article class="card" data-area="visitapp backend" data-horizon="v2">
|
<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-warn">V2 · remplace le talking head</span></div>
|
<div class="card-meta"><span class="tag">3 repos</span><span class="tag">Studio IA</span><span class="flag f-warn">V2 · remplace le talking head</span></div>
|
||||||
<h3>Personnages — un objet, quatre facettes</h3>
|
<h3>Personnages — un objet, quatre facettes</h3>
|
||||||
|
<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>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>
|
<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>
|
||||||
<p>⚠️ <strong>« Le visiteur choisit entre Viva et Marco » était un choix de voix déguisé en choix de guide.</strong> Le besoin réel est celui du <strong>Bastogne War Museum</strong> : 3-4 personnages qui narrent chacun <em>leurs</em> stations, avec leur voix et leur intonation. Le conservateur assigne (<code>NarratorPersonaId</code> sur <code>GuidedStep</code>/<code>GeoPoint</code>/<code>SectionArticle</code>), le visiteur ne choisit rien. <strong>Bonne nouvelle : ça divise le stockage TTS par deux au lieu de le multiplier</strong> — chaque contenu n'existe plus qu'en une voix.</p>
|
<p>⚠️ <strong>« Le visiteur choisit entre Viva et Marco » était un choix de voix déguisé en choix de guide.</strong> Le besoin réel est celui du <strong>Bastogne War Museum</strong> : 3-4 personnages qui narrent chacun <em>leurs</em> stations, avec leur voix et leur intonation. Le conservateur assigne (<code>NarratorPersonaId</code> sur <code>GuidedStep</code>/<code>GeoPoint</code>/<code>SectionArticle</code>), le visiteur ne choisit rien. <strong>Bonne nouvelle : ça divise le stockage TTS par deux au lieu de le multiplier</strong> — chaque contenu n'existe plus qu'en une voix.</p>
|
||||||
|
|||||||
@ -3,9 +3,10 @@ title: Module Studio — génération d'images sous identité visuelle
|
|||||||
area: backend manager
|
area: backend manager
|
||||||
horizon: v2
|
horizon: v2
|
||||||
tags: Studio IA
|
tags: Studio IA
|
||||||
flag: good | V2 · lots 0-4 codés le 13/09, gate à passer
|
flag: good | V2 · lots 0-6 codés, calibrage fait le 15/09, gate conservateur à passer
|
||||||
src: v2/studio-plan.md — §8 (exécutable lots 0-4), §9 (catalogue v0), décisions 22-23
|
src: v2/studio-plan.md — §8 (exécutable lots 0-4), §9 (catalogue v0), décisions 22-23
|
||||||
---
|
---
|
||||||
|
<p>✅ <strong>15/09 : lots 5 et 6 codés, calibrage §9.4 fait.</strong> Mention IA dans le fichier (XMP IPTC) + gravure en option. Calibrage sur 61 générations (Fourneau en gravure, Fort en aquarelle) : trois défauts corrigés avant tout client — négatif en double négation, titre de fiche recopié en légende, date d'un objet effacée. Coût réel fal : 0,03 $ l'image + 0,015 $ par référence ; <strong>unité arrêtée : 1 crédit = 0,015 $ de coût</strong>, vendu avec marge (≈ 0,05 €). Planches dans <code>outputs/studio-calibrage-2026-09-15/</code>. <strong>Reste</strong> : jugement visuel de Thomas, test du conservateur (gate lot 4), push de la branche.</p>
|
||||||
<p>🛠️ <strong>Lots 0 à 4 codés le 13/09</strong> sur la branche <code>studio</code> (manager-service, manager-app, mymuseum-visitapp) : ingestion serveur, crédits, identité visuelle (menu <strong>Studio</strong>), génération fal.ai derrière <code>IGenerationProvider</code> (fournisseur interchangeable), onglet <strong>Générer</strong> dans le sélecteur de ressource, image d'étape rattachée à une ressource. <strong>Reste avant le gate</strong> : bucket de dev + CORS, clé fal.ai (<code>Studio__Fal__Key</code>), migrations appliquées, calibrage et prix (§9.4), puis le test du conservateur.</p>
|
<p>🛠️ <strong>Lots 0 à 4 codés le 13/09</strong> sur la branche <code>studio</code> (manager-service, manager-app, mymuseum-visitapp) : ingestion serveur, crédits, identité visuelle (menu <strong>Studio</strong>), génération fal.ai derrière <code>IGenerationProvider</code> (fournisseur interchangeable), onglet <strong>Générer</strong> dans le sélecteur de ressource, image d'étape rattachée à une ressource. <strong>Reste avant le gate</strong> : bucket de dev + CORS, clé fal.ai (<code>Studio__Fal__Key</code>), migrations appliquées, calibrage et prix (§9.4), puis le test du conservateur.</p>
|
||||||
<p>✅ <strong>Plan consolidé le 13/09.</strong> Le §8 donne, pour les lots 0 à 4, les prérequis, les étapes, les vérifications et le gate. Le §9 contient un catalogue v0 (8 styles, règle de préambule, 3 gabarits) à calibrer en fin de lot 3. Six décisions ont été prises : <strong>upload par URL signée + ingestion serveur</strong> (bucket fermé aux clients, gros fichiers hors VPS), MVP limité à « depuis le texte » et « depuis une image » (objets et lieux), prix différés avec <code>Grant</code> manuel, une recharge qui prolonge tout le solde, plafonds d'upload prudents, catalogue calibré au lot 3. Le webhook fal.ai est signé en <strong>ED25519, pas en HMAC</strong>.</p>
|
<p>✅ <strong>Plan consolidé le 13/09.</strong> Le §8 donne, pour les lots 0 à 4, les prérequis, les étapes, les vérifications et le gate. Le §9 contient un catalogue v0 (8 styles, règle de préambule, 3 gabarits) à calibrer en fin de lot 3. Six décisions ont été prises : <strong>upload par URL signée + ingestion serveur</strong> (bucket fermé aux clients, gros fichiers hors VPS), MVP limité à « depuis le texte » et « depuis une image » (objets et lieux), prix différés avec <code>Grant</code> manuel, une recharge qui prolonge tout le solde, plafonds d'upload prudents, catalogue calibré au lot 3. Le webhook fal.ai est signé en <strong>ED25519, pas en HMAC</strong>.</p>
|
||||||
<p><strong>Le produit n'est pas l'accès aux modèles, c'est la cohérence.</strong> N'importe qui peut générer une image ailleurs. La valeur : qu'un conservateur qui ne sait pas prompter obtienne, en trois champs, une image raccord avec les quarante autres du même parcours. Une <code>VisualIdentity</code> par instance (style verrouillé, époque, palette, exclusions, 1-5 images de référence) + <strong>surcharge optionnelle par configuration</strong> — le parcours Halloween a sa propre identité, exactement comme <code>Configuration</code> porte déjà ses <code>PrimaryColor</code>/<code>Languages</code>. Injectée côté serveur dans chaque prompt, <strong>jamais retapée</strong>. Boutons « Générer » dans l'éditeur de contenu, pas dans un playground ; gabarits métier, prompt libre en mode avancé seulement.</p>
|
<p><strong>Le produit n'est pas l'accès aux modèles, c'est la cohérence.</strong> N'importe qui peut générer une image ailleurs. La valeur : qu'un conservateur qui ne sait pas prompter obtienne, en trois champs, une image raccord avec les quarante autres du même parcours. Une <code>VisualIdentity</code> par instance (style verrouillé, époque, palette, exclusions, 1-5 images de référence) + <strong>surcharge optionnelle par configuration</strong> — le parcours Halloween a sa propre identité, exactement comme <code>Configuration</code> porte déjà ses <code>PrimaryColor</code>/<code>Languages</code>. Injectée côté serveur dans chaque prompt, <strong>jamais retapée</strong>. Boutons « Générer » dans l'éditeur de contenu, pas dans un playground ; gabarits métier, prompt libre en mode avancé seulement.</p>
|
||||||
|
|||||||
@ -6,6 +6,7 @@ tags: 3 repos, Studio IA
|
|||||||
flag: warn | V2 · remplace le talking head
|
flag: warn | V2 · remplace le talking head
|
||||||
src: v2/studio-plan.md §3.8 — lots 7 et 8
|
src: v2/studio-plan.md §3.8 — lots 7 et 8
|
||||||
---
|
---
|
||||||
|
<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>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>
|
<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>
|
||||||
<p>⚠️ <strong>« Le visiteur choisit entre Viva et Marco » était un choix de voix déguisé en choix de guide.</strong> Le besoin réel est celui du <strong>Bastogne War Museum</strong> : 3-4 personnages qui narrent chacun <em>leurs</em> stations, avec leur voix et leur intonation. Le conservateur assigne (<code>NarratorPersonaId</code> sur <code>GuidedStep</code>/<code>GeoPoint</code>/<code>SectionArticle</code>), le visiteur ne choisit rien. <strong>Bonne nouvelle : ça divise le stockage TTS par deux au lieu de le multiplier</strong> — chaque contenu n'existe plus qu'en une voix.</p>
|
<p>⚠️ <strong>« Le visiteur choisit entre Viva et Marco » était un choix de voix déguisé en choix de guide.</strong> Le besoin réel est celui du <strong>Bastogne War Museum</strong> : 3-4 personnages qui narrent chacun <em>leurs</em> stations, avec leur voix et leur intonation. Le conservateur assigne (<code>NarratorPersonaId</code> sur <code>GuidedStep</code>/<code>GeoPoint</code>/<code>SectionArticle</code>), le visiteur ne choisit rien. <strong>Bonne nouvelle : ça divise le stockage TTS par deux au lieu de le multiplier</strong> — chaque contenu n'existe plus qu'en une voix.</p>
|
||||||
|
|||||||
BIN
outputs/studio-calibrage-2026-09-15/A-coherence.jpg
Normal file
|
After Width: | Height: | Size: 487 KiB |
BIN
outputs/studio-calibrage-2026-09-15/A-refs-0-3-5.jpg
Normal file
|
After Width: | Height: | Size: 441 KiB |
BIN
outputs/studio-calibrage-2026-09-15/B-coherence.jpg
Normal file
|
After Width: | Height: | Size: 195 KiB |
BIN
outputs/studio-calibrage-2026-09-15/C-coherence.jpg
Normal file
|
After Width: | Height: | Size: 174 KiB |
BIN
outputs/studio-calibrage-2026-09-15/archetypes.jpg
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
outputs/studio-calibrage-2026-09-15/samples.jpg
Normal file
|
After Width: | Height: | Size: 309 KiB |
BIN
outputs/studio-calibrage-2026-09-15/source.jpg
Normal file
|
After Width: | Height: | Size: 299 KiB |
BIN
outputs/studio-calibrage-2026-09-15/v2-A-negatif.jpg
Normal file
|
After Width: | Height: | Size: 917 KiB |
BIN
outputs/studio-calibrage-2026-09-15/v2-refs3-source.jpg
Normal file
|
After Width: | Height: | Size: 485 KiB |
BIN
outputs/studio-calibrage-2026-09-15/v3-contexte.jpg
Normal file
|
After Width: | Height: | Size: 997 KiB |
@ -19,8 +19,8 @@ Plans détaillés, pas encore démarrés en dev (sauf mention contraire) :
|
|||||||
| TTS pré-généré (audioguide multilingue) | [v2/tts-pregenerated-plan.md](../v2/tts-pregenerated-plan.md) | Priorité 3. ⚠️ **Trois corrections posées le 2026-09-02** (en-tête du fichier) : le moteur est **Gemini TTS**, pas Cloud TTS — le document disait les deux, le code tranche ; « le visiteur choisit entre Viva et Marco » est remplacé par **un guide adressable + N narrateurs** ; et le stockage s'en trouve **divisé par deux**, pas multiplié. Source de vérité sur les personnages : [v2/studio-plan.md §3.8](../v2/studio-plan.md) |
|
| TTS pré-généré (audioguide multilingue) | [v2/tts-pregenerated-plan.md](../v2/tts-pregenerated-plan.md) | Priorité 3. ⚠️ **Trois corrections posées le 2026-09-02** (en-tête du fichier) : le moteur est **Gemini TTS**, pas Cloud TTS — le document disait les deux, le code tranche ; « le visiteur choisit entre Viva et Marco » est remplacé par **un guide adressable + N narrateurs** ; et le stockage s'en trouve **divisé par deux**, pas multiplié. Source de vérité sur les personnages : [v2/studio-plan.md §3.8](../v2/studio-plan.md) |
|
||||||
| ~~Talking head (avatar animé)~~ | [v2/talking-head-plan.md](../v2/talking-head-plan.md) | ⛔ **ABANDONNÉ le 2026-09-02.** Son lipsync repose sur `enable_time_pointing` de **Google Cloud TTS**, or le code livré tourne sur **Gemini TTS** (`GeminiTtsEngine`, `gemini-2.5-flash-preview-tts`) : aucune source de timestamps. Le plan était sans fondation, pas « à faire ». Remplacé par le portrait canon statique d'un `Persona`, puis une boucle vidéo 6-8 s. En-tête d'abandon posé sur le fichier |
|
| ~~Talking head (avatar animé)~~ | [v2/talking-head-plan.md](../v2/talking-head-plan.md) | ⛔ **ABANDONNÉ le 2026-09-02.** Son lipsync repose sur `enable_time_pointing` de **Google Cloud TTS**, or le code livré tourne sur **Gemini TTS** (`GeminiTtsEngine`, `gemini-2.5-flash-preview-tts`) : aucune source de timestamps. Le plan était sans fondation, pas « à faire ». Remplacé par le portrait canon statique d'un `Persona`, puis une boucle vidéo 6-8 s. En-tête d'abandon posé sur le fichier |
|
||||||
| **Médiathèque — refonte de l'onglet Ressources** | ⭐ **[v1-mediatheque-plan.md](../v1-mediatheque-plan.md)** — spec autonome et exécutable, écrite le 2026-09-02 | ⭐ **V1 — prêt à implémenter, sans rien lire du plan Studio.** Rien à voir avec l'IA : renommage en Médiathèque, rail de facettes cumulables (type/usage/origine/configuration), filtre **« jamais utilisée »**, tri, groupement, sélection multiple, et le détail en **panneau latéral** avec la liste « Utilisée dans » — presque gratuite, `GetReferencedResourceIds` existe déjà sur les 13 sous-types. 🐛 Corrige deux bugs : le téléchargement forcé en `.json` quel que soit le type (`show_resource_popup.dart:91`) et `Resource.FileName` absent de `ToDTO()`. **Aucune clé API, aucun coût variable — meilleur ratio valeur/risque du chantier** |
|
| **Médiathèque — refonte de l'onglet Ressources** | ⭐ **[v1-mediatheque-plan.md](../v1-mediatheque-plan.md)** — spec autonome et exécutable, écrite le 2026-09-02 | ⭐ **V1 — prêt à implémenter, sans rien lire du plan Studio.** Rien à voir avec l'IA : renommage en Médiathèque, rail de facettes cumulables (type/usage/origine/configuration), filtre **« jamais utilisée »**, tri, groupement, sélection multiple, et le détail en **panneau latéral** avec la liste « Utilisée dans » — presque gratuite, `GetReferencedResourceIds` existe déjà sur les 13 sous-types. 🐛 Corrige deux bugs : le téléchargement forcé en `.json` quel que soit le type (`show_resource_popup.dart:91`) et `Resource.FileName` absent de `ToDTO()`. **Aucune clé API, aucun coût variable — meilleur ratio valeur/risque du chantier** |
|
||||||
| **Module Studio — génération IA d'images/vidéos/3D** | [v2/studio-plan.md](../v2/studio-plan.md) | 📦 **V2 — conception arrêtée le 2026-09-02, rien de codé.** Le produit n'est pas l'accès aux modèles, c'est la **cohérence visuelle à l'échelle d'un projet** : une `VisualIdentity` par instance + surcharge par configuration, injectée côté serveur dans chaque prompt. La génération se greffe sur le **sélecteur de ressource existant** (`showSelectResourceModal` embarque déjà `ResourcesScreen`) — un seul branchement couvre les 13 types de section, les POI et les étapes. MVP = escape game, images seulement. ⛔ **Prérequis dur : le backend ne sait pas écrire dans le bucket** (`IResourceBlobService` n'a que `DeleteAsync`) — lot 0 partagé avec le TTS pré-généré. ⚠️ Trois pièges tranchés : URL Firebase à jeton **publique** (préfixe `studio-drafts/` + proxy authentifié), `CheckQuota` avant/après **ne tient pas** sur des jobs Hangfire parallèles (réservation en deux temps sur `CreditLedger`), et `GuidedStep.ImageUrl` est une URL — les images de l'escape game **ne partiraient pas offline**. 🚫 Pas de watermark gravé : provenance + badge UI |
|
| **Module Studio — génération IA d'images/vidéos/3D** | [v2/studio-plan.md](../v2/studio-plan.md) | 🛠️ **V2 — lots 0 à 6 codés, calibrage fait le 2026-09-15** (voir studio-plan §9.4 : négatif, contexte, coûts réels, unité de crédit). Conception du 2026-09-02 : Le produit n'est pas l'accès aux modèles, c'est la **cohérence visuelle à l'échelle d'un projet** : une `VisualIdentity` par instance + surcharge par configuration, injectée côté serveur dans chaque prompt. La génération se greffe sur le **sélecteur de ressource existant** (`showSelectResourceModal` embarque déjà `ResourcesScreen`) — un seul branchement couvre les 13 types de section, les POI et les étapes. MVP = escape game, images seulement. ✅ Prérequis bucket levé (lot 0 : URL signée + ingestion serveur). ⚠️ Trois pièges tranchés : URL Firebase à jeton **publique** (préfixe `studio-drafts/` + proxy authentifié), `CheckQuota` avant/après **ne tient pas** sur des jobs Hangfire parallèles (réservation en deux temps sur `CreditLedger`), et `GuidedStep.ImageUrl` est une URL — les images de l'escape game **ne partiraient pas offline**. 🚫 Pas de watermark gravé par défaut : provenance + badge UI + XMP IPTC dans le fichier, gravure en option par instance (lot 6) |
|
||||||
| **Personnages — un guide adressable + N narrateurs** | [v2/studio-plan.md §3.8](../v2/studio-plan.md) | 📦 **V2 — arrêté le 2026-09-02.** **Trois plans décrivaient le même objet sans se croiser** : le canon visuel (studio-plan), les frames de lipsync (talking-head), et `PersonaConfig { WakewordId, GuideName, PersonaPrompt, VoiceName }` (tts-pregenerated). Une entité `Persona` les remplace, et les 4 colonnes `Instance.Guide*` deviennent une ligne. ⚠️ « Le visiteur choisit entre Viva et Marco » était **un choix de voix déguisé en choix de guide** : le besoin réel (modèle Bastogne War Museum) est N narrateurs assignés par le conservateur via `NarratorPersonaId` — ce qui **divise le stockage TTS par deux** au lieu de le multiplier. Le **wakeword devient une exigence du canal mains-libres**, pas une propriété du personnage : ça corrige le bug latent où le visiteur dirait « Marco » à quelqu'un qui se présente comme « Léon ». À ajouter : `Persona.VoicePrompt` (l'intonation, aujourd'hui la **constante de build** `kGeminiTtsPrompt`) et une table `TtsVoice` — deux constantes ne suffisent pas à quatre narrateurs |
|
| **Personnages — un guide adressable + N narrateurs** | [v2/studio-plan.md §3.8](../v2/studio-plan.md) | 🛠️ **V2 — lot 7 en cours** (entité `Persona`, écran Personnages, `TtsVoice` en base, figures d'archétypes). Arrêté le 2026-09-02 : **Trois plans décrivaient le même objet sans se croiser** : le canon visuel (studio-plan), les frames de lipsync (talking-head), et `PersonaConfig { WakewordId, GuideName, PersonaPrompt, VoiceName }` (tts-pregenerated). Une entité `Persona` les remplace, et les 4 colonnes `Instance.Guide*` deviennent une ligne. ⚠️ « Le visiteur choisit entre Viva et Marco » était **un choix de voix déguisé en choix de guide** : le besoin réel (modèle Bastogne War Museum) est N narrateurs assignés par le conservateur via `NarratorPersonaId` — ce qui **divise le stockage TTS par deux** au lieu de le multiplier. Le **wakeword devient une exigence du canal mains-libres**, pas une propriété du personnage : ça corrige le bug latent où le visiteur dirait « Marco » à quelqu'un qui se présente comme « Léon ». À ajouter : `Persona.VoicePrompt` (l'intonation, aujourd'hui la **constante de build** `kGeminiTtsPrompt`) et une table `TtsVoice` — deux constantes ne suffisent pas à quatre narrateurs |
|
||||||
| AI Persona par venue (guide IA personnalisable) | [v2/myinfomate-ai-persona-analysis.md](../v2/myinfomate-ai-persona-analysis.md) | Architecture de référence pour les chantiers IA ci-dessus |
|
| AI Persona par venue (guide IA personnalisable) | [v2/myinfomate-ai-persona-analysis.md](../v2/myinfomate-ai-persona-analysis.md) | Architecture de référence pour les chantiers IA ci-dessus |
|
||||||
| Lunettes Ray-Ban Meta | [roadmap.md](../roadmap.md) (section XR), [rayban-meta-integration.md](../rayban-meta-integration.md) | 🔨 **POC fonctionnel — bien plus avancé que ce que cette ligne disait jusqu'au 2026-08-09.** Voir §5bis |
|
| Lunettes Ray-Ban Meta | [roadmap.md](../roadmap.md) (section XR), [rayban-meta-integration.md](../rayban-meta-integration.md) | 🔨 **POC fonctionnel — bien plus avancé que ce que cette ligne disait jusqu'au 2026-08-09.** Voir §5bis |
|
||||||
| VR Meta Quest (borne office tourisme) | [v2/vr-quest-unity-plan.md](../v2/vr-quest-unity-plan.md) · [roadmap.md](../roadmap.md) (section XR) | 📦 **V2** — ⚠️ **« zéro ligne de code » était faux** (corrigé le 2026-08-31, relevé dans le code). Le canal VR est déjà dans le modèle : `AppType.VR`, `Instance.IsVR` en base depuis juillet 2025, sous-menu « VR » branché dans `main_screen.dart:65`, filtre stats + i18n `statsChannelVR` prêts. **Ce qui manque** : l'écran de flotte (`main_screen.dart:704` = `Text("TODO vr")`), un `Device.AppType` (le `DeviceController` est hardcodé sur `Tablet`), et l'app Unity. Back-office XR : **8-12 j**. App Unity : **3-4 mois**. La landing annonce « Meta Quest — Bientôt » en 4 langues (`translations.ts`, clé `mode4Desc`) |
|
| VR Meta Quest (borne office tourisme) | [v2/vr-quest-unity-plan.md](../v2/vr-quest-unity-plan.md) · [roadmap.md](../roadmap.md) (section XR) | 📦 **V2** — ⚠️ **« zéro ligne de code » était faux** (corrigé le 2026-08-31, relevé dans le code). Le canal VR est déjà dans le modèle : `AppType.VR`, `Instance.IsVR` en base depuis juillet 2025, sous-menu « VR » branché dans `main_screen.dart:65`, filtre stats + i18n `statsChannelVR` prêts. **Ce qui manque** : l'écran de flotte (`main_screen.dart:704` = `Text("TODO vr")`), un `Device.AppType` (le `DeviceController` est hardcodé sur `Tablet`), et l'app Unity. Back-office XR : **8-12 j**. App Unity : **3-4 mois**. La landing annonce « Meta Quest — Bientôt » en 4 langues (`translations.ts`, clé `mode4Desc`) |
|
||||||
|
|||||||
@ -159,7 +159,9 @@ Tout sur `Instance`, dupliqué depuis `SubscriptionPlan` : `StorageQuotaBytes`,
|
|||||||
| 20 | Lignage | **`Resource.Origin`** (`Uploaded` \| `Generated` \| `Derived`) et **`Resource.SourceResourceId`** en colonnes typées ; `AiProvenance` jsonb garde le détail. Reporte la décision n°4 d'`immersif-frontiere-plan` §5. Posé au lot 0, puisque l'ingestion l'écrit |
|
| 20 | Lignage | **`Resource.Origin`** (`Uploaded` \| `Generated` \| `Derived`) et **`Resource.SourceResourceId`** en colonnes typées ; `AiProvenance` jsonb garde le détail. Reporte la décision n°4 d'`immersif-frontiere-plan` §5. Posé au lot 0, puisque l'ingestion l'écrit |
|
||||||
| 21 | Contrat fournisseur | **`ProviderResult` multi-fichier**, délais et relances **par `GenerationKind`**. Le job composite (parent + N enfants) est réservé à la 3D. Reporte la décision n°6 d'`immersif-frontiere-plan` §5 |
|
| 21 | Contrat fournisseur | **`ProviderResult` multi-fichier**, délais et relances **par `GenerationKind`**. Le job composite (parent + N enfants) est réservé à la 3D. Reporte la décision n°6 d'`immersif-frontiere-plan` §5 |
|
||||||
| 22 | Plafond dur et dotation de plan — *13/09, lot 1* | **Retirés.** Avec des crédits prépayés (décision 17), le solde *est* le plafond : un « plafond dur organisation » n'a plus rien à borner. Seul reste `StudioPerUserDailyCap`, en crédits. `SubscriptionPlan.HasStudio` / `StudioCreditsGranted` et `Instance.StudioProviderRegion` ne sont pas créés tant que rien ne les lit (prix différés, décision 16 ; région déclarative) |
|
| 22 | Plafond dur et dotation de plan — *13/09, lot 1* | **Retirés.** Avec des crédits prépayés (décision 17), le solde *est* le plafond : un « plafond dur organisation » n'a plus rien à borner. Seul reste `StudioPerUserDailyCap`, en crédits. `SubscriptionPlan.HasStudio` / `StudioCreditsGranted` et `Instance.StudioProviderRegion` ne sont pas créés tant que rien ne les lit (prix différés, décision 16 ; région déclarative) |
|
||||||
| 23 | Écarts des lots 2 à 4 — *13/09* | **Fournisseur interchangeable** : `IGenerationProvider` (soumission, sondage, lecture du webhook) + `GenerationModel.ProviderKey` en base ; changer de fournisseur = une classe et une ligne de catalogue. **Une requête par variante** (FLUX.2 pro n'a pas de `num_images`). **Référence source avant celles de l'identité** dans l'ordre d'envoi. Migration unique `AddStudioGeneration` pour les lots 2 et 3. **Non livrés** : `preview`, `GET /jobs`, `cancel`, `reject`, `regenerate`, l'interrupteur UI de `CanValidateAssets`. **Pas de `target` serveur** : l'onglet « Générer » vit dans le sélecteur (`showSelectResourceModal`, mode sélection) et la ressource validée revient au champ qui l'a ouvert — donc absent du bouton « Ajouter » de la Médiathèque, qui relève du lot 5. Surcharges d'identité en puces, pas en onglets ; `ModelKey` non exposé (un seul modèle). **`GuidedStep.ImageUrl` conservée** et remplie par le client avec `ImageResourceId` (motif `GeoPoint`) : visitapp-web n'a rien à changer, mymuseum-visitapp lit l'id pour l'hors-ligne, tablet-app n'a pas d'étapes. `CreditCost = 10` provisoire jusqu'au calibrage |
|
| 23 | Écarts des lots 2 à 4 — *13/09* | **Fournisseur interchangeable** : `IGenerationProvider` (soumission, sondage, lecture du webhook) + `GenerationModel.ProviderKey` en base ; changer de fournisseur = une classe et une ligne de catalogue. **Une requête par variante** (FLUX.2 pro n'a pas de `num_images`). **Référence source avant celles de l'identité** dans l'ordre d'envoi. Migration unique `AddStudioGeneration` pour les lots 2 et 3. **Non livrés** : `preview`, `GET /jobs`, `cancel`, `reject`, `regenerate`, l'interrupteur UI de `CanValidateAssets`. **Pas de `target` serveur** : l'onglet « Générer » vit dans le sélecteur (`showSelectResourceModal`, mode sélection) et la ressource validée revient au champ qui l'a ouvert — donc absent du bouton « Ajouter » de la Médiathèque, qui relève du lot 5. Surcharges d'identité en puces, pas en onglets ; `ModelKey` non exposé (un seul modèle). **`GuidedStep.ImageUrl` conservée** et remplie par le client avec `ImageResourceId` (motif `GeoPoint`) : visitapp-web n'a rien à changer, mymuseum-visitapp lit l'id pour l'hors-ligne, tablet-app n'a pas d'étapes. `CreditCost = 10` provisoire jusqu'au calibrage || 24 | Modèles 3D et multi-vues — *15/09* | **Tout reste sur fal** : Meshy (v5, v6-preview, v7), Hi3D, Tripo3D, Hunyuan3D et Trellis y sont exposés — aucun second fournisseur à intégrer, aucune seconde clé. **Deux lignes de catalogue, pas une** : `3d-default` mono-image (~0,02–0,05 $) et `3d-multiview` = `meshy/v7/multi-image-to-3d` (~1,20 $). Le facteur ~25 sur le coût impose que le basculement de l'un à l'autre soit **annoncé avant la génération, jamais silencieux**. Hi3D n'expose pas de multiview : excellent en fidélité structurelle, il ne couvre pas le cas d'usage central. Ids et prix à revérifier au calibrage (§9.4) |
|
||||||
|
| 25 | Casting visiteur — *15/09* | **Retenu** — lève le « hors périmètre » de §3.8. `ConfigurationPersona { ConfigurationId, PersonaId, Order, IsFeatured }` ne porte **que** l'ordre et la mise en avant : l'appartenance reste **calculée** depuis les narrateurs assignés. Un personnage ne s'assigne qu'à **un seul endroit — le contenu** ; l'écran casting est une *vue*, jamais une seconde saisie. Rien ne s'affiche côté visiteur sans `Configuration.IsCastingShownToVisitor` (défaut off). Lot 8bis |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -673,12 +675,13 @@ Cibles au moment de la rédaction, **à ne jamais écrire dans le code** :
|
|||||||
|
|
||||||
| Rôle | Modèle | Note |
|
| Rôle | Modèle | Note |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Image par défaut | FLUX.2 [pro] | jusqu'à 10 images de référence — **chiffre non retrouvé sur la page API fal le 13/09, à confirmer au calibrage** (§9.4) ; bonne préservation de style |
|
| Image par défaut | FLUX.2 [pro] | jusqu'à 10 images de référence — **mesuré le 15/09 : 422 « At most 10 image URLs are allowed » au-delà** ; bonne préservation de style |
|
||||||
| Personnages et scènes narratives | Nano Banana Pro / Gemini 3 Pro Image | jusqu'à 14 entrées de référence |
|
| Personnages et scènes narratives | Nano Banana Pro / Gemini 3 Pro Image | jusqu'à 14 entrées de référence |
|
||||||
| Texte lisible / vectoriel | Recraft V3 | |
|
| Texte lisible / vectoriel | Recraft V3 | |
|
||||||
| Vidéo par défaut | Kling 3.0 | clips 6-8 s, pensés pour la boucle |
|
| Vidéo par défaut | Kling 3.0 | clips 6-8 s, pensés pour la boucle |
|
||||||
| Vidéo avec audio natif | Veo 3.1 | |
|
| Vidéo avec audio natif | Veo 3.1 | |
|
||||||
| 3D | Meshy 6 ou Tripo | objets isolés uniquement, export GLB |
|
| 3D — 1 image | Hi3D (`hitem3d/hi3d/image-to-3d`) ou Tripo3D | objets isolés, export GLB, ~0,02–0,05 $ |
|
||||||
|
| 3D — plusieurs vues | **Meshy v7** (`meshy/v7/multi-image-to-3d`) | 2 à 4 photos du **même** objet, ~1,20 $ (1,40 $ en ultra) — voir décision 24 et lot 11 |
|
||||||
|
|
||||||
`StudioProviderRegion` sur l'instance est déclaratif aujourd'hui ; il devient un critère de sélection
|
`StudioProviderRegion` sur l'instance est déclaratif aujourd'hui ; il devient un critère de sélection
|
||||||
de provider le jour où une région alternative existe.
|
de provider le jour où une région alternative existe.
|
||||||
@ -934,11 +937,48 @@ donc **deux canons qui divergent**, exactement ce que `Persona` existe pour emp
|
|||||||
dans l'escape game » reste **calculé**, jamais déclaré : un champ déclaré peut mentir, un compte
|
dans l'escape game » reste **calculé**, jamais déclaré : un champ déclaré peut mentir, un compte
|
||||||
d'usages non.
|
d'usages non.
|
||||||
|
|
||||||
**Un seul cas justifierait un vrai lien configuration ↔ personnage** : présenter le **casting** au
|
#### Le casting — décidé le 2026-09-15 (décision 25)
|
||||||
visiteur (« les 4 témoins que vous allez rencontrer »), qui demande un ordre et un sous-ensemble
|
|
||||||
éditorial qu'un ensemble calculé ne porte pas. Table optionnelle
|
Un seul cas justifiait un vrai lien configuration ↔ personnage : présenter le **casting** au visiteur
|
||||||
`ConfigurationPersona { ConfigurationId, PersonaId, Order, IsFeatured }`, remplie seulement si cet
|
(« les 4 témoins que vous allez rencontrer »), qui demande un ordre et un sous-ensemble éditorial
|
||||||
écran existe. **Hors périmètre tant que la décision produit n'est pas prise.**
|
qu'un ensemble calculé ne porte pas. **Il est retenu** — c'est aussi le premier usage visiteur réel
|
||||||
|
du canon visuel, qui ne servait jusqu'ici qu'à la cohérence des images générées.
|
||||||
|
|
||||||
|
> **La règle qui rend l'écran simple :** *on assigne un personnage à un seul endroit — le contenu.*
|
||||||
|
> Le casting n'est pas une seconde saisie, c'est une **vue** de ce qui est déjà calculé, plus deux
|
||||||
|
> champs éditoriaux : l'ordre et la mise en avant. Deux endroits où déclarer la même chose, ce sont
|
||||||
|
> deux vérités qui divergent — le même piège que les deux canons évités plus haut.
|
||||||
|
|
||||||
|
**Écran `Configuration › Personnages`.** Une ligne par personnage réellement utilisé : portrait canon,
|
||||||
|
nom, rôle, **d'où vient l'usage** (« 6 étapes du parcours principal », cliquable). Deux contrôles,
|
||||||
|
pas trois : une case « montré au visiteur » et une poignée de réordonnancement. **Aucun sélecteur de
|
||||||
|
personnage sur cet écran** : pour en ajouter un, on lui assigne un contenu ; pour en retirer un, on
|
||||||
|
change le narrateur de ses contenus — et le lien pour y aller est sur la ligne.
|
||||||
|
|
||||||
|
**Les trois états — c'est là que se joue la clarté**, parce que la majorité des clients n'auront
|
||||||
|
jamais qu'un seul personnage et ne doivent pas voir un écran de casting vide :
|
||||||
|
|
||||||
|
| Situation | Ce que montre l'écran | Ce que le client a à faire |
|
||||||
|
|---|---|---|
|
||||||
|
| Aucun narrateur assigné | Bandeau : « **Léon** raconte toute cette visite » + *(guide de l'instance)* + lien vers sa fiche | **rien** — cas nominal |
|
||||||
|
| Un seul personnage | Le même bandeau, pas de liste | rien ; l'interrupteur casting est masqué, pas grisé |
|
||||||
|
| Deux personnages ou plus | La liste + l'interrupteur **« Présenter les personnages au visiteur »** (`IsCastingShownToVisitor`, **défaut off**) | cocher, ordonner |
|
||||||
|
|
||||||
|
Quatre règles, dans la ligne des quatre exigences de l'onglet « Narrateurs » :
|
||||||
|
|
||||||
|
1. **Hérité et choisi se distinguent à l'œil**, ici aussi : `↳ Le gouverneur` en gris quand il n'est
|
||||||
|
là que comme repli du parcours, **La sentinelle** en gras quand un contenu le désigne.
|
||||||
|
2. **Rien n'apparaît côté visiteur sans un geste explicite.** Un client qui assigne un deuxième
|
||||||
|
narrateur ne doit pas découvrir un nouvel écran dans son app sans l'avoir demandé.
|
||||||
|
3. **Un personnage sans portrait canon** s'affiche avec un gabarit neutre et un avertissement, et ne
|
||||||
|
peut pas être « mis en avant » : un casting à trous est pire que pas de casting.
|
||||||
|
4. **L'ordre par défaut est celui d'apparition dans la visite**, pas l'ordre de création : c'est ce
|
||||||
|
que le visiteur va vivre, et ça évite au client d'avoir à réordonner quoi que ce soit dans 90 %
|
||||||
|
des cas.
|
||||||
|
|
||||||
|
Table `ConfigurationPersona { ConfigurationId, PersonaId, Order, IsFeatured }` — **Order et
|
||||||
|
IsFeatured seulement.** L'appartenance reste calculée : un champ déclaré peut mentir, un compte
|
||||||
|
d'usages non.
|
||||||
|
|
||||||
**Règle du wakeword — c'est une exigence du canal, pas une propriété du personnage.**
|
**Règle du wakeword — c'est une exigence du canal, pas une propriété du personnage.**
|
||||||
|
|
||||||
@ -1193,6 +1233,9 @@ POST /api/Studio/personas/{id}/canon { assetId } → fige le port
|
|||||||
POST /api/Studio/personas/{id}/views { kind } → job (profil, plan large, dos)
|
POST /api/Studio/personas/{id}/views { kind } → job (profil, plan large, dos)
|
||||||
DELETE /api/Studio/personas/{id}/views/{viewId}
|
DELETE /api/Studio/personas/{id}/views/{viewId}
|
||||||
POST /api/Studio/personas/{id}/archive
|
POST /api/Studio/personas/{id}/archive
|
||||||
|
|
||||||
|
GET /api/Studio/configurations/{id}/casting → liste calculée + Order/IsFeatured
|
||||||
|
PUT /api/Studio/configurations/{id}/casting { isShownToVisitor, entries[{personaId, order, isFeatured}] }
|
||||||
```
|
```
|
||||||
|
|
||||||
### Crédits
|
### Crédits
|
||||||
@ -1267,6 +1310,7 @@ Migrations additives, **une par lot** (le §8 dit laquelle), aucune donnée exis
|
|||||||
| `Personas` | `InstanceId`, index `(InstanceId, IsArchived)` — **pas de `Kind`** (décision 7) ; remplace les colonnes `Guide*` de `Instance` |
|
| `Personas` | `InstanceId`, index `(InstanceId, IsArchived)` — **pas de `Kind`** (décision 7) ; remplace les colonnes `Guide*` de `Instance` |
|
||||||
| `PersonaViews` | `PersonaId` FK cascade, `ResourceId` FK |
|
| `PersonaViews` | `PersonaId` FK cascade, `ResourceId` FK |
|
||||||
| `TtsVoices` | `Key` unique — catalogue, plus deux constantes |
|
| `TtsVoices` | `Key` unique — catalogue, plus deux constantes |
|
||||||
|
| `ConfigurationPersonas` | `ConfigurationId` FK, `PersonaId` FK, index unique `(ConfigurationId, PersonaId)` — **ordre et mise en avant seulement**, l'appartenance reste calculée (décision 25, lot 8bis) |
|
||||||
| `BeforeAfterPairs` | `AfterResourceId`, `BeforeResourceId` |
|
| `BeforeAfterPairs` | `AfterResourceId`, `BeforeResourceId` |
|
||||||
| `CreditLedgerEntries` | `InstanceId`, `UserId`, `GenerationJobId?`, index `(InstanceId, CreatedAt)` |
|
| `CreditLedgerEntries` | `InstanceId`, `UserId`, `GenerationJobId?`, index `(InstanceId, CreatedAt)` |
|
||||||
|
|
||||||
@ -1276,6 +1320,7 @@ Migrations additives, **une par lot** (le §8 dit laquelle), aucune donnée exis
|
|||||||
Resource += Origin int not null default 0 -- Uploaded=0 | Generated=1 | Derived=2 (lot 0)
|
Resource += Origin int not null default 0 -- Uploaded=0 | Generated=1 | Derived=2 (lot 0)
|
||||||
SourceResourceId? -- lignage parent (lot 0)
|
SourceResourceId? -- lignage parent (lot 0)
|
||||||
AiProvenance jsonb? -- détail (lot 3)
|
AiProvenance jsonb? -- détail (lot 3)
|
||||||
|
Configuration += IsCastingShownToVisitor bool not null default false -- lot 8bis
|
||||||
Instance += StudioEnabled, StudioCreditsBalance, StudioCreditsExpireAt,
|
Instance += StudioEnabled, StudioCreditsBalance, StudioCreditsExpireAt,
|
||||||
StudioPerUserDailyCap, -- lot 1, livré
|
StudioPerUserDailyCap, -- lot 1, livré
|
||||||
IsAiWatermarkBurned -- lot 6
|
IsAiWatermarkBurned -- lot 6
|
||||||
@ -1395,11 +1440,18 @@ des `Resource` et n'ont donc rien à faire dans la bibliothèque. En usage norma
|
|||||||
|
|
||||||
`AiProvenance`, descente jusqu'aux 3 clients visiteurs, badge traduit, `rightsHolder`, option de gravure.
|
`AiProvenance`, descente jusqu'aux 3 clients visiteurs, badge traduit, `rightsHolder`, option de gravure.
|
||||||
|
|
||||||
|
> **Fait le 2026-09-15.** À la validation, `AiImageMarker` écrit un XMP IPTC `DigitalSourceType = trainedAlgorithmicMedia`
|
||||||
|
> + `dc:rights` = `rightsHolder` (survit au ré-encodage de l'ingestion, testé). Gravure : `Instance.IsAiWatermarkBurned`
|
||||||
|
> (interrupteur SuperAdmin dans le dialogue d'instance), texte fixe « Généré par IA · AI-generated » en bas à droite,
|
||||||
|
> police DejaVu Sans embarquée. ⚠️ `IsImageWatermark` (filigrane du lieu) reste mort — carte 305, rien partagé.
|
||||||
|
|
||||||
### Lot 7 — Personnages (fusion guide + figures)
|
### Lot 7 — Personnages (fusion guide + figures)
|
||||||
|
|
||||||
Registre de personnages, grille d'archétypes neutres (une douzaine à pré-produire), paramètres,
|
Registre de personnages, grille d'archétypes neutres (une douzaine à pré-produire), paramètres,
|
||||||
canon en **jeu de vues**, jauge de budget de références, réinjection en référence n°1, archivage.
|
canon en **jeu de vues**, jauge de budget de références, réinjection en référence n°1, archivage.
|
||||||
|
|
||||||
|
> **État au 2026-09-15.** Fait : `Persona`, écran Personnages, `TtsVoice` en base, migration `AddPersonas`. Fichiers pré-produits le 15/09 et **embarqués dans manager-app** (`assets/images/studio/`) plutôt que déposés au bucket : une URL de bucket différerait entre dev et prod, alors qu'un asset marche partout — `VisualStyle.SampleImageUrl` prime s'il est rempli. 8 échantillons de style (un même moulin dans les 8 styles) et 12 figures d'archétypes (mannequin neutre au trait), ≈ 0,60 $. **Reste** : l'écoute des voix — 6 extraits audio `TtsVoice` à générer en Gemini TTS, bloqué sur la clé (absente en local).
|
||||||
|
|
||||||
**Migration structurante** : les 4 colonnes `Instance.Guide*` deviennent une ligne
|
**Migration structurante** : les 4 colonnes `Instance.Guide*` deviennent une ligne
|
||||||
`Persona` à facette parole remplie (pas de `Kind`, décision 7), et `Instance` porte un
|
`Persona` à facette parole remplie (pas de `Kind`, décision 7), et `Instance` porte un
|
||||||
`GuidePersonaId`. Le catalogue `TtsVoice` passe
|
`GuidePersonaId`. Le catalogue `TtsVoice` passe
|
||||||
@ -1416,6 +1468,18 @@ 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.
|
||||||
|
|
||||||
|
### Lot 8bis — Casting visiteur *(petit, juste après le lot 8)*
|
||||||
|
|
||||||
|
N'a de sens qu'une fois plusieurs narrateurs assignables, donc après le lot 8 — et il est court.
|
||||||
|
|
||||||
|
- `ConfigurationPersona { ConfigurationId, PersonaId, Order, IsFeatured }` et
|
||||||
|
`Configuration.IsCastingShownToVisitor` (défaut `false`).
|
||||||
|
- Écran `Configuration › Personnages` : liste **calculée** depuis les narrateurs assignés, trois
|
||||||
|
états (0 / 1 / n personnages), aucun sélecteur de personnage — voir §3.8.
|
||||||
|
- Côté visiteur : écran d'entrée « les personnes que vous allez rencontrer », portrait canon + nom +
|
||||||
|
rôle. Trois fronts. **Ne s'affiche que si l'interrupteur est armé et si ≥ 2 personnages ont un
|
||||||
|
portrait.**
|
||||||
|
|
||||||
### Lot 9 — Avant / après
|
### Lot 9 — Avant / après
|
||||||
|
|
||||||
Gabarit image-to-image + composant slider ×3 clients.
|
Gabarit image-to-image + composant slider ×3 clients.
|
||||||
@ -1426,10 +1490,54 @@ Kling 3.0 / Veo 3.1, clips 6-8 s en boucle, canon d'un personnage comme image so
|
|||||||
stockage sérieux : à cadrer côté quota avant d'ouvrir. C'est ici que revient l'idée d'un portrait
|
stockage sérieux : à cadrer côté quota avant d'ouvrir. C'est ici que revient l'idée d'un portrait
|
||||||
animé, sous une forme qui tient en 2026.
|
animé, sous une forme qui tient en 2026.
|
||||||
|
|
||||||
|
> **Non engagé — arbitré le 2026-09-15.** Faire *parler* un personnage reste souhaitable, mais le
|
||||||
|
> blocage est le **stockage**, pas la techno (le lipsync, lui, est mort pour une autre raison :
|
||||||
|
> décision 9). Tant que l'enveloppe de stockage n'est pas chiffrée, ce lot reste après tout le
|
||||||
|
> reste — V2 tardive, voire V3. Le portrait canon statique du lot 8 est la réponse en attendant.
|
||||||
|
|
||||||
### Lot 11 — 3D
|
### Lot 11 — 3D
|
||||||
|
|
||||||
Meshy 6 / Tripo, objets isolés, export GLB, `ResourceType.Model3D` (déjà dans l'enum, valeur 13). Suppose un viewer GLB côté
|
Objets isolés, export GLB, `ResourceType.Model3D` (déjà dans l'enum, valeur 13). Suppose un viewer
|
||||||
visiteur — dépend du chantier VR/XR (`vr-quest-unity-plan.md`).
|
GLB côté visiteur — dépend du chantier VR/XR (`vr-quest-unity-plan.md`).
|
||||||
|
|
||||||
|
**Deux modèles au catalogue, pas un** (décision 24) : `3d-default` mono-image et `3d-multiview`
|
||||||
|
(`meshy/v7/multi-image-to-3d`). Tous deux sur fal, donc zéro intégration supplémentaire.
|
||||||
|
|
||||||
|
#### Cas d'usage nommé — « l'objet de la vitrine, en 3D »
|
||||||
|
|
||||||
|
C'est le cœur du lot, et il ne se résume pas à un appel d'API : **la qualité du résultat dépend
|
||||||
|
davantage des photos fournies que du prompt.** C'est le seul endroit du Studio où c'est vrai, et
|
||||||
|
l'écran doit être construit autour de ça.
|
||||||
|
|
||||||
|
1. Le conservateur ouvre le sélecteur de ressource d'une `SectionModel3D`, onglet **Générer**,
|
||||||
|
gabarit « **Illustration 3D d'un objet** » — libellé volontairement distinct de « objet
|
||||||
|
numérisé » (photogrammétrie, prestation hors Studio) : les vendre sous le même mot est un
|
||||||
|
risque réputationnel chez une institution scientifique.
|
||||||
|
2. **Quatre emplacements de dépôt nommés et illustrés** — pas une zone « glissez vos images ici » :
|
||||||
|
|
||||||
|
| | Face | Profil | Dos | 3/4 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| | obligatoire | recommandé | recommandé | recommandé |
|
||||||
|
|
||||||
|
Chaque case porte une silhouette d'exemple. Sous le bloc, **une seule consigne**, courte :
|
||||||
|
*même objet, même lumière, fond neutre, objet entier dans le cadre.* C'est la recommandation du
|
||||||
|
modèle, et elle pèse plus lourd que n'importe quel réglage.
|
||||||
|
3. **Le coût se met à jour en direct, et le changement de modèle est annoncé** : 1 photo → modèle
|
||||||
|
mono-image ; dès la 2ᵉ → Meshy v7 multi, **~25× plus cher**. Une ligne explicite au moment où
|
||||||
|
la bascule se produit, jamais une facture découverte après coup (même principe que le coût de
|
||||||
|
régénération par ligne de l'onglet Narrateurs).
|
||||||
|
4. À l'inverse, **ne pas culpabiliser le mono-image** : une seule photo reste un usage légitime et
|
||||||
|
bon marché pour une illustration. La formulation est « plus de vues = plus fidèle », pas
|
||||||
|
« vous avez mal fait ».
|
||||||
|
5. Génération asynchrone en **job composite** (parent + enfants, décision 21), puis **normalisation
|
||||||
|
canonique du GLB** à l'ingestion — échelle, pivot, orientation (décision n°2 d'
|
||||||
|
`immersif-frontiere-plan` §5) : sans elle les POI posés sur un modèle sautent à la
|
||||||
|
régénération suivante.
|
||||||
|
6. **Provenance visible obligatoire et non désactivable** sur le `Model3D` généré (décision n°11
|
||||||
|
du même plan) — contrairement aux images, où la gravure est optionnelle. Un visiteur qui fait
|
||||||
|
tourner « le casque de Léon » croit voir l'objet.
|
||||||
|
7. La ressource validée revient au champ qui a ouvert le sélecteur, et les **POI se posent dans
|
||||||
|
l'éditeur three.js en iframe** (décision n°9) — le vrai morceau non trivial du chantier.
|
||||||
|
|
||||||
⚠️ **Ce lot faisait quatre lignes et se contentait de renvoyer au plan VR, qui lui-même renvoyait
|
⚠️ **Ce lot faisait quatre lignes et se contentait de renvoyer au plan VR, qui lui-même renvoyait
|
||||||
ici.** La frontière est tranchée depuis le 2026-09-11 dans
|
ici.** La frontière est tranchée depuis le 2026-09-11 dans
|
||||||
@ -1685,7 +1793,7 @@ la première migration du Studio, pas en arrivant au lot 11.
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `illustration-painterly` | Illustration peinte | `painterly digital illustration, visible brush strokes, soft edges, rich but controlled colors` |
|
| `illustration-painterly` | Illustration peinte | `painterly digital illustration, visible brush strokes, soft edges, rich but controlled colors` |
|
||||||
| `ligne-claire` | Ligne claire | `ligne claire illustration, clean uniform outlines, flat colors, no gradients` |
|
| `ligne-claire` | Ligne claire | `ligne claire illustration, clean uniform outlines, flat colors, no gradients` |
|
||||||
| `engraving` | Gravure ancienne | `antique copperplate engraving, fine cross-hatching, monochrome ink on aged paper` |
|
| `engraving` | Gravure ancienne | `antique copperplate engraving, fine cross-hatching, black ink only on aged off-white paper, no color` |
|
||||||
| `watercolor` | Aquarelle | `loose watercolor painting, transparent washes, visible paper texture, soft bleeding edges` |
|
| `watercolor` | Aquarelle | `loose watercolor painting, transparent washes, visible paper texture, soft bleeding edges` |
|
||||||
| `gouache-poster` | Affiche gouache | `mid-century gouache poster, bold simplified shapes, limited palette, subtle grain` |
|
| `gouache-poster` | Affiche gouache | `mid-century gouache poster, bold simplified shapes, limited palette, subtle grain` |
|
||||||
| `diorama` | Maquette / diorama | `handcrafted miniature diorama, scale model, tilt-shift, warm studio lighting` |
|
| `diorama` | Maquette / diorama | `handcrafted miniature diorama, scale model, tilt-shift, warm studio lighting` |
|
||||||
@ -1710,7 +1818,7 @@ PromptPreamble =
|
|||||||
+ "Keep a consistent visual style with the reference images." -- si ReferenceResourceIds ≠ ∅
|
+ "Keep a consistent visual style with the reference images." -- si ReferenceResourceIds ≠ ∅
|
||||||
|
|
||||||
NegativeFragment =
|
NegativeFragment =
|
||||||
"no text, no letters, no watermark, no signature, no logo" -- toujours
|
"text, letters, captions, signatures, watermarks, logos, stamps, plate numbers" -- toujours, sans « no » (§9.4)
|
||||||
+ ", {Exclusions, joined ', '}"
|
+ ", {Exclusions, joined ', '}"
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -1718,14 +1826,14 @@ Puces d'exclusion prédéfinies : `anachronisms`, `modern-objects`, `gore`, `nud
|
|||||||
`real-people` (« aucune personne réelle identifiable »), et `text-in-image`, affichée cochée et
|
`real-people` (« aucune personne réelle identifiable »), et `text-in-image`, affichée cochée et
|
||||||
verrouillée puisqu'elle est déjà dans le négatif de base.
|
verrouillée puisqu'elle est déjà dans le négatif de base.
|
||||||
|
|
||||||
⚠️ Toutes les variantes de FLUX.2 n'ont pas de `negative_prompt` séparé : le négatif est alors ajouté au
|
✅ Vérifié le 15/09 sur le schéma OpenAPI fal : ni `flux-2-pro` ni `flux-2-pro/edit` n'ont de `negative_prompt`.
|
||||||
prompt sous la forme `Avoid: …`. À établir modèle par modèle au calibrage, et à consigner dans
|
Le négatif part dans le prompt sous la forme `Avoid: …` — d'où un négatif rédigé **sans « no »**.
|
||||||
`GenerationModel.Params`.
|
|
||||||
|
|
||||||
### 9.3 Gabarits du MVP
|
### 9.3 Gabarits du MVP
|
||||||
|
|
||||||
Contexte de fiche (§3.3, point 4), ajouté après le corps de chaque gabarit :
|
Contexte de fiche (§3.3, point 4), ajouté après le corps de chaque gabarit :
|
||||||
`"Context: {titre de la fiche}. {description en texte brut, 300 caractères max}"`, dans la langue par
|
`"Background knowledge, never written in the image: {titre de la fiche}. {description, 300 caractères max}"`
|
||||||
|
(« Context: » seul faisait écrire le titre en légende, §9.4), dans la langue par
|
||||||
défaut de la configuration.
|
défaut de la configuration.
|
||||||
|
|
||||||
**`puzzle-decor` — Décor d'énigme** · `AcceptsPersona = false` · `landscape_16_9` · 4 variantes ·
|
**`puzzle-decor` — Décor d'énigme** · `AcceptsPersona = false` · `landscape_16_9` · 4 variantes ·
|
||||||
@ -1793,3 +1901,29 @@ Une identité de test par style visé pour les premiers clients — au minimum `
|
|||||||
| Coût | coût réel par image, selon le nombre de références | base de `CreditCost` (décision 16) |
|
| Coût | coût réel par image, selon le nombre de références | base de `CreditCost` (décision 16) |
|
||||||
|
|
||||||
Sortie : les textes des §9.1-9.3 corrigés **dans ce document**, puis re-seedés.
|
Sortie : les textes des §9.1-9.3 corrigés **dans ce document**, puis re-seedés.
|
||||||
|
|
||||||
|
#### Résultats du 2026-09-15 — 61 générations, ≈ 3,13 $ estimés
|
||||||
|
|
||||||
|
Identités de test : A gravure / Fourneau Saint-Michel (refs = planches « Forges » de l'Encyclopédie, domaine public),
|
||||||
|
B aquarelle / Fort de Saint-Héribert, C illustration peinte / Fourneau. Objets : photos Wikimedia libres. Le jugement
|
||||||
|
« à l'aveugle » est celui de Claude sur planches contact : **à refaire par Thomas** avant d'ouvrir à un client.
|
||||||
|
|
||||||
|
| Série | Résultat | Suite |
|
||||||
|
|---|---|---|
|
||||||
|
| Cohérence | A 10/10, B 5/5, C 5/5 lus « du même projet » | ✅ |
|
||||||
|
| Références 0/3/5 | Écart net : avec refs, vraie planche monochrome ; sans, gravure *colorisée* (lueur rose, sépia). 3 → 5 refs : gain faible pour +50 % de coût. Les refs apportent aussi leurs numéros de planche et légendes | budget §3.3 tient ; 3 refs suffisent pour un style |
|
||||||
|
| Image source | 5/5 objets reconnaissables. Mais le négatif « no text » **effaçait la date 1703** d'une taque | instruction sujet complétée : garder les inscriptions de l'objet — date revenue ✅ |
|
||||||
|
| Négatif | v1 « Avoid: no text… » : ~4/10 avec légende/signature. v2 sans « no » + « captions, signatures, plate numbers » : 3/10. v3 + contexte « never written in the image » : **0/10** visible | ✅ les trois corrections sont dans le code et le seed |
|
||||||
|
| Modèle | plafond 10 refs mesuré ; pas de `negative_prompt` ; `/edit` accepte `landscape_16_9` | consigné |
|
||||||
|
| Coût | **0,03 $** l'image (16:9 comme carré : fal compte 1 MP = 1024²) **+ 0,015 $ par référence** : 0,045 $ avec 1 source · 0,075 $ 3 refs · 0,105 $ 5 refs · 0,18 $ 10 refs | voir ci-dessous |
|
||||||
|
|
||||||
|
Coûts **recoupés sur l'export d'usage fal** du 15/09 : 44 MP `flux-2-pro` (1,32 $) + 57,5 MP `/edit` (1,725 $) = 3,05 $,
|
||||||
|
dont ≈ 0,30 $ de portraits faits à la main — le calibrage lui-même a coûté ≈ 2,75 $ (estimé 3,13 $ avec l'ancienne grille).
|
||||||
|
|
||||||
|
**Unité arrêtée le 2026-09-15** : 1 crédit = 0,015 $ de coût fal. `CreditCost = 2` par image,
|
||||||
|
`CreditCostPerReference = 1` par référence (identité, canon, source). Ex. 3 variantes × 3 refs = 15 crédits ≈ 0,23 $.
|
||||||
|
**Prix de vente = coût × marge**, jamais le coût nu : proposition ≈ 0,05 €/crédit (×3,3), packs dégressifs
|
||||||
|
200 = 12 € · 600 = 30 € · 2 000 = 80 € (pire marge ×2,7). La marge couvre aperçus, régénérations, change USD,
|
||||||
|
Stripe, stockage et support. Prix en € à confirmer avec la recharge Stripe (après le gate du lot 4).
|
||||||
|
|
||||||
|
Anachronismes vus malgré l'exclusion : poêle à bois moderne (A-03 ×2), vélo (refs3 v2), plafonniers (B). À surveiller.
|
||||||
|
|||||||