Jak mogę znormalizować dźwięk za pomocą ffmpeg?

119

Chcę, aby najgłośniejszy dźwięk szczytowy w klipie filmowym był tak głośny, na jaki pozwala kodek, a następnie odpowiednio wzmacniał każdy inny dźwięk.

Jaki jest praktyczny przykład, aby to osiągnąć za pomocą ffmpeg?

Jon Skarpeteig
źródło
1
Chcesz, aby dźwięk został „znormalizowany”. Znalazłem ten wątek i jest tam wiele dobrych informacji. Mam nadzieję, że to pomoże!
bobsbarricades

Odpowiedzi:

189

Opcja 1: Wbudowane filtry normalizacyjne

Obecny ffmpeg ma dwa filtry, których można bezpośrednio użyć do normalizacji - chociaż są one już dość zaawansowane, więc nie stosują tylko wzmocnienia, aby osiągnąć poziom szczytowy. Tutaj są:

  • loudnorm: normalizacja głośności zgodnie z EBU R128. Możesz ustawić zintegrowany docelowy poziom głośności, docelowy zakres głośności lub maksymalny prawdziwy szczyt. Jest to zalecane do publikowania audio i wideo i jest wykorzystywane przez nadawców na całym świecie.
  • dynaudnorm: „Inteligentna” normalizacja głośności bez obcinania, która dynamicznie stosuje normalizację do okienkowanych części pliku. Może to zmienić charakterystykę dźwięku, dlatego należy zachować ostrożność.

Ponadto, volumefiltr może być używany do wykonywania prostych regulacji głośności. Zobacz wpis wiki Manipulacja głośnością audio, aby uzyskać więcej.

loudnormFiltr może być stosowany z jednym przejściem, ale zaleca się, aby wykonać dwa cykle, które umożliwia bardziej precyzyjne normalizację liniowej. Jest to trochę trudne do zautomatyzowania. Ponadto, jeśli chcesz „prostej” opartej na RMS lub szczytowej normalizacji do 0 dBFS (lub dowolnego innego celu), czytaj dalej.


Opcja 2: użyj ffmpeg-normalizenarzędzia

Stworzyłem program Python do normalizacji plików multimedialnych , dostępny również na PyPi . Po prostu:

  • pobierz ffmpeg (wybierz wersję statyczną , wersja 3.1 lub wyższa)
  • umieść ffmpegplik wykonywalny w swoim pliku, $PATHdodając go na przykład /usr/local/binlub dodając do niego katalog$PATH
  • Biegać pip install ffmpeg-normalize
  • Posługiwać się ffmpeg-normalize

Na przykład:

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

Lub, aby zwyczajnie wsadowo znormalizować kilka plików audio i zapisać je jako nieskompresowany plik WAV do folderu wyjściowego:

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

Narzędzie obsługuje EBU R128 (domyślnie), RMS i peak. Sprawdź ffmpeg-normalize -hwięcej opcji i sprawdź README, aby zobaczyć kilka przykładów.

Ponadto obsługuje ponowne kodowanie za pomocą innych koderów (np. AAC lub MP3) lub automatyczne scalanie audio z powrotem w wideo.


Opcja 3: Ręczna normalizacja dźwięku za pomocą ffmpeg

W ffmpeg możesz użyć volumefiltra, aby zmienić głośność ścieżki. Upewnij się, że pobierasz najnowszą wersję programu.

Ten przewodnik służy do normalizacji szczytów , co oznacza, że ​​najgłośniejsza część pliku będzie ustawiona na 0 dB zamiast czegoś niższego. Istnieje również normalizacja oparta na RMS, która stara się, aby średnia głośność była taka sama dla wielu plików. Aby to zrobić, nie próbuj zwiększać maksymalnej głośności do 0 dB, ale średnią głośność do wybranego poziomu dB (np. -26 dB).

Dowiedz się, jaki zysk zastosować

Najpierw musisz przeanalizować strumień audio pod kątem maksymalnej głośności, aby zobaczyć, czy normalizacja się w ogóle opłaciłaby:

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

