Ajout de la spec de migration AV1-SVT + Opus
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
144
docs/superpowers/specs/2026-03-22-av1-opus-design.md
Normal file
144
docs/superpowers/specs/2026-03-22-av1-opus-design.md
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user