TL;DR: Ein Beispiel für Loudnorm 2pass in einer einzigen Zeile unter Verwendung von ffpmpeg (ffmpeg-normalize ist ein einzelner Thread/Prozess und ich kann keine anderen ffmpeg-Optionen damit kombinieren)
Es gibt nicht wirklich viele Beispiele zu Loudnorm, da es relativ neu für ffmpeg ist. Ich benutze ffmpeg seit ungefähr 10 Jahren. Ich bin jedoch neu für Loudnorm
Ich habe gelesen:
http://k.ylo.ph/2016/04/04/loudnorm.html
Wie kann ich Audio mit ffmpeg normalisieren?
die hilfreich sind. Ich versuche jedoch, mehrere ffmpeg-Einträge in einem zusammenzufassen. Die Verwendung der ffmpeg-normalize-Bibliothek (der Python-Bibliothek) beschränkt Sie ebenfalls auf einen einzigen Thread/Prozess. was langsam ist
für 2 Durchgänge von ffmpeg x264 können Sie einfach Folgendes tun:
ffmpeg -y -i $FILE -c:v libx264 -b:v 4000k -pass 1 -c:a aac -b:a 256k -f mkv /dev/null && \
ffmpeg -i $FILE -c:v libx264 -b:v 4000k -pass 2 -c:a aac -b:a 256k $FILE.mkv
scheint allerdings für Loudnorm nicht zu existieren. Ich sehe keine Möglichkeit, es mit einem einzigen und zwei Durchgängen zu machen?
derzeit kodiere ich das Video, dann normalisiere ich das Audio und entferne schließlich Metadaten und Kapiteldaten aus den Dateien, falls diese vorhanden sind (unabhängig davon, ob sie vorhanden sind oder nicht).
Dadurch werden 3 Wegwerfdateien erstellt (einschließlich des Originals)
Die Möglichkeit, Loudnorm in einer einzigen Zeile auszuführen, würde mir dabei helfen, andere Dinge hinzuzufügen. Ist es außerdem möglich, einen 2-Pass von x264 und einen 2-Pass von Loudnorm gleichzeitig auszuführen? Das heißt, die beiden werden verarbeitet und dann im zweiten Pass kombiniert.
Wenn möglich hätte ich gerne Beispiele dafür und keine Links zu Dingen. Ich kann selbst Links googeln und habe das seit mehreren Wochen gemacht. Danke
Antwort1
Es gibt keine Möglichkeit, einen Zwei-Durchgang-Loudnorm-Filter automatisch mit nur ffmpeg auszuführen, aber Sie können denffmpeg-normalize
Programm, das das für Sie erledigt. Ich weiß, Sie haben es erwähnt, aber wenn Sie gleichzeitig Videos kodieren möchten – insbesondere mit zwei Durchgängen –, müssen Sie jedoch mit einer Zwischendatei arbeiten, und zwar:
- Erster Lauf:
ffmpeg-normalize
auf dem Originalvideo, Kopieren des Original-Videostreams. - Zweiter Durchlauf: x264-Kodierung (multithreaded) der normalisierten Audiodatei oder der Videostreams der Originaldatei.
Was Sie erreichen möchten, lässt sich mit ffmpeg allein nicht erreichen. Sie müssen Ihre eigene Lösung programmieren, insbesondere wenn Sie mehrere Dateien parallel verarbeiten möchten. Dies würde den Prozess sicherlich beschleunigen, selbst wenn ein einzelner ffmpeg-Lauf nur einen Thread verwendet.
Als Ausgangspunkt gibt es auch eineeinfacheres Ruby-Skriptim FFmpeg-Repository. Es führt zwei Loudnorm-Durchläufe durch und liest die Statistiken des ersten Durchlaufs. Sie können es möglicherweise ändern, um zusätzlich die zweistufige x264-Kodierung mit Multithreading auszuführen, d. h., den ersten x264-Durchlauf im ersten Durchlauf und den zweiten im zweiten Durchlauf auszuführen:
Erster Pass:
ffmpeg -y -i $FILE -c:v libx264 -b:v 4000k -pass 1 -filter:a loudnorm=print_format=json -f mkv /dev/null
Lesen Sie die JSON-Statistiken aus der loudnorm
Ausgabe (z. B. mit dem JSON-Parser von Python oder einem anderen Tool wie grep
oder awk
) und führen Sie dann den zweiten Durchgang aus:
ffmpeg -i $FILE -c:v libx264 -b:v 4000k -pass 2 -filter:a loudnorm=linear=true:measured_I=$input_i:measured_LRA=$input_lra:measured_tp=$input_tp:measured_thresh=$input_thresh -c:a aac -b:a 256k $FILE.mkv
Wobei $input_i
, $input_lra
, $input_tp
, $input_thresh
die aus dem ersten Durchgang gelesenen Werte sind.
Antwort2
Es ist kein weiteres Programm erforderlich. Dies KANN tatsächlich allein mit ffmpeg erledigt werden. Ich habe tatsächlich eine Bat-Datei erstellt, die dies erledigt.
cls
echo off
ffmpeg -i %1 -filter_complex "[0:a]loudnorm=I=-16:TP=-1.5:LRA=11:print_format=summary" -f null x 2>%1.txt
@for /f "tokens=3" %%a in ('findstr /C:"Input Integrated" %1.txt') do (set II=%%a)
echo %II% is the Input Integrated
@for /f "tokens=4" %%a in ('findstr /C:"Input True Peak" %1.txt') do (set ITP=%%a)
echo %ITP% is the Input True Peak
@for /f "tokens=3" %%a in ('findstr /C:"Input LRA" %1.txt') do (set ILRA=%%a)
echo %ILRA% is the Input LRA
@for /f "tokens=3" %%a in ('findstr /C:"Input Threshold" %1.txt') do (set IT=%%a)
echo %IT% is the Input Threshold
@for /f "tokens=3" %%a in ('findstr /C:"Output Integrated" %1.txt') do (set OI=%%a)
echo %OI% is the Output Integrated
@for /f "tokens=4" %%a in ('findstr /C:"Output True Peak" %1.txt') do (set OTP=%%a)
echo %OTP% is the Output True Peak
@for /f "tokens=3" %%a in ('findstr /C:"Output LRA" %1.txt') do (set OLRA=%%a)
echo %OLRA% is the Output LRA
@for /f "tokens=3" %%a in ('findstr /C:"Output Threshold" %1.txt') do (set OT=%%a)
echo %OT% is the Output Threshold
@for /f "tokens=3" %%a in ('findstr /C:"Target Offset" %1.txt') do (set TO=%%a)
echo %TO% is the Target Offset
ffmpeg -i %1 -af loudnorm=linear=true:I=-16:LRA=11:tp=-1.5:measured_I=%II%:measured_LRA=%ILRA%:measured_tp=%ITP%:measured_thresh=%IT%:offset=%TO%:print_format=summary loudnorm.wav
Dabei wird zunächst das Audio analysiert und die Ergebnisse in einer Textdatei gespeichert. Anschließend werden die Ergebnisse aus der Textdatei gelesen und als Variablen für jedes erforderliche Messfeld gespeichert. Sie müssen lediglich I= und TP= in der Datei nach Ihren Wünschen anpassen.
Antwort3
AbpetermgVorschlag, dies ist das Äquivalent für *nix-Benutzer:
ffmpeg -i $input -filter:a loudnorm=print_format=json -f null /dev/null 2>&1 >/dev/null | sed -n '/{/,/}/p' > /tmp/info
ii=`grep \"input_i\" /tmp/info | cut -d: -f2 | tr -cd [:digit:].-`
itp=`grep \"input_tp\" /tmp/info | cut -d: -f2 | tr -cd [:digit:].-`
ilra=`grep \"input_lra\" /tmp/info | cut -d: -f2 | tr -cd [:digit:].-`
it=`grep \"input_thresh\" /tmp/info | cut -d: -f2 | tr -cd [:digit:].-`
to=`grep \"target_offset\" /tmp/info | cut -d: -f2 | tr -cd [:digit:].-`
ffmpeg -i $input -af loudnorm=linear=true:I=-16:LRA=11:tp=-1.5:measured_I=$ii:measured_LRA=$ilra:measured_tp=$itp:measured_thresh=$it:offset=$to:print_format=summary $output
Ersetzen Sie $input und $output durch Ihre Ein- und Ausgabedateien.
Der ersteffmpegBefehl erzeugt eine ausführliche Ausgabe mit einem endgültigen JSON-Objekt, das durch densedBefehl in der Pipe und in einer temporären Datei gespeichert. Jeder der fünf folgenden Befehle lädt in eine Variable einen relevanten Parameter, der an den zweiten Befehl weitergegeben wird.ffmpegDie Filterung erfolgt in drei Schritten einer Pipe: Zuerst wird die Zeile ausgewählt, die den relevanten Parameter enthält (grep), anschließend wird der Wert durch den Namen getrennt (schneiden), und schließlich wird nur der numerische Teil aussortiert (tr). Der Vorgang ist nicht 100 % zuverlässig, da er vom Ausgabeformat des ffmpeg-Befehls abhängt.
Antwort4
weitere Bash-Skripte für den ffmpeg-Loudnorm-Filter
#! /usr/bin/env bash
# ffmpeg-loudnorm-analyze.sh
# analyze loudness of audio streams
# write result to stdout in json format
# example output: see end of script
# TODO verify ffmpeg output format: Parsed_loudnorm_([0-9]+)
set -e
set -u
input_file="$1"
shift
# extra args. example: -map 0:a:0 # process only the first audio stream
extra_args=("$@")
# https://ffmpeg.org/ffmpeg-filters.html#loudnorm
ffmpeg -i "$input_file" -pass 1 "${extra_args[@]}" \
-filter:a loudnorm=print_format=json -f null -y /dev/null |
grep -E '^\[Parsed_loudnorm_([0-9]+) @ 0x[0-9a-f]+\]' -A12 |
perl -0777 -pe 's/}\s+\[Parsed_loudnorm_([0-9]+) @ 0x[0-9a-f]+\]\s+/ },\n "$1": /g' |
perl -0777 -pe 's/\[Parsed_loudnorm_([0-9]+) @ 0x[0-9a-f]+\]\s+/ "$1": /g' |
sed 's/^}/ }/' |
sed '1 i\{'
printf '}\n';
exit
example output:
{
"0": {
"input_i": "-30.05",
"input_tp": "-0.01",
...
},
"1": {
"input_i": "-30.05",
"input_tp": "-0.01",
...
}
}
#! /usr/bin/env bash
# ffmpeg-loudnorm-format-filters.sh
# take a json file generated by ffmpeg-loudnorm-analyze.sh
# and format audio filters for ffmpeg
# example output:
# loudnorm=linear=true:I=-14:LRA=7:tp=-1:measured_I=-30.05:measured_LRA=16.60:measured_tp=-0.01:measured_thresh=-41.55:offset=0.46:print_format=summary
# to use the audio filter in ffmpeg:
# ffmpeg -af "loudnorm=..."
# https://ffmpeg.org/ffmpeg-filters.html#loudnorm
# https://superuser.com/questions/1604545/ffmpeg-loudnorm-results-in-not-very-loud
# https://youlean.co/loudness-standards-full-comparison-table/
max_integrated=-14
max_true_peak=-1
# LRA: loudness range target. Range is 1.0 - 50.0. Default value is 7.0
#loudnorm_LRA=11
loudnorm_LRA=7
loudnorm_linear=true
loudnorm_print_format=summary
loudnorm_extra_args=
set -e
set -u
json_file="$1"
stream_ids=$(jq -r 'keys[]' "$json_file" | sort -n)
s='"'
s+='loudnorm='
s+='linear='$loudnorm_linear':'
s+='I='$max_integrated':'
s+='LRA='$loudnorm_LRA':'
s+='tp='$max_true_peak':'
s+='measured_I=\(.input_i):'
s+='measured_LRA=\(.input_lra):'
s+='measured_tp=\(.input_tp):'
s+='measured_thresh=\(.input_thresh):'
s+='offset=\(.target_offset):'
s+='print_format='$loudnorm_print_format
s+="$loudnorm_extra_args"
s+='"'
jq_script="$s"
# print one filter per line, sorted by loudnorm result index
for stream_id in $stream_ids; do
stream_json="$(jq -r ".\"$stream_id\"" "$json_file")"
ffmpeg_loudnorm_filter="$(echo "$stream_json" | jq -r "$jq_script")"
echo "$ffmpeg_loudnorm_filter"
done