web-dev-qa-db-fra.com

Comment puis-je normaliser l'audio en utilisant ffmpeg?

Je veux que le son de crête le plus fort dans un clip soit aussi fort que le permet le codec, puis que tous les autres sons soient amplifiés en conséquence.

Qu'est-ce qu'un exemple pratique pour accomplir cela en utilisant ffmpeg?

105
Jon Skarpeteig

Option 1: filtres de normalisation intégrés

Current ffmpeg a deux filtres qui peuvent être directement utilisés pour la normalisation - bien qu’ils soient déjà assez avancés, ils ne s’appliquent pas simplement pour obtenir un gain afin d’atteindre un niveau maximal. Les voici:

  • loudnorm : normalisation de la sonie selon EBU R128. Vous pouvez définir une cible de volume intégrée, une cible de plage de volume ou un pic maximal maximal. Ceci est recommandé pour la publication audio et vidéo et est utilisé par les diffuseurs du monde entier.
  • dynaudnorm : normalisation de volume «intelligent» sans découpage, qui applique la normalisation de manière dynamique aux parties fenêtrées du fichier. Cela peut modifier les caractéristiques du son, il convient donc de l’appliquer avec prudence.

En outre, le filtre volume peut être utilisé pour effectuer de simples ajustements de volume. Voir l’entrée wiki Audio Volume Manipulation pour plus d’informations.

Le filtre loudnorm peut être utilisé avec un seul passage, mais il est recommandé d'effectuer deux passages, ce qui permet une normalisation linéaire plus précise. C'est un peu difficile à automatiser. De même, si vous souhaitez une normalisation «simple» basée sur RMS ou une normalisation de crête à 0 dBFS (ou toute autre cible), lisez la suite.


Option 2: Utiliser l'outil ffmpeg-normalize

J'ai créé un programme Python pour normaliser les fichiers multimédias , disponible sur PyPi également . Vous simplement:

  • download ffmpeg (choisissez un construction statique, version 3.1 ou supérieure)
  • placez l'exécutable ffmpeg dans votre $PATH en l'ajoutant, par exemple, à /usr/local/bin ou en ajoutant son répertoire à $PATH
  • Exécuter pip install ffmpeg-normalize
  • Utilisez ffmpeg-normalize

Par exemple:

ffmpeg-normalize input.mp4 -o output.mp4 -c:a aac -b:a 192k

Ou, simplement, normalisez par lots un certain nombre de fichiers audio et écrivez-les au format WAV non compressé dans un dossier de sortie:

ffmpeg-normalize *.m4a -of /path/to/outputFolder -ext wav

L'outil prend en charge EBU R128 (valeur par défaut), RMS et Peak. Jetez un coup d'œil à ffmpeg-normalize -h pour plus d'options et examinez le fichier README pour quelques exemples.

En outre, il prend en charge le ré-encodage avec d'autres encodeurs (par exemple, AAC ou MP3) ou la fusion automatique de l'audio dans la vidéo.


Option 3: Normaliser manuellement l'audio avec ffmpeg

Dans ffmpeg, vous pouvez utiliser le filtre volume pour modifier le volume d’une piste. Assurez-vous de télécharger une version récente du programme.

Ce guide concerne la normalisation crête, ce qui signifie que la partie la plus forte du fichier reste à 0 dB au lieu de quelque chose de plus bas. Il existe également une normalisation basée sur RMS qui essaie de rendre la sonorité moyenne identique sur plusieurs fichiers. Pour ce faire, n'essayez pas de pousser le volume maximum à 0 dB, mais le volume moyen au niveau de dB souhaité (par exemple -26 dB).

Découvrez le gain à appliquer

Vous devez d’abord analyser le flux audio pour déterminer le volume maximum et voir si la normalisation serait rentable:

ffmpeg -i video.avi -af "volumedetect" -vn -sn -dn -f null /dev/null

Remplacez /dev/null par NUL sous Windows.
Les arguments -vn , -sn et -dn indiquent à ffmpeg d'ignorer les flux non audio au cours de cette analyse. Cela accélère considérablement l'analyse.

Cela produira quelque chose comme ce qui suit:

[Parsed_volumedetect_0 @ 0x7f8ba1c121a0] mean_volume: -16.0 dB
[Parsed_volumedetect_0 @ 0x7f8ba1c121a0] max_volume: -5.0 dB
[Parsed_volumedetect_0 @ 0x7f8ba1c121a0] histogram_0db: 87861

Comme vous pouvez le constater, notre volume maximal est de -5,0 dB. Nous pouvons donc appliquer un gain de 5 dB. Si vous obtenez une valeur de 0 dB, vous n'avez pas besoin de normaliser l'audio.

Appliquez le filtre de volume:

Nous appliquons maintenant le filtre volume à un fichier audio. Notez que l'application du filtre signifie que nous devrons ré-encoder le flux audio. Le codec que vous voulez pour l'audio dépend du format original, bien sûr. Voici quelques exemples:

  • Fichier audio standard: Encodez simplement le fichier avec le codeur dont vous avez besoin:

    ffmpeg -i input.wav -af "volume=5dB" output.mp3
    

    Vos options sont très larges, bien sûr.

  • Format AVI: Généralement, les fichiers audio MP3 avec vidéo sont fournis dans un conteneur AVI:

    ffmpeg -i video.avi -af "volume=5dB" -c:v copy -c:a libmp3lame -q:a 2 output.avi
    

    Ici, nous avons choisi le niveau de qualité 2. Les valeurs vont de 0 à 9 et moins signifie mieux. Consultez le guide MP3 VBR pour plus d’informations sur le réglage de la qualité. Vous pouvez également définir un débit binaire fixe avec -b:a 192k, par exemple.

  • Format MP4: Avec un conteneur MP4, vous trouverez généralement l’audio AAC. Nous pouvons utiliser l'encodeur AAC intégré de ffmpeg.

    ffmpeg -i video.mp4 -af "volume=5dB" -c:v copy -c:a aac -b:a 192k output.mp4
    

    Ici, vous pouvez également utiliser d'autres encodeurs AAC. Certains d'entre eux supportent également VBR. Voir this answer et le AAC encoding guide pour quelques astuces.

