Bagaimana saya bisa menormalkan audio menggunakan ffmpeg?

99

Saya ingin suara puncak paling keras dalam klip video sekencang yang diizinkan oleh codec, lalu minta setiap suara lainnya diperkuat.

Apa contoh praktis untuk mencapai ini menggunakan ffmpeg?

Jon Skarpeteig
sumber
1
Anda ingin audio dinormalisasi. saya menemukan utas ini dan ada banyak informasi bagus di sana. Semoga ini bisa membantu!
bobsbarricades

Jawaban:

153

Opsi 1: Filter Normalisasi Internal

Ffmpeg saat ini memiliki dua filter yang dapat langsung digunakan untuk normalisasi - meskipun mereka sudah cukup maju, sehingga mereka tidak hanya menerapkan penguatan untuk mencapai level puncak. Di sini mereka:

  • loudnorm: normalisasi kenyaringan menurut EBU R128. Anda dapat menetapkan target kenyaringan terintegrasi, target rentang kenyaringan, atau puncak sejati maksimum. Ini direkomendasikan untuk mempublikasikan audio dan video dan digunakan oleh penyiar di seluruh dunia.
  • dynaudnorm: Normalisasi kenyaringan "cerdas" tanpa kliping, yang menerapkan normalisasi secara dinamis pada bagian-bagian file yang berjendela. Ini dapat mengubah karakteristik suara, sehingga harus diterapkan dengan hati-hati.

Juga volume filter dapat digunakan untuk melakukan penyesuaian volume sederhana. Lihat Manipulasi Volume Audio entri wiki untuk lebih.

Itu loudnorm filter dapat digunakan dengan satu lintasan, tetapi direkomendasikan untuk melakukan dua lintasan, yang memungkinkan normalisasi linier yang lebih akurat. Ini agak sulit untuk diotomatisasi. Juga, jika Anda menginginkan "sederhana" berbasis RMS atau normalisasi puncak menjadi 0 dBFS (atau target lainnya), baca terus.


Opsi 2: Gunakan ffmpeg-normalize alat

saya menciptakan program Python untuk menormalkan file media , tersedia di PyPi juga . Anda hanya:

  • unduh ffmpeg (Pilih membangun statis , versi 3.1 atau lebih tinggi)
  • menempatkan ffmpeg dieksekusi di $PATH dengan menambahkannya, misalnya, /usr/local/bin, atau menambahkan direktori ke $PATH
  • Menjalankan pip install ffmpeg-normalize
  • Menggunakan ffmpeg-normalize

Sebagai contoh:

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

Atau, untuk sekadar menormalisasi sejumlah file audio dan menuliskannya sebagai WAV yang tidak dikompresi ke folder output:

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

Alat ini mendukung EBU R128 (default), RMS dan puncak. Lihatlah ffmpeg-normalize -h untuk opsi lainnya dan periksa Baca aku untuk beberapa contoh.

Selain itu, ini mendukung pengodean ulang dengan enkode lain (mis., AAC atau MP3), atau penggabungan otomatis audio kembali ke video.


Opsi 3: Normalisasi audio dengan ffmpeg

Dalam ffmpeg Anda dapat menggunakan volume filter untuk mengubah volume trek. Pastikan Anda unduh versi terbaru dari program ini.

Panduan ini untuk puncak normalisasi, yang berarti bahwa itu akan membuat bagian paling keras dalam file duduk pada 0 dB bukannya sesuatu yang lebih rendah. Ada juga normalisasi berbasis RMS yang mencoba membuat rata-rata kenyaringan yang sama di beberapa file. Untuk melakukannya, jangan coba mendorong volume maksimum ke 0 dB, tetapi volume rata-rata ke tingkat pilihan dB (mis. -26 dB).

Cari tahu keuntungan untuk diterapkan

Pertama, Anda perlu menganalisis aliran audio untuk volume maksimum untuk melihat apakah normalisasi akan membuahkan hasil:

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

Menggantikan /dev/null dengan NUL di Windows.
Itu -vn, -sn, dan -dn argumen memerintahkan ffmpeg untuk mengabaikan aliran non-audio selama analisis ini. Ini secara drastis mempercepat analisis.

Ini akan menampilkan sesuatu seperti berikut:

[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

Seperti yang Anda lihat, volume maksimum kami adalah -5,0 dB, jadi kami dapat menerapkan kenaikan 5 dB. Jika Anda mendapatkan nilai 0 dB, maka Anda tidak perlu menormalkan audio.

Terapkan filter volume:

Sekarang kami menerapkan volume filter ke file audio. Perhatikan bahwa menerapkan filter berarti kita harus menyandikan ulang aliran audio. Codec apa yang Anda inginkan untuk audio tergantung pada format aslinya, tentu saja. Berikut ini beberapa contohnya:

  • File audio biasa: Cukup enkode file dengan encoder apa pun yang Anda butuhkan:

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

    Pilihan Anda sangat luas, tentu saja.

  • Format AVI: Biasanya ada audio MP3 dengan video yang datang dalam wadah AVI:

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

    Di sini kami memilih tingkat kualitas 2. Nilai berkisar 0-9 dan lebih rendah berarti lebih baik. Periksalah Panduan VBR MP3 untuk info lebih lanjut tentang pengaturan kualitas. Anda juga dapat mengatur bitrate tetap dengan -b:a 192k, sebagai contoh.

  • Format mp4: Dengan wadah MP4, Anda biasanya akan menemukan audio AAC. Kita dapat menggunakan encoder AAC ffmpeg.

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

    Di sini Anda juga dapat menggunakan enkode AAC lainnya. Beberapa dari mereka juga mendukung VBR. Lihat jawaban ini dan Panduan pengkodean AAC untuk beberapa tips.

Dalam contoh di atas, aliran video akan disalin menggunakan -c:v copy. Jika ada subtitle dalam file input Anda, atau beberapa stream video, gunakan opsi -map 0 sebelum nama file keluaran.

slhck
sumber
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Journeyman Geek
4
Ini adalah hadiah yang terus memberi. 6 tahun kemudian, dan masih diperbarui dan dipelihara. Sudah selesai dilakukan dengan baik!
Jon Skarpeteig
@ Terima kasih, terima kasih banyak!
slhck
Apakah opsi 3 menghindari kliping jika saya mengatur volume baru sehingga max_volume nol? yaitu menggunakan nilai kebalikan yang diberikan oleh max_volume
rraallvv
@rraallvv Ya, seharusnya. Itu juga apa adanya ffmpeg-normalize alat tidak, ketika Anda menentukan tingkat 0 dB dan normalisasi puncak.
slhck
7

Saya tidak bisa mengomentari pesan terbaik sehingga itu adalah bash jelek saya berdasarkan itu untuk melakukan itu

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

Berikut ini skrip untuk menormalkan tingkat suara file .m4a. Hati-hati jika tingkat suaranya terlalu sunyi untuk memulai. Suara terakhir bisa lebih baik jika Anda menggunakan sesuatu seperti Audacity dalam kasus itu.

#!/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
sumber