docs: améliorer rendu markdown et navigation mkdocs
- Ajouter ADR-018 (librairies Go) dans TECHNICAL.md - Transformer Shared en menu dépliable dans mkdocs (cohérence avec autres domaines) - Corriger listes markdown (ajout lignes vides avant listes) - Corriger line breaks dans génération BDD (étapes "Et" sur nouvelles lignes) - Ajouter script fix-markdown-lists.sh pour corrections futures Impacte 86 fichiers de documentation et 164 fichiers BDD générés.
This commit is contained in:
@@ -14,11 +14,13 @@
|
||||
| **🚌 Transport** | Variable | Auto GPS + Manuel possible | Bus touristiques, trains panoramiques |
|
||||
|
||||
**Détection automatique** :
|
||||
|
||||
- Vitesse moyenne calculée sur 30 secondes
|
||||
- Suggestion mode au démarrage : "Détection : 🚗 Voiture. Est-ce correct ? [Oui] [Changer]"
|
||||
- User peut forcer mode manuellement (settings)
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Flexibilité maximale créateurs et utilisateurs
|
||||
- Expériences optimisées par type de déplacement
|
||||
- Gestion cas limites (vélo lent vs piéton rapide)
|
||||
@@ -93,12 +95,14 @@
|
||||
| **Zone diffusion** | ✅ | Polygon géographique |
|
||||
|
||||
**Wizard de création** :
|
||||
|
||||
- Étape 1 : Infos générales (titre, description, mode)
|
||||
- Étape 2 : Ajout séquences une par une
|
||||
- Étape 3 : Preview carte (trace + points)
|
||||
- Étape 4 : Validation modération (3 premiers audio-guides)
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Contrôle total créateur sur expérience
|
||||
- Carte preview aide visualiser parcours
|
||||
- Wizard guidé = réduction friction création
|
||||
@@ -133,10 +137,12 @@ Séquence 1 [fin] → PAUSE → User clique → Séquence 2 [fin] → PUB AUTO-P
|
||||
```
|
||||
|
||||
**Fréquence pub** :
|
||||
|
||||
- Gratuits : 1 pub toutes les 5 séquences (paramétrable admin 1/3 à 1/10)
|
||||
- Premium : 0 pub
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Pub s'insère naturellement (pas d'attente utilisateur pour déclencher)
|
||||
- User garde contrôle rythme visite (pause après pub)
|
||||
- Monétisation effective créateurs
|
||||
@@ -199,15 +205,18 @@ Séquence 1 [fin] → PAUSE → User clique → Séquence 2 [fin] → PUB AUTO-P
|
||||
```
|
||||
|
||||
**Navigation libre** :
|
||||
|
||||
- User peut sauter séquences déjà connues
|
||||
- User peut revenir en arrière à tout moment
|
||||
- User peut aller directement à séquence 8 (même si 4-7 non écoutées)
|
||||
|
||||
**Sauvegarde progression** :
|
||||
|
||||
- Checkmarks ✅ sur séquences écoutées >80%
|
||||
- Position exacte sauvegardée dans séquence en cours
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Utilisateur contrôle 100% son rythme
|
||||
- Adapté musées : visitor peut voir physiquement une œuvre lointaine et vouloir écouter sa description
|
||||
- Pas de frustration (liberté totale)
|
||||
@@ -241,6 +250,7 @@ Séquence 1 [fin] → PAUSE → User clique → Séquence 2 [fin] → PUB AUTO-P
|
||||
8. Séquence suivante démarre immédiatement (pas de décompte)
|
||||
|
||||
**Pas de système "7 secondes avant" pour les audio-guides** :
|
||||
|
||||
- Contrairement aux contenus géolocalisés simples (voir [../../recommendation/rules/interactions-navigation.md](../../recommendation/rules/interactions-navigation.md#511-file-dattente-et-commande-suivant))
|
||||
- Les séquences se déclenchent **au point GPS exact** (rayon 30m)
|
||||
- Raison : expérience guidée continue, user sait qu'il suit un parcours
|
||||
@@ -268,6 +278,7 @@ Séquence 1 [fin] → PAUSE → User clique → Séquence 2 [fin] → PUB AUTO-P
|
||||
- Si vitesse **>10 km/h** ET user clique bouton (Suivant/Précédent) :
|
||||
- Toast 3 secondes : "⚠️ Manipulation en conduite détectée. Pour votre sécurité, demandez à un passager."
|
||||
- **Action quand même exécutée** (pas de blocage)
|
||||
|
||||
- Justification : sensibilisation sans bloquer (passager peut légitimement manipuler)
|
||||
|
||||
**Schéma flux** :
|
||||
@@ -278,6 +289,7 @@ Point GPS 1 (30m) → Séquence 1 AUTO → User roule → Distance affichée →
|
||||
```
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Flexibilité maximale : GPS optimise expérience MAIS user garde contrôle
|
||||
- Gestion cas limites : routes fermées, détours, embouteillages
|
||||
- Sécurité : warning sensibilise sans bloquer (passager légitime)
|
||||
@@ -361,12 +373,14 @@ Quand une séquence se termine et qu'il reste un point GPS suivant, l'interface
|
||||
```
|
||||
|
||||
**Progress bar dynamique** :
|
||||
|
||||
- Se remplit au fur et à mesure qu'on se rapproche du point
|
||||
- Calcul : `progress = 100 - (distance_actuelle / distance_initiale * 100)`
|
||||
- Exemple : distance initiale 500m, distance actuelle 175m → progress = 65%
|
||||
- Couleur : vert (#4CAF50) pour la partie remplie, gris (#E0E0E0) pour le reste
|
||||
|
||||
**Bouton "Rejouer séq."** :
|
||||
|
||||
- Permet de réécouter la séquence qui vient de se terminer
|
||||
- User clique → séquence actuelle redémarre depuis 0:00
|
||||
- Utile si distraction pendant l'écoute
|
||||
@@ -414,6 +428,7 @@ if (currentSpeed > 5) {
|
||||
```
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Distance + ETA = info essentielle sans surcharge visuelle
|
||||
- Direction (flèche) = aide se repérer sans carte complexe
|
||||
- Simplicité = moins distraction conducteur
|
||||
@@ -470,10 +485,12 @@ Popup 5 secondes :
|
||||
| **Faire demi-tour** | Lance navigation GPS externe (Google Maps / Waze) vers point manqué |
|
||||
|
||||
**Si user au-delà rayon tolérance (>100m)** :
|
||||
|
||||
- Aucun popup (point trop loin, probablement hors itinéraire)
|
||||
- User peut naviguer manuellement (bouton Suivant)
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Flexibilité créateur (ajuste selon terrain, vitesse prévue)
|
||||
- Gestion intelligente imprévus (détours, routes fermées)
|
||||
- User pas bloqué (toujours moyen avancer)
|
||||
@@ -489,6 +506,7 @@ Popup 5 secondes :
|
||||
##### Comportement bouton [▶|] Suivant
|
||||
|
||||
**1. Premier clic (mode GPS auto actif)** :
|
||||
|
||||
- Désactive GPS automatique
|
||||
- Passe à la séquence suivante immédiatement
|
||||
- Bascule en **mode manuel**
|
||||
@@ -496,12 +514,14 @@ Popup 5 secondes :
|
||||
- Timer 10 secondes démarre
|
||||
|
||||
**2. Deuxième clic (dans les 10 secondes suivantes)** :
|
||||
|
||||
- Sort de l'audio-guide
|
||||
- Audio-guide mis en **pause** (historique conservé)
|
||||
- Retour au **flux normal** (algorithme de recommandation)
|
||||
- Toast 2s : "Audio-guide en pause"
|
||||
|
||||
**3. Clics suivants (après 10 secondes)** :
|
||||
|
||||
- Passe à la séquence suivante (comportement standard mode manuel)
|
||||
- Timer 10 secondes redémarre à chaque clic
|
||||
|
||||
@@ -584,6 +604,7 @@ function onSuivantClick() {
|
||||
```
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Résout le problème des embouteillages (30 min sans contenu)
|
||||
- Double intention claire : désactiver GPS puis sortir
|
||||
- User garde toujours le contrôle (peut reprendre audio-guide plus tard)
|
||||
@@ -625,6 +646,7 @@ function onSuivantClick() {
|
||||
- Pub entre séquences
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Vélo : moins de contrôle qu'auto (obstacles, arrêts), nécessite tolérance
|
||||
- Transport : moins de contrôle utilisateur (suit ligne fixe), rayon large compense
|
||||
- Même UX globale = cohérence
|
||||
@@ -677,6 +699,7 @@ Séquence 2 [fin]
|
||||
| **Transport** | Attente GPS OU user clique Suivant | Attente GPS OU user clique Suivant |
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Monétisation équitable créateurs (tous modes participent)
|
||||
- Pub s'insère naturellement (auto-play, pas d'attente utilisateur)
|
||||
- User garde contrôle : piéton clique Suivant, voiture peut skip manuel
|
||||
@@ -697,10 +720,12 @@ Séquence 2 [fin]
|
||||
| **Revenus pub audio-guides** | 3€ / 1000 écoutes complètes (6% CA pub) |
|
||||
|
||||
**Distinction contenus normaux vs audio-guides** :
|
||||
|
||||
- Dashboard sépare : "Revenus contenus classiques" / "Revenus audio-guides"
|
||||
- Permet créateur voir performance par type
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Transparence créateur (comprend revenus)
|
||||
- Incite création audio-guides (nouvelle source revenus)
|
||||
|
||||
@@ -731,10 +756,12 @@ Séquence 2 [fin]
|
||||
| **Cloud** | PostgreSQL (sync auto) | Multi-device (reprendre sur autre appareil) |
|
||||
|
||||
**Synchronisation** :
|
||||
|
||||
- Sauvegarde locale : chaque fin de séquence + chaque 30s
|
||||
- Sync cloud : à la reconnexion réseau (batch)
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Expérience fluide (pas de perte progression)
|
||||
- Multi-device (démarrer sur iPhone, continuer sur iPad)
|
||||
- Offline-first (fonctionne sans réseau)
|
||||
@@ -744,6 +771,7 @@ Séquence 2 [fin]
|
||||
#### 16.6.2 Interface de reprise
|
||||
|
||||
**Conditions popup** :
|
||||
|
||||
- Dernière écoute **<30 jours**
|
||||
- Progression **>0%** et **<100%** (pas terminé)
|
||||
|
||||
@@ -776,11 +804,13 @@ Séquence 2 [fin]
|
||||
| **Voir séquences** | Affiche liste complète, user choisit séquence départ |
|
||||
|
||||
**Expiration progression** :
|
||||
|
||||
- Progression conservée **30 jours**
|
||||
- Après 30j : popup "Audio-guide expiré. Recommencez depuis le début ?"
|
||||
- Suppression données progression (mais historique "écouté" préservé)
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Contexte clair : user sait exactement où il en est
|
||||
- Flexibilité : reprendre OU recommencer (choix utilisateur)
|
||||
- 30 jours = raisonnable pour tourisme multi-jours ou retour ultérieur
|
||||
@@ -798,10 +828,12 @@ Séquence 2 [fin]
|
||||
5. User clique Reprendre → continue séquence 4
|
||||
|
||||
**Conflit de version** :
|
||||
|
||||
- Si modifications simultanées 2 appareils (rare) : **dernière modification gagne**
|
||||
- Toast : "Progression mise à jour depuis votre autre appareil"
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Confort utilisateur (change d'appareil librement)
|
||||
- Use case réel : planning trajet sur tablette, écoute sur smartphone en voiture
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
**Objectif** : Proposer des contenus audio au moment précis où l'utilisateur passe devant un point d'intérêt géographique, pour enrichir son trajet avec des informations contextuelles liées au paysage.
|
||||
|
||||
**Contrainte principale** : **Sécurité routière**
|
||||
|
||||
- Aucune distraction visuelle (pas de texte à lire)
|
||||
- Notification sonore uniquement + icône minimale
|
||||
- Validation par un seul bouton physique au volant ("Suivant")
|
||||
@@ -26,6 +27,7 @@
|
||||
**Méthode** : API GPS native iOS/Android
|
||||
|
||||
**Principe** :
|
||||
|
||||
- Calcul temps d'arrivée au point GPS basé sur vitesse actuelle et distance
|
||||
- Notification déclenchée **7 secondes avant** d'atteindre le point
|
||||
- Permet au conducteur d'avoir le temps de réagir (2s) + décompte (5s)
|
||||
@@ -118,11 +120,13 @@ class GeoContentDetector(private val fusedLocationClient: FusedLocationProviderC
|
||||
```
|
||||
|
||||
**Cas particulier : vitesse nulle ou très faible** :
|
||||
|
||||
- Si vitesse < 5 km/h (1.4 m/s) ET distance < 50m → notification immédiate
|
||||
- Exemple : user arrêté à un feu rouge à 30m du point
|
||||
- Évite notification trop tardive quand user redémarre
|
||||
|
||||
**Fréquence de vérification** :
|
||||
|
||||
- GPS updates : toutes les 1 seconde (balance batterie/précision)
|
||||
- Calcul ETA : à chaque update GPS
|
||||
- Notification : déclenchée immédiatement quand ETA ≤ 7s
|
||||
@@ -134,6 +138,7 @@ class GeoContentDetector(private val fusedLocationClient: FusedLocationProviderC
|
||||
**Philosophie** : **Minimalisme absolu** pour sécurité routière
|
||||
|
||||
❌ **Pas de** :
|
||||
|
||||
- Titre texte à lire
|
||||
- Description longue
|
||||
- Bouton "Annuler" ou "Plus tard"
|
||||
@@ -141,6 +146,7 @@ class GeoContentDetector(private val fusedLocationClient: FusedLocationProviderC
|
||||
- Image/cover du contenu
|
||||
|
||||
✅ **Uniquement** :
|
||||
|
||||
- Son bref (notification)
|
||||
- Icône selon tag du contenu
|
||||
- Compteur chiffres (7→1)
|
||||
@@ -179,12 +185,14 @@ class GeoContentDetector(private val fusedLocationClient: FusedLocationProviderC
|
||||
```
|
||||
|
||||
**Évolution du compteur** :
|
||||
|
||||
- Affichage pendant 7 secondes
|
||||
- Compteur décrémente : 7 → 6 → 5 → 4 → 3 → 2 → 1 → disparaît
|
||||
- Police grande (72pt), bold, couleur blanche
|
||||
- Background semi-transparent (noir 50% opacity)
|
||||
|
||||
**Notification sonore** :
|
||||
|
||||
- **Son** : bip court (0.5s) ou "ding" doux personnalisé RoadWave
|
||||
- **Volume** : suit le volume système notification (indépendant du volume media)
|
||||
- **Pas de vibration** : inutile en voiture (téléphone sur support)
|
||||
@@ -200,6 +208,7 @@ class GeoContentDetector(private val fusedLocationClient: FusedLocationProviderC
|
||||
**Décision** : Notification sonore uniquement en mode CarPlay/Android Auto
|
||||
|
||||
**Contexte** :
|
||||
|
||||
- [CarPlay Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/carplay) interdisent les overlays qui "takeover" l'écran
|
||||
- [Android Auto Media Apps Guidelines](https://developer.android.com/training/cars/media) imposent des interactions minimales
|
||||
- Sécurité routière maximale = pas de distraction visuelle
|
||||
@@ -207,11 +216,13 @@ class GeoContentDetector(private val fusedLocationClient: FusedLocationProviderC
|
||||
**Comportement en mode CarPlay/Android Auto** :
|
||||
|
||||
❌ **Désactivé** :
|
||||
|
||||
- Icône overlay
|
||||
- Compteur visuel (7...6...5...)
|
||||
- Tout élément graphique supplémentaire
|
||||
|
||||
✅ **Activé uniquement** :
|
||||
|
||||
- Notification sonore (bip ou ding)
|
||||
- Bouton "Suivant" standard (déjà présent)
|
||||
|
||||
@@ -280,12 +291,14 @@ class NotificationManager(private val context: Context) {
|
||||
6. Contenu géolocalisé démarre après 5s
|
||||
|
||||
**Justification** :
|
||||
|
||||
- ✅ Conformité maximale CarPlay/Android Auto guidelines
|
||||
- ✅ Sécurité routière (pas de distraction visuelle)
|
||||
- ✅ User peut toujours valider via bouton "Suivant" standard
|
||||
- ✅ Apps comparables (Waze, Apple Maps) utilisent alertes sonores similaires
|
||||
|
||||
**Alternative envisagée** : Mini-badge sur bouton "Suivant"
|
||||
|
||||
- Moins invasif qu'un compteur
|
||||
- Mais toujours considéré comme overlay (zone grise)
|
||||
- **Décision** : Privilégier conformité maximale (sonore uniquement)
|
||||
@@ -297,15 +310,18 @@ class NotificationManager(private val context: Context) {
|
||||
**User appuie sur "Suivant"** :
|
||||
|
||||
**Étape 1 : Transition visuelle (0.3s)**
|
||||
|
||||
- Icône + compteur "7" disparaissent avec fade out
|
||||
- Nouveau compteur "5" apparaît (plus grand, centré)
|
||||
|
||||
**Étape 2 : Décompte 5 secondes**
|
||||
|
||||
- Compteur décrémente : 5 → 4 → 3 → 2 → 1
|
||||
- Contenu actuel continue de jouer **normalement** (pas de baisse volume)
|
||||
- User entend le contenu en cours pendant le décompte
|
||||
|
||||
**Étape 3 : Fin du décompte**
|
||||
|
||||
- Compteur atteint "0"
|
||||
- Fade out 0.3s du contenu actuel
|
||||
- Fade in 0.3s du contenu géolocalisé
|
||||
@@ -327,6 +343,7 @@ T+5s : Décompte atteint 0
|
||||
```
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Évite silence inconfortable pendant décompte
|
||||
- User continue d'écouter du contenu intéressant
|
||||
- Transition naturelle
|
||||
@@ -353,6 +370,7 @@ T+5s : Décompte atteint 0
|
||||
### 17.3 Limitation anti-spam
|
||||
|
||||
**Problème identifié** :
|
||||
|
||||
- Routes riches en points d'intérêt (parcours touristiques)
|
||||
- Risque de notifier toutes les 30 secondes
|
||||
- Fatigue utilisateur + distraction conducteur
|
||||
@@ -362,6 +380,7 @@ T+5s : Décompte atteint 0
|
||||
#### 17.3.1 Quota : 6 contenus géolocalisés par heure
|
||||
|
||||
**Règle** :
|
||||
|
||||
- Maximum **6 contenus géolocalisés** notifiés par heure
|
||||
- Fenêtre glissante : calcul sur les 60 dernières minutes (pas réinitialisation à 0h)
|
||||
- Si quota atteint : notifications suivantes ignorées silencieusement
|
||||
@@ -380,6 +399,7 @@ T+5s : Décompte atteint 0
|
||||
```
|
||||
|
||||
**Exception : audio-guides multi-séquences** :
|
||||
|
||||
- Un audio-guide avec N séquences compte comme **1 seul contenu** dans le quota
|
||||
- Une fois démarré, toutes ses séquences sont jouables (pas de limite)
|
||||
- Exemple : audio-guide 8 séquences = 1 quota, contenus simples restants = 5
|
||||
@@ -422,12 +442,14 @@ func RecordNotification(userID string, contentID string) {
|
||||
#### 17.3.2 Cooldown : 10 minutes après notification ignorée
|
||||
|
||||
**Règle** :
|
||||
|
||||
- Si user ne clique pas sur "Suivant" pendant les 7 secondes
|
||||
- → Cooldown de **10 minutes** activé
|
||||
- → Aucune nouvelle notification pendant ce délai
|
||||
- → Même si quota non atteint
|
||||
|
||||
**Justification** :
|
||||
|
||||
- User a probablement une raison de ne pas vouloir de contenu géolocalisé maintenant
|
||||
- Évite harcèlement (notifications répétées ignorées)
|
||||
- Respecte choix implicite de l'utilisateur
|
||||
@@ -458,6 +480,7 @@ func ActivateCooldown(userID string) {
|
||||
```
|
||||
|
||||
**Exception : notification validée (user a cliqué)** :
|
||||
|
||||
- Pas de cooldown si user a cliqué sur "Suivant"
|
||||
- Même si user skip le contenu ensuite (pendant le décompte ou après)
|
||||
- Cooldown = pénalité uniquement pour notification complètement ignorée
|
||||
@@ -503,6 +526,7 @@ Timeline :
|
||||
6. User appuie "Précédent" → **retour au contenu géolocalisé à 42s**
|
||||
|
||||
**Règle** : Comme décrit dans [../../recommendation/rules/interactions-navigation.md](../../recommendation/rules/interactions-navigation.md#52-commande-précédent) :
|
||||
|
||||
- Si temps écouté ≥ 10 secondes → replay contenu actuel depuis début
|
||||
- Si temps écouté < 10 secondes → retour contenu précédent (position exacte)
|
||||
|
||||
@@ -567,6 +591,7 @@ if (avgSpeedKmh < 5) {
|
||||
```
|
||||
|
||||
**Hysteresis (éviter basculements intempestifs)** :
|
||||
|
||||
- Nouvelle vitesse doit être stable pendant **10 secondes** avant basculement
|
||||
- Exemple : user passe de 20 km/h à 3 km/h (arrêt feu rouge)
|
||||
- Si vitesse remonte à 20 km/h après 8s → pas de basculement
|
||||
@@ -595,6 +620,7 @@ if (avgSpeedKmh < 5) {
|
||||
| **Type contenu** | Audio-guides uniquement | Tous contenus géolocalisés |
|
||||
|
||||
**Transition fluide** :
|
||||
|
||||
- Pas de popup ou message à l'utilisateur
|
||||
- Basculement invisible et automatique
|
||||
- Permissions ajustées automatiquement (si déjà accordées)
|
||||
@@ -608,6 +634,7 @@ if (avgSpeedKmh < 5) {
|
||||
**Scénario** : Autoroute A6, vitesse 130 km/h, contenu géolocalisé détecté.
|
||||
|
||||
**Calcul** :
|
||||
|
||||
- Vitesse : 130 km/h = 36.1 m/s
|
||||
- ETA 7s → distance notification : 7 × 36.1 = **252 mètres** avant le point
|
||||
- User a 7s pour cliquer "Suivant"
|
||||
@@ -618,6 +645,7 @@ if (avgSpeedKmh < 5) {
|
||||
**Conclusion** : Le système fonctionne même à très haute vitesse ✅
|
||||
|
||||
**Cas extrême : 180 km/h** (illégal mais théoriquement possible) :
|
||||
|
||||
- Vitesse : 180 km/h = 50 m/s
|
||||
- ETA 7s → distance notification : 350m avant le point
|
||||
- Décompte 5s : user parcourt 250m
|
||||
@@ -655,6 +683,7 @@ T+57s : User clique "Suivant" → contenu Château B démarre
|
||||
**Solution proposée** : **Ajuster le cooldown selon validation précédente**
|
||||
|
||||
Nouvelle règle :
|
||||
|
||||
- Notification validée (user a cliqué) : pas de cooldown
|
||||
- Notification ignorée (user n'a pas cliqué) : cooldown 10 min
|
||||
- Exception : si 2+ notifications validées consécutives, cooldown réduit à 5 min
|
||||
@@ -687,18 +716,21 @@ func CalculateCooldown(userID string) time.Duration {
|
||||
**Scénario** : User se gare à 30m d'un château, sort de voiture, visite 1h, revient.
|
||||
|
||||
**Problème** :
|
||||
|
||||
- Vitesse < 5 km/h + distance < 50m → notification immédiate
|
||||
- Mais user en mode "stationnement", pas en mode "conduite"
|
||||
|
||||
**Solution** : **Détection mode stationnement**
|
||||
|
||||
Règle :
|
||||
|
||||
- Si vitesse < 1 km/h pendant **2 minutes** consécutives
|
||||
- → Mode "stationnement" activé
|
||||
- → Pas de notification de contenus géolocalisés
|
||||
- → Basculement automatique en mode piéton (push arrière-plan)
|
||||
|
||||
**Reprise conduite** :
|
||||
|
||||
- Vitesse > 5 km/h pendant 10s
|
||||
- → Mode "voiture" réactivé
|
||||
- → Notifications reprennent (si quota non atteint)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
**Décision** : Formats universels avec encodage asynchrone
|
||||
|
||||
**Formats acceptés** :
|
||||
|
||||
- ✅ MP3 (`.mp3`)
|
||||
- ✅ AAC (`.aac`, `.m4a`)
|
||||
- ❌ WAV, FLAC (trop lourds, inutiles en voiture)
|
||||
@@ -31,6 +32,7 @@
|
||||
```
|
||||
|
||||
**Temps d'encodage estimé** :
|
||||
|
||||
- Contenu 5 min → ~30 secondes
|
||||
- Podcast 1h → ~5 minutes
|
||||
- Podcast 4h → ~20 minutes
|
||||
@@ -54,11 +56,13 @@
|
||||
| 2.0x | Survol rapide (modérateurs) |
|
||||
|
||||
**Disponible pour** :
|
||||
|
||||
- ✅ Modérateurs (validation rapide : 30s → 15s à 2x)
|
||||
- ✅ Auditeurs (tous les contenus)
|
||||
- ✅ Standard industrie (YouTube, Spotify, Apple Podcasts)
|
||||
|
||||
**Justification** :
|
||||
|
||||
- **Simplicité** : 2 formats couvrent 95% des cas d'usage
|
||||
- **Coût optimisé** : pas de conversion WAV/FLAC lourds
|
||||
- **Stockage réduit** : suppression original après encodage
|
||||
@@ -84,6 +88,7 @@
|
||||
**Zone de diffusion (obligatoire)** :
|
||||
|
||||
Options mutuellement exclusives :
|
||||
|
||||
- **Point GPS** : latitude + longitude + rayon (100m à 10km)
|
||||
- **Ville** : sélection dans référentiel INSEE
|
||||
- **Département** : sélection liste
|
||||
@@ -91,6 +96,7 @@ Options mutuellement exclusives :
|
||||
- **National** : France entière
|
||||
|
||||
**Tags disponibles** (1 à 3 obligatoires) :
|
||||
|
||||
- Automobile
|
||||
- Voyage
|
||||
- Famille
|
||||
@@ -105,12 +111,14 @@ Options mutuellement exclusives :
|
||||
- Santé
|
||||
|
||||
**Champs optionnels** :
|
||||
|
||||
- ❌ Description (ajout ultérieur)
|
||||
- ❌ Image couverture (génération auto)
|
||||
|
||||
**Image de couverture par défaut** :
|
||||
|
||||
Génération automatique selon règles :
|
||||
|
||||
- Icône selon type géo : 📍 Ancré / 🌍 Contextuel / 🎧 Neutre
|
||||
- Couleur selon tag principal : bleu (Auto), vert (Voyage), rouge (Musique), etc.
|
||||
- Format 800×800px, PNG
|
||||
@@ -127,6 +135,7 @@ Classification : Tout public
|
||||
```
|
||||
|
||||
**Justification** :
|
||||
|
||||
- **Friction minimale** : 5 champs max = 2 min de publication
|
||||
- **Publication rapide** : pas de blocage sur description/image
|
||||
- **Coût 0** : pas de génération IA au MVP
|
||||
@@ -161,6 +170,7 @@ Classification : Tout public
|
||||
| **Zone diffusion** | Cohérente (pas "Tour Eiffel" avec zone "National") |
|
||||
|
||||
**Délai de validation** :
|
||||
|
||||
- Objectif : **24-48h** (jours ouvrés)
|
||||
- Priorité : FIFO (First In First Out)
|
||||
- Weekend : délai peut atteindre 72h
|
||||
@@ -169,11 +179,13 @@ Classification : Tout public
|
||||
**Notification créateur** :
|
||||
|
||||
**Si accepté** :
|
||||
|
||||
- Email + push : "✅ Votre contenu '[Titre]' est en ligne !"
|
||||
- Lien direct vers le contenu
|
||||
- Compteur : "2/3 contenus validés pour devenir créateur vérifié"
|
||||
|
||||
**Si refusé** :
|
||||
|
||||
- Email + push : "❌ Contenu '[Titre]' refusé"
|
||||
- Raison détaillée : "Qualité audio insuffisante" / "Tags non pertinents" / "Classification incorrecte" / etc.
|
||||
- Lien vers règles de publication
|
||||
@@ -182,11 +194,13 @@ Classification : Tout public
|
||||
**Après 3 validations** :
|
||||
|
||||
Créateur obtient **statut "Vérifié"** :
|
||||
|
||||
- Badge ✓ visible sur profil
|
||||
- Contenus futurs publiés **immédiatement** (modération a posteriori uniquement)
|
||||
- Modération seulement si signalé par utilisateurs
|
||||
|
||||
**Outils modérateur** :
|
||||
|
||||
- Écoute accélérée (1.5x ou 2x) = double productivité
|
||||
- Interface dédiée : queue de contenus à valider
|
||||
- Raccourcis clavier : A (Accepter), R (Rejeter), Espace (Pause)
|
||||
@@ -197,6 +211,7 @@ Créateur obtient **statut "Vérifié"** :
|
||||
⚠️ **Non implémenté au MVP** (complexité juridique)
|
||||
|
||||
Vision future (envisageable) :
|
||||
|
||||
- Créateurs établis peuvent opt-in "Modérateur communautaire"
|
||||
- Formation obligatoire (30 min) + quiz (80%)
|
||||
- Pré-validation uniquement (validation finale toujours par équipe RoadWave)
|
||||
@@ -204,6 +219,7 @@ Vision future (envisageable) :
|
||||
- Attribution aléatoire (pas de collusion)
|
||||
|
||||
**Justification décision MVP** :
|
||||
|
||||
- **Responsabilité juridique** : plateforme reste responsable (DSA EU)
|
||||
- **Qualité garantie** : modérateurs formés et mandatés
|
||||
- **Anti-spam efficace** : bloque 95% des abus dès le début
|
||||
@@ -233,18 +249,22 @@ Vision future (envisageable) :
|
||||
**Raisons restrictions** :
|
||||
|
||||
**Audio non modifiable** :
|
||||
|
||||
- Évite fraude : uploader contenu validé → remplacer par spam
|
||||
- Intégrité : auditeurs doivent écouter ce qui a été validé
|
||||
|
||||
**Zone/Type non modifiables** :
|
||||
|
||||
- Évite manipulation : créer "Local Paris" → changer en "National" pour boost visibilité
|
||||
- Évite abus : créer "Neutre" (faible pondération géo) → changer en "Ancré" (forte pondération)
|
||||
|
||||
**Classification non modifiable** :
|
||||
|
||||
- Évite contournement : uploader "Tout public" → passer en "18+" sans revalidation
|
||||
- Sécurité : garantit que classification a été vérifiée
|
||||
|
||||
**Si besoin de changer audio/zone/classification** :
|
||||
|
||||
- Action : **Supprimer contenu + republier**
|
||||
- Si créateur <3 contenus validés : retourne en file validation
|
||||
- Si créateur ≥3 contenus validés : publication immédiate
|
||||
@@ -269,11 +289,13 @@ Créateur supprime podcast écouté par 1000 personnes
|
||||
```
|
||||
|
||||
**Notifications suppression** :
|
||||
|
||||
- Pas de notification aux auditeurs (pour éviter effet Streisand)
|
||||
- Historique reste consultable : "Vous avez écouté ce contenu le [date]"
|
||||
- Si auditeur tente de réécouter : "Ce contenu n'est plus disponible"
|
||||
|
||||
**Justification** :
|
||||
|
||||
- **Simplicité** : règles claires et non-ambiguës
|
||||
- **Sécurité** : évite manipulations algorithme et contournements modération
|
||||
- **Contrôle créateur** : liberté totale de supprimer (RGPD)
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
4. Mention titre + artiste dans métadonnées (recommandé)
|
||||
|
||||
**Justification juridique** :
|
||||
|
||||
- Directive UE 2019/790 : exception citation à des fins de critique
|
||||
- Jurisprudence FR : citation courte autorisée si justifiée
|
||||
- 30s = standard industrie (YouTube, TikTok)
|
||||
@@ -108,6 +109,7 @@ Validation normale continue
|
||||
- ✅ Modération **a posteriori uniquement** (si signalé)
|
||||
|
||||
**Justification** :
|
||||
|
||||
- **Coût 0€** : réutilise écoute 30s déjà effectuée
|
||||
- **Scalable** : pas de validation pour créateurs établis
|
||||
- **Pragmatique** : détecte violations évidentes (90% des cas)
|
||||
@@ -175,6 +177,7 @@ Validation normale continue
|
||||
**Détail sanctions** :
|
||||
|
||||
**Avertissement (1ère fois)** :
|
||||
|
||||
- Suppression contenu immédiate
|
||||
- Email + push + in-app : "⚠️ Contenu retiré pour violation droits d'auteur"
|
||||
- Explication pédagogique : règles musique, lien vers CGU
|
||||
@@ -182,22 +185,26 @@ Validation normale continue
|
||||
- Créateur peut republier version corrigée
|
||||
|
||||
**Strike 1 (2e fois)** :
|
||||
|
||||
- Suppression contenu
|
||||
- Strike ajouté au compteur (visible profil créateur)
|
||||
- Suspension upload **3 jours**
|
||||
- Email détaillé : titre détecté, timestamp, règle violée
|
||||
|
||||
**Strike 2 (3e fois)** :
|
||||
|
||||
- Idem Strike 1
|
||||
- Suspension upload **7 jours**
|
||||
- Warning : "Strike 2/4 - Vous approchez du seuil critique"
|
||||
|
||||
**Strike 3 (4e fois)** :
|
||||
|
||||
- Idem Strike 2
|
||||
- Suspension upload **30 jours**
|
||||
- Warning : "Strike 3/4 - Prochaine violation = ban définitif"
|
||||
|
||||
**Strike 4 - Ban définitif (5e fois)** :
|
||||
|
||||
- Désactivation compte créateur
|
||||
- Tous contenus dépubliés
|
||||
- Pas de création nouveau compte (email/téléphone blacklisté)
|
||||
@@ -226,6 +233,7 @@ Créateur a Strike 2 (7 jours de suspension)
|
||||
```
|
||||
|
||||
**Justification** :
|
||||
|
||||
- **Tolérance 1ère fois** : évite punir erreurs honnêtes
|
||||
- **Escalade progressive** : dissuasion sans brutalité
|
||||
- **4 strikes avant ban** : cohérent avec système global (sections 9, 14)
|
||||
@@ -239,6 +247,7 @@ Créateur a Strike 2 (7 jours de suspension)
|
||||
**Décision** : Réutilise système existant section 14.3.3
|
||||
|
||||
**Accès** :
|
||||
|
||||
- Bouton "Contester cette décision" dans notification sanction
|
||||
- Délai : **7 jours** après notification
|
||||
|
||||
@@ -266,11 +275,13 @@ Champs standards (voir section 14) **+** champs spécifiques :
|
||||
**Cas particulier : Musique libre mal détectée**
|
||||
|
||||
Si créateur prouve musique = licence Epidemic Sound / Artlist :
|
||||
|
||||
- ✅ Appel automatiquement accepté
|
||||
- ✅ Ajout titre à **whitelist interne** (évite futures erreurs)
|
||||
- ✅ Excuse + compensation (ex: 1 mois Premium offert)
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Réutilise processus éprouvé (section 14)
|
||||
- Preuve licence = résout 90% des cas
|
||||
- Délai 72h acceptable (pas de suspension immédiate sur appel)
|
||||
@@ -309,6 +320,7 @@ Interdit :
|
||||
```
|
||||
|
||||
**Justification** :
|
||||
|
||||
- Prévention > sanction (économie modération)
|
||||
- Créateurs informés = moins de violations
|
||||
- Coût : 0€ (documentation statique)
|
||||
@@ -382,12 +394,14 @@ Modérateur humain vérifie :
|
||||
**Coût total MVP** : **0€** (validation manuelle intégrée)
|
||||
|
||||
**Conformité juridique** :
|
||||
|
||||
- ✅ Directive UE 2019/790 (droit d'auteur + exception citation)
|
||||
- ✅ DSA (Digital Services Act) : modération réactive + droit d'appel
|
||||
- ✅ SACEM/SDRM : protection ayants droit + processus contentieux
|
||||
- ✅ Fair use : tolérance 30s conforme jurisprudence FR/UE
|
||||
|
||||
**Scalabilité** :
|
||||
|
||||
- 0-1000 contenus/mois : validation manuelle suffisante (3h/mois modération)
|
||||
- 1000-10K contenus/mois : fingerprinting open-source requis
|
||||
- 10K+ contenus/mois : API commerciale à considérer (ACRCloud)
|
||||
@@ -404,6 +418,7 @@ Modérateur humain vérifie :
|
||||
---
|
||||
|
||||
**Lien avec autres sections** :
|
||||
|
||||
- Section 4.3 : Validation des 3 premiers contenus (workflow intégré)
|
||||
- Section 7.2 : Interdictions lives + fingerprinting post-MVP
|
||||
- Section 14 : Système modération (signalements, sanctions, appels)
|
||||
|
||||
@@ -18,12 +18,14 @@
|
||||
4. Après 15s → **Live public**, auditeurs peuvent rejoindre
|
||||
|
||||
**Notification abonnés** :
|
||||
|
||||
- ✅ **Push notification immédiate** à tous les abonnés dans la zone géographique
|
||||
- Message : "🔴 [Nom créateur] est en direct : [Titre live]"
|
||||
- Tap notification → ouverture app + lecture live immédiate
|
||||
- **Filtrage géographique** : si abonné hors zone, pas de notif (évite frustration)
|
||||
|
||||
**Limite de durée** :
|
||||
|
||||
- **Maximum 8 heures** par session live
|
||||
- Warning créateur à 7h30 : "Votre live se terminera dans 30 min"
|
||||
- Si besoin continuer → arrêt + redémarrage nouveau live (évite abus ressources serveur)
|
||||
@@ -56,12 +58,14 @@
|
||||
```
|
||||
|
||||
**Détection violations** :
|
||||
|
||||
- **Signalement utilisateurs** : bouton "Signaler" accessible pendant live
|
||||
- **IA audio fingerprint** : détection musique protégée en arrière-plan (post-MVP, voir [Section 18](detection-contenu-protege.md))
|
||||
- **Modération réactive** : modérateurs peuvent écouter lives signalés en temps réel
|
||||
- **Coupure immédiate** : modérateur peut arrêter live si contenu illégal évident
|
||||
|
||||
**Justification** :
|
||||
|
||||
- **Buffer 15s** : équilibre entre test qualité et friction minimale
|
||||
- **Notification abonnés** : engagement maximal, valeur ajoutée live
|
||||
- **8h max** : couvre 99% cas usage (podcasts longs, émissions radio) sans abus
|
||||
@@ -117,11 +121,13 @@
|
||||
| **Modifier replay** | ❌ Non | Intégrité enregistrement |
|
||||
|
||||
**Conservation fichier source** :
|
||||
|
||||
- Opus raw conservé **7 jours** après fin live (backup)
|
||||
- Suppression automatique après 7j (économie stockage)
|
||||
- Si replay supprimé par créateur → fichier raw supprimé immédiatement
|
||||
|
||||
**Justification** :
|
||||
|
||||
- **Compte à rebours 5s** : outro propre, pas de coupure brutale
|
||||
- **Tolérance 60s** : évite arrêts intempestifs (tunnel, changement cellule)
|
||||
- **Enregistrement auto** : valorisation contenu éphémère, génération contenu pérenne
|
||||
@@ -172,6 +178,7 @@
|
||||
**Décision ferme** : ❌ **Aucun chat en direct, ni maintenant ni dans le futur**
|
||||
|
||||
**Raisons** :
|
||||
|
||||
- **Sécurité routière** : pas de distraction en voiture (focus UX)
|
||||
- **Harcèlement** : évite contenu haineux, insultes, trolling
|
||||
- **Modération** : pas de coût modération temps réel (impossible à scale)
|
||||
@@ -189,9 +196,11 @@
|
||||
| **Réactions emoji** | ❌ | Jamais implémenté (décision définitive) |
|
||||
|
||||
**Messages utilisateur** :
|
||||
|
||||
- "💬 Les discussions ne sont pas disponibles sur RoadWave pour garantir votre sécurité en voiture et éviter le harcèlement."
|
||||
|
||||
**Justification décision définitive** :
|
||||
|
||||
- **UX cohérente** : RoadWave = écoute en conduisant, pas réseau social interactif
|
||||
- **Bien-être** : évite toxicité, harcèlement, haine (fléau réseaux sociaux)
|
||||
- **Juridique** : pas de risque contentieux modération chat (DSA EU)
|
||||
@@ -223,6 +232,7 @@ Auditeurs (App mobile, HLS natif)
|
||||
6. **Post-live** → Job async : Opus → MP3 256 kbps → Publication replay
|
||||
|
||||
**Dépendances** :
|
||||
|
||||
- ✅ **Pion WebRTC** (Go library, open source, MIT license)
|
||||
- ✅ **FFmpeg** (conversion audio, LGPL/GPL)
|
||||
- ✅ **NGINX** (cache et distribution HLS, open source)
|
||||
@@ -230,6 +240,7 @@ Auditeurs (App mobile, HLS natif)
|
||||
- ✅ **PostgreSQL + Redis** (métadonnées live + cache)
|
||||
|
||||
**Avantages** :
|
||||
|
||||
- ✅ Pas de dépendance Google/Facebook/Cloudflare (souveraineté)
|
||||
- ✅ WebRTC standard ouvert (Pion = lib Go pure)
|
||||
- ✅ Réutilise infra HLS existante (pas de doublon)
|
||||
@@ -245,6 +256,7 @@ Auditeurs (App mobile, HLS natif)
|
||||
| **Scale** | 1M-10M | Kubernetes auto-scale (2000+ lives) | +1K€ + bande passante |
|
||||
|
||||
**Bande passante** :
|
||||
|
||||
- Live : 48 kbps × nb_auditeurs (via NGINX Cache, segments)
|
||||
- Exemple : 100 auditeurs = 4.8 Mbps = ~2 Go/heure via cache
|
||||
- Coût estimé : ~0.02€/heure pour 100 auditeurs
|
||||
|
||||
Reference in New Issue
Block a user