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?
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?
Respostas:
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 volume
filtro 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 loudnorm
filtro 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.
ffmpeg-normalize
ferramentaCriei um programa Python para normalizar arquivos de mídia , disponíveis também no PyPi . Você simplesmente:
ffmpeg
executável no seu $PATH
adicionando-o, por exemplo /usr/local/bin
, ou adicionando seu diretório a$PATH
pip install ffmpeg-normalize
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 -h
mais 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.
ffmpeg
No ffmpeg, você pode usar o volume
filtro 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).
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/null
por NUL
no Windows.
A -vn
, -sn
, e -dn
argumentos 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.
Agora aplicamos o volume
filtro 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 0
antes do nome do arquivo de saída.
ffmpeg-normalize
ferramenta faz quando você especifica um nível de 0 dB e normalização de pico.
loudnorm
filtro (ou outro):ffmpeg -i input.wav -filter:a loudnorm output.wav
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
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
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