diff --git a/docs/superpowers/specs/2026-03-22-av1-opus-design.md b/docs/superpowers/specs/2026-03-22-av1-opus-design.md new file mode 100644 index 0000000..813d001 --- /dev/null +++ b/docs/superpowers/specs/2026-03-22-av1-opus-design.md @@ -0,0 +1,144 @@ +# Spec : Migration AV1-SVT + Opus + +**Date :** 2026-03-22 +**Objectif :** Remplacer le pipeline H.265/AAC par AV1-SVT/Opus avec sélection automatique du CRF via `ab-av1 crf-search`. Passer la sortie en MKV. Simplifier la structure (suppression du chunking, de l'entrelacement automatique, du remux MP4). + +--- + +## Contexte + +`vid_convert.py` est un script Python standalone de conversion vidéo pour l'archivage de demux DVD/BluRay. Il orchestre FFmpeg, mkvmerge et des outils tiers pour produire un fichier optimisé qualité/poids. + +**Sources attendues :** demux HEVC (H.265) en conteneur MKV ou MP4, ou fichiers DVD (MPEG-2, SD). +État actuel : H.265 (libx265), AAC-LC (libfdk_aac), encodage en chunks de 300s, sortie MP4. + +--- + +## Changements + +### 1. Codec vidéo : libx265 → libsvtav1 + +- Encodeur : `libsvtav1` +- Pixel format : `yuv420p10le` (10 bits, inchangé) +- Paramètres SVT-AV1 via `-svtav1-params` (remplace `-x265-params`) +- Suppression de la logique de chunks (300s) : encodage en une seule passe +- Sortie intermédiaire : `{file}_video.mkv` (une seule piste vidéo, remplace les multiples `{file}_video_t*.mkv`) + +### 2. Sélection du CRF via ab-av1 + +Nouvelle fonction `find_crf(file, enc_options)` : + +- Commande : `ab-av1 crf-search --input {file} --encoder libsvtav1 --vmaf 96 --enc {enc_options}` +- Cible VMAF : **96** (codé en dur) +- **Pour les sources HDR10**, ajouter `--vmaf-model path=/usr/share/vmaf/model/vmaf_4k_v0.6.1.json` si disponible, afin d'utiliser un modèle VMAF calibré HDR. Si le modèle est absent, `ab-av1` utilise le modèle par défaut (acceptable, légère imprécision sur HDR). +- **Parsing de la sortie :** `ab-av1 crf-search` émet une ligne finale du type `crf 32 VMAF 96.21 ...`. On extrait le CRF en cherchant une ligne contenant à la fois `crf` et `VMAF` et en lisant le token suivant `crf`. +- Fallback à CRF 32 si la commande échoue ou si le parsing ne trouve rien. + +**`enc_options`** est une chaîne de paramètres SVT-AV1 au format `key=value:key=value`, construite dans le `main` : + +| Flag CLI | Option SVT-AV1 | +|---|---| +| (base) | `preset=6` | +| `--animation` | `tune=0` (VQ, préférable pour l'animation) | +| (défaut) | `tune=1` (PSNR) | +| `--interlaced` | aucun paramètre SVT-AV1 (yadif géré côté FFmpeg) | + +Les métadonnées HDR (mastering display, HDR10+) sont passées **séparément** à `convert_video` via `-svtav1-params`, et non via `enc_options`. `enc_options` ne contient que les options de qualité/preset. + +### 3. Codec audio : libfdk_aac → libopus + +- Encodeur : `libopus` (doit être compilé dans FFmpeg — vérifier avec `ffmpeg -codecs | grep opus`) +- Mode VBR (`-vbr on`) +- Bitrate adaptatif : + - ≤ 2 canaux : 128k + - 6 canaux (5.1) : 320k + - 8 canaux (7.1) : 450k +- Multicanal : `-mapping_family 1` +- Workaround `5.1(side)` → `5.1` conservé +- Normalisation de volume (`volumedetect` + filtre `volume=`) inchangée + +### 4. HDR10 statique + +Les métadonnées mastering display et content-light sont passées via `-svtav1-params` : +``` +mastering-display=G(x,y)B(x,y)R(x,y)WP(x,y)L(max,min):content-light=maxcll,maxfall +``` +La logique de calcul des coordonnées chromatiques (depuis `side_data_list`) est conservée. + +### 5. HDR10+ + +- **Extraction :** `hdr10plus_parser` (binaire inclus) +- **Conteneur source :** si le fichier source est en MKV, la commande d'extraction doit omettre `-vbsf hevc_mp4toannexb` (ce bitstream filter est uniquement nécessaire pour les sources HEVC en MP4). `get_infos` détecte le conteneur via `ffprobe format_name` et adapte la commande. +- **Injection :** via `hdr10plus-json={path}` dans `-svtav1-params` (SVT-AV1 natif) + +### 6. Dolby Vision + +- `get_infos` détecte la présence d'un stream DV (entrée `DOVI` dans `side_data_list`) +- **Profile 8** (dual-layer, cas le plus fréquent) : fallback automatique vers HDR10 — la couche HDR10 est encodée normalement, l'enhancement layer DV est perdu +- **Profile 5** (RPU uniquement, sans couche HDR10 indépendante) : avertissement loggé ; la couche de base est traitée telle quelle (HDR10 si les métadonnées sont présentes dans le stream, sinon SDR) +- Dans tous les cas, un message indique : `"Dolby Vision détecté (Profile X). Encodage sans couche DV."` +- Pas d'intégration `dovi_tool` + +### 7. Entrelacement + +- `is_interlaced()` supprimée +- Nouvel argument CLI `--interlaced` (flag booléen) +- Le filtre `yadif` dans `convert_video` n'est appliqué que si `--interlaced` est passé + +### 8. Assemblage MKV simplifié + +- `create_mkv` assemble : `{file}_video.mkv` + N `{file}_audio_*.mka` + N `{file}_subtitle_*.mkv` → `NEW_{filename}.mkv` +- Le fichier de sortie est directement nommé `NEW_{filename}.mkv` (suppression du nom intermédiaire `_FINAL.mkv`) +- Nettoyage des fichiers temporaires : `{file}_video.mkv`, `{file}_audio_*.mka`, `{file}_subtitle_*.mkv` supprimés après assemblage +- `mkv_to_mp4` supprimée + +### 9. Corrections + +- Ligne 308 : `infos = get_infos(file)` décommenté +- `interlaced = False` orphelin supprimé +- `-t` / `--starttime` supprimé + +--- + +## Arguments CLI finaux + +| Argument | Description | +|---|---| +| `f_input` | Fichier source | +| `-d` / `--debug` | Logging DEBUG | +| `-s` / `--stabilise` | Stabilisation vidéo (vidstab) | +| `-a` / `--animation` | Tuning animation (tune=0) | +| `-c` / `--vhs` | Restauration VHS (hqdn3d + unsharp) | +| `--interlaced` | Forcer le désentrelacement (yadif) | + +--- + +## Flux d'exécution + +``` +get_infos → [stabilization] → cropping → volume_audio → find_crf +→ extract_subs (×N) → convert_audio (×N) → convert_video → create_mkv +``` + +`stabilization` n'est exécutée que si `--stabilise` est passé, avant le crop. + +--- + +## Dépendances + +| Outil | Usage | Changement | +|---|---|---| +| `ffmpeg` + `ffprobe` | Encodage, analyse | Inchangé (libopus requis) | +| `ab-av1` | Sélection CRF | **Nouveau** | +| `hdr10plus_parser` | Extraction HDR10+ | Inchangé | +| `mkvmerge` | Assemblage final | Inchangé | +| `libfdk_aac` | Audio AAC | **Supprimé** | +| `libopus` | Audio Opus | **Nouveau** (dans FFmpeg) | + +--- + +## Hors scope + +- Dolby Vision Profile 5 avec `dovi_tool` +- DV Profile 10 pour AV1 (expérimental, non viable) +- Interface utilisateur, tests automatisés