ffmpeg loudnorm 2pass in einer einzigen Zeile

ffmpeg loudnorm 2pass in einer einzigen Zeile

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-normalizeProgramm, 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-normalizeauf 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 loudnormAusgabe (z. B. mit dem JSON-Parser von Python oder einem anderen Tool wie grepoder 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_threshdie 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

verwandte Informationen