Wymień /dev/nullsię NULw systemie Windows.
Argumenty -vn, -sni -dninstruują ffmpeg, aby ignorował strumienie inne niż audio podczas tej analizy. To drastycznie przyspiesza analizę.

Spowoduje to wyświetlenie czegoś takiego:

[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

Jak widać, nasza maksymalna głośność wynosi -5,0 dB, więc możemy zastosować wzmocnienie 5 dB. Jeśli uzyskasz wartość 0 dB, nie musisz normalizować dźwięku.

Zastosuj filtr głośności:

Teraz stosujemy volumefiltr do pliku audio. Pamiętaj, że zastosowanie filtra oznacza, że ​​będziemy musieli ponownie zakodować strumień audio. Wybór kodeku audio zależy oczywiście od jego oryginalnego formatu. Oto kilka przykładów:

  • Zwykły plik audio: wystarczy zakodować plik dowolnym koderem, którego potrzebujesz:

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

    Twoje opcje są oczywiście bardzo szerokie.

  • Format AVI: zazwyczaj w formacie AVI jest plik audio MP3 z wideo:

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

    Tutaj wybraliśmy poziom jakości 2. Zakres wartości od 0–9 i niższy oznacza lepszy. Sprawdź MP3 VBR instrukcji , aby uzyskać więcej informacji na temat ustawiania jakości. Możesz także ustawić na przykład stały bitrate -b:a 192kza pomocą.

  • Format MP4: W kontenerze MP4 zwykle znajdziesz dźwięk AAC. Możemy użyć wbudowanego kodera AAC ffmpeg.

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

    Tutaj możesz także użyć innych koderów AAC. Niektóre z nich obsługują również VBR. Zobacz tę odpowiedź i przewodnik po kodowaniu AAC, aby uzyskać kilka wskazówek.

W powyższych przykładach strumień wideo zostanie skopiowany za pomocą -c:v copy. Jeśli w pliku wejściowym są napisy lub wiele strumieni wideo, użyj opcji -map 0przed nazwą pliku wyjściowego.

slhck
źródło
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Journeyman Geek
7
To jest dar, który wciąż daje. 6 lat później wciąż jest aktualizowana i utrzymywana. Dobra robota!
Jon Skarpeteig,
Czy w opcji 3 unika się obcinania, jeśli ustawię nowy poziom głośności, więc maksymalna objętość wynosi zero? tzn. używając przeciwnej wartości początkowej podanej przez max_volume
rraallvv
@rraallvv Tak, powinno. To samo robi ffmpeg-normalizenarzędzie, gdy określisz poziom 0 dB i szczytową normalizację.
slhck
7

Nie mogę komentować najlepszej wiadomości, więc jest to mój brzydki bash oparty na tym, aby to zrobić

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
Sebastien Willemijns
źródło
5

Oto skrypt normalizujący poziomy dźwięku plików .m4a. Uważaj, czy poziomy głośności są zbyt ciche, aby zacząć. Ostateczny dźwięk może być lepszy, jeśli w takim przypadku użyjesz czegoś takiego jak Audacity.

#!/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
Chris Prince
źródło
-2

ffmpeg -i image.jpg -i "input.mp3" -acodec copy tmp.avi

mencoder -ovc copy -oac copy tmp.avi -of rawaudio -af volnorm = 1 -oac mp3lame -lameopts cbr: preset = 192 -sate 48000 -o "output.mp3"

rm -f tmp.avi

Wycie Maquelana
źródło
2
Porównując to z innymi odpowiedziami tutaj, mam nadzieję, że jest jasne, że w Twoim poście brakuje informacji kontekstowych i objaśniających, które mogłyby być przydatne. Co to jest „mencoder” i jaką rolę odgrywa w odpowiedzi na pytanie?
music2myear
2
Czy możesz edytować swoją odpowiedź, aby wyjaśnić, dlaczego ten kod odpowiada na pytanie? Odpowiedzi zawierające tylko kod są odradzane , ponieważ nie uczą rozwiązania.
DavidPostill