Mes scripts FFMPEG

De manière commune, je préfixe l’exécution de FFMPEG avec

-y -hide_banner -loglevel error -stats -err_detect ignore_err

De nombreux codes ont été créés pour Unix, à adapter pour Windows.

Convertir une musique en mono

ffmpeg -i input.mp3 -ac 1 -b:a 64k output.mp3

Assombrir une vidéo

ffmpeg -i input.mp4 -crf 20 -vf eq=gamma=0.95:contrast=1.1 -c:v libx264 -c:a copy output.mp4

Tester le niveau sonore

ffmpeg -i input.mp4 -c copy -t 00:10:00.0 tmp.mp4
ffmpeg -i tmp.mp4 -filter_complex "showwavespic,scale=128:128,crop=128:64:0:32" -frames:v 1 tmp.jpg && rm tmp.mp4
noirs=$(convert tmp.jpg -threshold 1% -format %c histogram:info:- | grep black | sed -r 's#[\ ]*##' | cut -c1-4) && rm tmp.jpg
[ "$noirs" -ge 5500 ] && another_script_to_normalize.sh input.mp4

Explications :

  1. On teste sur un extrait de 10 minutes
  2. On convertit l’extrait en image représentant le spectre sonore
  3. Avec ImageMagick, on va compter le nombre de pixels noirs (sur 8192)
  4. S’il est supérieur à 5500, on normalise l’audio

Normaliser l’audio d’une vidéo (nécessite ffmpeg-normalize)

. ~/.venv/bin/activate
ffmpeg-normalize input.mp4 --verbose --normalization-type rms --target-level -15 --force --progress --output-folder "./normalized"
ffmpeg -i input.mp4 -i input.mkv -c:v copy -map 0:v:0 -map 1:a:0 normalized.mp4

Explications :

  1. On active l’environnement de Python
  2. On normalise l’audio de la vidéo, qui génère un fichier MKV
  3. On remplace l’audio d’origine par l’audio normalisé

Supprimer les bandes noires d’une vidéo

ffmpeg -i input.mp4 -vf $(ffmpeg -ss 30 -i "$1" -t 5:00 -vsync vfr -vf fps=1/2,cropdetect -f null - 2>&1 | awk '/crop/ { print $NF }' | tr ' ' '\n' | sort | uniq -c | sort -n | tail -1 | awk '{ print $NF }') -ss 0 -t 0:01 -threads 5 -preset ultrafast -strict -2 temp.mp4
ffmpeg -i input.mp4 -i temp.mp4 -filter_complex "[0:v][1:v]hstack=inputs=2[v];[0:a][1:a]amerge=inputs=2[a]" -map "[v]" -map "[a]" -ac 2 comp.mp4 && rm temp.mp4

if [ ! -s comp.mp4 ]
then
  ffmpeg  -i input.mp4 -vf $(ffmpeg -ss 30 -i input.mp4 -t 5:00 -vsync vfr -vf fps=1/2,cropdetect -f null - 2>&1 | awk '/crop/ { print $NF }' | tr ' ' '\n' | sort | uniq -c | sort -n | tail -1 | awk '{ print $NF }') -pix_fmt yuv420p -movflags +faststart -threads 5 -preset ultrafast -strict -2 temp.mp4
  ffmpeg -i temp.mp4 -threads 5 input.mp4  rm temp.mp4
fi
rm comp.mp4

Explications :

  1. On extrait les 5 premières minutes de vidéo sans les bandes noires s’il y en a
  2. On tente une concaténation de la vidéo d’origine avec l’extrait
  3. Si la concaténation est impossible (absence du fichier comp.mp4), on supprime les bandes de toute la vidéo, en 2 passes (plus rapide)

Pixels carrés

ffmpeg -i input.mp4 -vf scale=iw:ceil((ih/sar)/2)*2,setsar=1 -crf 20 -c:v libx264 -c:a copy output.mp4

Explications :

  1. on utilise la valeur sar, qui correspond au ratio largeur/hauteur des pixels pour recalculer la hauteur et obtenir des pixels carrés.

Vidéo 1280

ffmpeg -i input.mp4 -vf scale=1280:-2 -crf 20 -c:v libx264 -c:a copy output.mp4

Explications :

  1. le scale=XXX:-2 définit la hauteur proportionnellement, mais toujours paire (les vidéos n’acceptent pas les dimensions impaires)

Remise à l’échelle

Exemple avec 16/9

ffmpeg -i input.mp4 -vf scale=iw:ceil(iw*(1/(16/9))/2)*2,setdar=16/9 -c:v libx264 -c:a copy output.mp4

Explications :

  1. Ici on force la hauteur qui est le produit de la largeur par l’inverse de la proportion (pour du 16/9, on aura iw*9/16), tout en s’assurant que le résultat soit pair
  2. le setdar force le rendu final avec les proportions souhaitées, ce qui aura pour conséquence d’avoir les pixels carrés