# GAB-024 · GenericVideoBlock — « Bloc vidéo YouTube / MP4 »

**Archétype / renderer_key :** `media_viewer` (cartographie) · **module :** EdTechPlayKit
**renderer_key à concevoir (pas de moteur kit)** : `media_viewer` ne correspond à aucun moteur kit existant — le renderer est dérivé directement de l'écran source.
**Critère validé :** changer le JSON change le titre, l'URL, la durée, le fallback et la transcription sans modifier le HTML. check.py 12/12.

## Pack (structure officielle par-GAB)

```
GAB-024/
  renderer.html            ← moteur bloc vidéo (ne pas modifier par instance)
  instance.example.json    ← SOURCE DE VÉRITÉ (contenu réel, à plat)
  schema.contract.json     ← contrat de validation
  README-contract.md       ← ce fichier
```

## Champs requis (instance, à plat)

`gab_id` · `video_id` · `title` · `video_url` · `fallback_text`

Optionnels : `video_type` (enum youtube/mp4/vimeo), `thumbnail_url`, `duration_label`, `transcript`.

## Ce qui vient du JSON vs HTML

- **JSON** : titre affiché sous le player + dans le hero, URL de la vidéo, URL du thumbnail, durée, texte de fallback + lien direct, transcription textuelle.
- **HTML** : structure player (aspect-ratio 16/9), bouton play, animation barres EQ, barre de progression, toggle transcript, layout, fallback.

## Garde-fous (child_safety / accessibilité)

- **fallback_text obligatoire** : aucun contenu vidéo sans alternative textuelle (CNIL, WCAG).
- **transcript optionnelle** : si fournie, affichée via toggle — améliore l'accessibilité et le SEO.
- **Aucune autoplay** : lecture uniquement sur interaction utilisateur explicite (clic ou Entrée/Espace).
- **BLOCKED** si `video_id` / `title` / `video_url` / `fallback_text` absent.
- **Pas de lien externe concurrents EdTech** (règle réseau DIGIKA).

## _TODO — Contenus manquants dans la source HTML

Les champs suivants sont présents dans l'instance avec `_TODO` car non fournis par la source HTML hardcodée :

| Champ | Raison |
|---|---|
| `video_url` | URL YouTube/MP4 absente de l'écran source (player simulé) |
| `thumbnail_url` | Aucune image de prévisualisation dans la démo source |
| `duration_label` | Durée non affichée dans la démo source |
| `transcript` | Transcription absente de la démo source |

Ces `_TODO` sont à remplir lors de la production de contenu réel. Le renderer gère le cas `_TODO` : il ne plante pas, il masque les éléments optionnels manquants.

## QA à vérifier

1. Modifier `title` → titre changé dans hero + info block sans modifier le HTML (critère d'or).
2. `video_url` absent → BLOCKED propre affiché.
3. `title` absent → BLOCKED propre affiché.
4. Clic player → état `.playing`, bouton play masqué, barres EQ animées, progression démarre.
5. Deuxième clic → pause, progression conservée.
6. `thumbnail_url` fourni → image visible avant lecture.
7. `transcript` fourni → bouton toggle visible, expand/collapse fonctionne.
8. Responsive 375/768/1024 → aspect-ratio 16/9 respecté, 0 débordement.

## external_refs / dependencies

Ce GAB s'insère dans une session EdTechPlayKit. Il est **display-only** :
- Il affiche la vidéo et trace l'interaction (lecture/pause/progression).
- Il **n'écrit pas** de XP ni d'historique : c'est le **GamificationAdapter** qui enregistre l'activité.
- Pour un outil interactif externe, voir **GAB-025 · GenericEmbedBlock**.
- Pour un contenu audio seul, voir le module **AudioLearning**.

## Source

`INDEX-300-playkit-GAB-021-025-PLAYABLE.html` (stage `data-tpl="24"`, handler `videoToggle()`).