Dans les exemples ci-dessus, le flux vidéo sera copié à l'aide de -c:v copy. S'il y a des sous-titres dans votre fichier d'entrée ou plusieurs flux vidéo, utilisez l'option -map 0 avant le nom du fichier de sortie.

166
slhck

Je ne peux pas commenter le meilleur message, alors c’est ma laide bash qui me permet de le faire.

ffmpeg -i sound.mp3 -af volumedetect -f null -y nul &> original.txt
grep "max_volume" original.txt > original1.tmp
sed -i 's|: -|=|' original1.tmp
if [ $? = 0 ]
 then
 sed -i 's| |\r\n|' original.tmp
 sed -i 's| |\r\n|' original.tmp
 sed -i 's| |\r\n|' original.tmp
 sed -i 's| |\r\n|' original.tmp
 grep "max_volume" original1.tmp > original2.tmp
 sed -i 's|max_volume=||' original2.tmp
 yourscriptvar=$(cat "./original2.tmp")dB
 rm result.mp3
 ffmpeg -i sound.mp3 -af "volume=$yourscriptvar" result.mp3
 ffmpeg -i result.mp3 -af volumedetect -f null -y nul &> result.txt
fi
7

Voici un script pour normaliser les niveaux sonores des fichiers .m4a. Faites attention si les niveaux sonores sont trop faibles pour commencer. Le son final peut être meilleur si vous utilisez quelque chose comme Audacity dans ce cas.

#!/bin/bash

# Purpose: Use ffmpeg to normalize .m4a audio files to bring them up to max volume, if they at first have negative db volume. Doesn't process them if not. Keeps bitrate same as source files.
# Parameters: $1 should be the name of the directory containing input .m4a files.
#   $2 should be the output directory.

INPUTDIR=$1
OUTPUTDIR=$2

<<"COMMENT"

# For ffmpeg arguments http://superuser.com/questions/323119/how-can-i-normalize-audio-using-ffmpeg
# and
# https://kdecherf.com/blog/2012/01/14/ffmpeg-converting-m4a-files-to-mp3-with-the-same-bitrate/
ffmpeg -i test.m4a -af "volumedetect" -f null /dev/null

ffmpeg -i test.m4a -af "volumedetect" -f null /dev/null 2>&1 | grep max_volume
# output: max_volume: -10.3 dB

ffmpeg -i test.m4a -af "volumedetect" -f null /dev/null 2>&1 | grep 'max_volume\|Duration'
# Output:
#  Duration: 00:00:02.14, start: 0.000000, bitrate: 176 kb/s
# [Parsed_volumedetect_0 @ 0x7f8531e011a0] max_volume: -10.3 dB

ffmpeg -i test.m4a -af "volumedetect" -f null /dev/null 2>&1 | grep max_volume | awk -F': ' '{print $2}' | cut -d' ' -f1
# Output: -10.3

ffmpeg -i test.m4a 2>&1 | grep Audio
# output: Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 170 kb/s (default)

ffmpeg -i test.m4a 2>&1 | grep Audio | awk -F', ' '{print $5}' | cut -d' ' -f1
# output: 170

# This works, but I get a much smaller output file. The sound levels do appear normalized.
ffmpeg -i test.m4a -af "volume=10.3dB" -c:v copy -c:a aac -strict experimental output.m4a

# Operates quietly.
ffmpeg -i test.m4a -af "volume=10.3dB" -c:v copy -c:a aac -strict experimental -b:a 192k output.m4a -loglevel quiet

COMMENT

# $1 (first param) should be the name of a .m4a input file, with .m4a extension
# $2 should be name of output file, with extension
function normalizeAudioFile {
    INPUTFILE=$1
    OUTPUTFILE=$2

    DBLEVEL=`ffmpeg -i ${INPUTFILE} -af "volumedetect" -f null /dev/null 2>&1 | grep max_volume | awk -F': ' '{print $2}' | cut -d' ' -f1`

    # We're only going to increase db level if max volume has negative db level.
    # Bash doesn't do floating comparison directly
    COMPRESULT=`echo ${DBLEVEL}'<'0 | bc -l`
    if [ ${COMPRESULT} -eq 1 ]; then
        DBLEVEL=`echo "-(${DBLEVEL})" | bc -l`
        BITRATE=`ffmpeg -i ${INPUTFILE} 2>&1 | grep Audio | awk -F', ' '{print $5}' | cut -d' ' -f1`

        # echo $DBLEVEL
        # echo $BITRATE

        ffmpeg -i ${INPUTFILE} -af "volume=${DBLEVEL}dB" -c:v copy -c:a aac -strict experimental -b:a ${BITRATE}k ${OUTPUTFILE} -loglevel quiet

    else
        echo "Already at max db level:" $DBLEVEL "just copying exact file"
        cp ${INPUTFILE} ${OUTPUTFILE}
    fi
}

for inputFilePath in ${INPUTDIR}/*; do
    inputFile=$(basename $inputFilePath)
    echo "Processing input file: " $inputFile
    outputFilePath=${OUTPUTDIR}/$inputFile
    normalizeAudioFile ${inputFilePath} ${outputFilePath}
done
5
Chris Prince