6.1 KiB
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.jsonsi disponible, afin d'utiliser un modèle VMAF calibré HDR. Si le modèle est absent,ab-av1utilise 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 typecrf 32 VMAF 96.21 .... On extrait le CRF en cherchant une ligne contenant à la foiscrfetVMAFet en lisant le token suivantcrf. - 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=3:tune=0 (VQ, qualité perçue — défaut pour tous les contenus) |
--animation |
aucun changement de tune (VQ reste optimal) |
--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 avecffmpeg -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.1conservé - Normalisation de volume (
volumedetect+ filtrevolume=) 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_infosdétecte le conteneur viaffprobe format_nameet adapte la commande. - Injection : via
hdr10plus-json={path}dans-svtav1-params(SVT-AV1 natif)
6. Dolby Vision
get_infosdétecte la présence d'un stream DV (entréeDOVIdansside_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
yadifdansconvert_videon'est appliqué que si--interlacedest passé
8. Assemblage MKV simplifié
create_mkvassemble :{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_*.mkvsupprimés après assemblage mkv_to_mp4supprimée
9. Corrections
- Ligne 308 :
infos = get_infos(file)décommenté interlaced = Falseorphelin supprimé-t/--starttimesupprimé
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