ffmpeg altonorm 2pass em linha única

ffmpeg altonorm 2pass em linha única

DR um exemplo de loudnorm 2pass em linha única usando ffmpeg (ffmpeg-normalize é thread/processo único e não consigo combinar outras opções de ffmpeg a ele)

Não há muitos exemplos no Loudnorm, já que é relativamente novo no ffmpeg. Tenho usado o ffmpeg há cerca de 10 anos. Eu sou novo no Loudnorm, no entanto

Eu li:

http://k.ylo.ph/2016/04/04/loudnorm.html

Como posso normalizar o áudio usando o ffmpeg?

que são úteis. no entanto, estou tentando consolidar várias entradas do ffmpeg em 1. usar a biblioteca ffmpeg-normalize (o python) também limita você a um único thread/processo. que é lento

para 2 passagens do ffmpeg x264 você pode simplesmente fazer:

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

não parece existir para o alto padrão. Não vejo uma maneira de fazer isso com uma passagem única e duas?

atualmente estou codificando vídeo, normalizando o áudio e, finalmente, removendo metadados e dados de capítulos de arquivos, se existirem (independentemente de existirem ou não)

isso cria 3 arquivos descartáveis ​​(incluindo o original)

ser capaz de fazer alto-norm em uma única linha me ajudaria a adicionar outras coisas. Também é possível fazer 2 passagens de x264 e 2 passagens de alto-norm simultaneamente? como fazer com que ele processe os dois e depois combine-os na segunda passagem.

Se possível, gostaria de exemplos disso e não de links para coisas. Posso pesquisar links no Google por conta própria e por várias semanas. Obrigado

Responder1

Não há como executar um filtro Loudnorm de duas passagens automaticamente apenas com o ffmpeg, mas você pode usar offmpeg-normalizeprograma para fazer isso por você. Eu sei que você mencionou isso, mas se quiser codificar vídeo ao mesmo tempo - principalmente com duas passagens - você terá que trabalhar com um arquivo intermediário, ou seja:

  • Primeira execução: ffmpeg-normalizeno vídeo original, copiando o fluxo de vídeo original.
  • Segunda execução: codificação x264 (multithread) do arquivo de áudio normalizado ou dos fluxos de vídeo do arquivo original.

O que você deseja alcançar simplesmente não pode ser feito apenas pelo ffmpeg. Você precisa programar sua própria solução, principalmente se quiser lidar com vários arquivos em paralelo. Isso certamente aceleraria o processo, mesmo se uma única execução do ffmpeg usasse apenas um thread.

Como ponto de partida, há também umscript Ruby mais simplesno repositório FFmpeg. Ele executa duas passagens de alto padrão, lendo as estatísticas da primeira execução. Você pode modificá-lo para executar adicionalmente a codificação x264 de duas passagens com multithreading, ou seja, executar a primeira passagem x264 na primeira execução e a segunda na segunda execução:

Primeira passagem:

ffmpeg -y -i $FILE -c:v libx264 -b:v 4000k -pass 1 -filter:a loudnorm=print_format=json -f mkv /dev/null

Leia as estatísticas JSON da loudnormsaída (por exemplo, usando o analisador JSON do Python ou qualquer outra ferramenta como grepou awk) e execute a segunda passagem:

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

Onde $input_i, $input_lra, $input_tp, $input_threshsão os valores lidos na primeira passagem.

Responder2

Não há necessidade de outro programa. Na verdade, isso PODE ser feito apenas com o ffmpeg. Na verdade, criei um arquivo bat que fará isso.

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

O que isto faz é primeiro analisar o áudio e salvar os resultados em um arquivo de texto. Em seguida, ele lê os resultados do arquivo de texto e os armazena como variáveis ​​para cada campo de medição necessário. Basta ajustar I= e TP= ao seu gosto no arquivo.

Responder3

Começando depetermgsugestão, este é o equivalente para usuários *nix:

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

Substitua $input e $output pelos seus arquivos de entrada e saída.

O primeiroffmpegO comando produz uma saída detalhada com um objeto JSON final, que é filtrado pelosedcomando no pipe e armazenado em um arquivo temporário. Cada um dos cinco comandos que se seguem carrega em uma variável um parâmetro relevante para ser alimentado ao segundoffmpegpassar. A filtragem opera em três etapas de um pipe: primeiro é selecionada a linha que contém o parâmetro relevante (grep), em seguida o valor é separado pelo nome (corte) e, finalmente, apenas a parte numérica é classificada (tr). O processo não é 100% confiável, pois depende do formato de saída do comando ffmpeg.

Responder4

mais scripts bash para o filtro ffmpeg loudnorm

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

informação relacionada