Files
vid_convert/docs/superpowers/specs/2026-03-22-av1-opus-design.md
2026-03-22 22:56:41 +01:00

6.1 KiB
Raw Blame History

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_*.mkvNEW_{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