Como normalizar o áudio usando o ffmpeg?

119

Eu quero que o som mais alto de um clipe de filme seja o mais alto que o codec permita, e então todos os outros sons sejam amplificados de acordo.

O que é um exemplo prático para fazer isso usando o ffmpeg?

Jon Skarpeteig
fonte
1
Você está procurando ter o áudio 'normalizado'. Eu encontrei este tópico e há muitas informações boas lá. Espero que ajude!
Bobsbarricades

Respostas:

190

Opção 1: Filtros de normalização incorporados

O ffmpeg atual possui dois filtros que podem ser usados ​​diretamente para normalização - embora já sejam bastante avançados, portanto, eles não aplicam simplesmente o ganho para atingir um nível de pico. Aqui estão eles:

  • loudnorm: normalização do volume de acordo com EBU R128. Você pode definir um alvo de volume integrado, um alvo de faixa de volume ou pico máximo máximo. Isso é recomendado para a publicação de áudio e vídeo e é usado por emissoras em todo o mundo.
  • dynaudnorm: Normalização de volume “inteligente” sem recorte, que aplica a normalização dinamicamente sobre partes da janela do arquivo. Isso pode alterar as características do som, por isso deve ser aplicado com cautela.

Além disso, o volumefiltro pode ser usado para realizar ajustes simples de volume. Consulte a entrada wiki de Manipulação de volume de áudio para obter mais informações.

O loudnormfiltro pode ser usado com uma passagem, mas é recomendável executar duas passagens, o que permite uma normalização linear mais precisa. Isso é um pouco difícil de automatizar. Além disso, se você deseja uma normalização “simples” baseada em RMS ou em pico para 0 dBFS (ou qualquer outro destino), continue lendo.


Opção 2: use a ffmpeg-normalizeferramenta

Criei um programa Python para normalizar arquivos de mídia , disponíveis também no PyPi . Você simplesmente:

  • download ffmpeg (escolha uma compilação estática , versão 3.1 ou superior)
  • coloque o ffmpegexecutável no seu $PATHadicionando-o, por exemplo /usr/local/bin, ou adicionando seu diretório a$PATH
  • Corre pip install ffmpeg-normalize
  • Usar ffmpeg-normalize

Por exemplo:

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

Ou, para normalizar em lote vários arquivos de áudio e gravá-los como WAV descompactado em uma pasta de saída:

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

A ferramenta suporta EBU R128 (padrão), RMS e pico. Dê uma olhada em ffmpeg-normalize -hmais opções e verifique o README para alguns exemplos.

Além disso, ele suporta a recodificação com outros codificadores (por exemplo, AAC ou MP3) ou a fusão automática do áudio de volta ao vídeo.


Opção 3: normalizando manualmente o áudio com ffmpeg

No ffmpeg, você pode usar o volumefiltro para alterar o volume de uma faixa. Certifique-se de baixar uma versão recente do programa.

Este guia é para normalização de pico , o que significa que fará com que a parte mais alta do arquivo fique em 0 dB em vez de algo mais baixo. Há também uma normalização baseada em RMS, que tenta tornar a intensidade média a mesma em vários arquivos. Para fazer isso, não tente empurrar o volume máximo para 0 dB, mas o volume médio para o nível de dB de escolha (por exemplo, -26 dB).

Descubra o ganho a aplicar

Primeiro, você precisa analisar o fluxo de áudio para obter o volume máximo para ver se a normalização valeria a pena:

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

Substitua /dev/nullpor NULno Windows.
A -vn, -sn, e -dnargumentos instruir ffmpeg para ignorar fluxos não são de áudio durante esta análise. Isso acelera drasticamente a análise.

Isso produzirá algo como o seguinte:

[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

Como você pode ver, nosso volume máximo é de -5,0 dB, para que possamos aplicar um ganho de 5 dB. Se você obtiver um valor de 0 dB, não precisará normalizar o áudio.

Aplique o filtro de volume:

Agora aplicamos o volumefiltro a um arquivo de áudio. Observe que a aplicação do filtro significa que teremos que recodificar o fluxo de áudio. Qual codec você deseja para o áudio depende do formato original, é claro. aqui estão alguns exemplos:

  • Arquivo de áudio simples: basta codificar o arquivo com o codificador que você precisar:

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

    Suas opções são muito amplas, é claro.

  • Formato AVI: Geralmente, há áudio MP3 com vídeo que vem em um contêiner AVI:

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

    Aqui, escolhemos o nível de qualidade 2. Os valores variam de 0 a 9 e inferior significa melhor. Consulte o guia MP3 VBR para obter mais informações sobre como definir a qualidade. Você também pode definir uma taxa de bits fixa com -b:a 192k, por exemplo.

  • Formato MP4: com um contêiner MP4, você normalmente encontrará áudio AAC. Podemos usar o codificador AAC incorporado do ffmpeg.

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

    Aqui você também pode usar outros codificadores AAC. Alguns deles também suportam VBR. Veja esta resposta e o guia de codificação AAC para obter algumas dicas.

Nos exemplos acima, o fluxo de vídeo será copiado usando -c:v copy. Se houver legendas no arquivo de entrada ou vários fluxos de vídeo, use a opção -map 0antes do nome do arquivo de saída.

slhck
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Journeyman Geek
7
Este é o presente que continua dando. Seis anos depois, ele ainda está sendo atualizado e mantido. Bem feito!
Jon Skarpeteig
A opção 3 evita o recorte se eu definir o novo volume para que max_volume seja zero? ou seja, usando o valor oposto inicial dado por max_volume
rraallvv
@rraallvv Sim, deveria. É também o que a ffmpeg-normalizeferramenta faz quando você especifica um nível de 0 dB e normalização de pico.
slhck
Para usar o loudnormfiltro (ou outro):ffmpeg -i input.wav -filter:a loudnorm output.wav
Joschua
7

Eu não posso comentar sobre a melhor mensagem, então essa é a minha feia festança com base nela para fazer isso

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
fonte
5

Aqui está um script para normalizar os níveis de som dos arquivos .m4a. Cuidado se os níveis de som estiverem muito baixos para começar. O som final pode ser melhor se você usar algo como o Audacity nesse caso.

#!/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
fonte
-2

ffmpeg -i image.jpg -i "input.mp3" -acodec copia 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

Uivo de Maquelan
fonte
2
Comparando isso com as outras respostas aqui, espero que fique claro que sua postagem não possui informações contextuais e explicativas que a tornariam útil. O que é "mencoder" e qual o seu papel na resposta à pergunta?
music2myear 21/03
2
Você poderia editar sua resposta para dar uma explicação de por que esse código responde à pergunta? As respostas somente de código são desencorajadas , porque não ensinam a solução.
DavidPostill