From: Stefano Sabatini <stefasab@gmail.com> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Cc: Stefano Sabatini <stefasab@gmail.com> Subject: [FFmpeg-devel] [PATCH] tools/normalize: port to python3, extend syntax Date: Wed, 5 Apr 2023 01:12:10 +0200 Message-ID: <20230404231210.70359-1-stefasab@gmail.com> (raw) Also add documentation and logging. --- tools/normalize.py | 106 +++++++++++++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 33 deletions(-) diff --git a/tools/normalize.py b/tools/normalize.py index 7d87c5e154..e87f738c5f 100755 --- a/tools/normalize.py +++ b/tools/normalize.py @@ -1,33 +1,73 @@ -#!/usr/bin/env python2 - -import sys, subprocess - -if len(sys.argv) > 2: - ifile = sys.argv[1] - encopt = sys.argv[2:-1] - ofile = sys.argv[-1] -else: - print 'usage: %s <input> [encode_options] <output>' % sys.argv[0] - sys.exit(1) - -analysis_cmd = 'ffprobe -v error -of compact=p=0:nk=1 ' -analysis_cmd += '-show_entries frame_tags=lavfi.r128.I -f lavfi ' -analysis_cmd += "amovie='%s',ebur128=metadata=1" % ifile -try: - probe_out = subprocess.check_output(analysis_cmd, shell=True) -except subprocess.CalledProcessError, e: - sys.exit(e.returncode) -loudness = ref = -23 -for line in probe_out.splitlines(): - sline = line.rstrip() - if sline: - loudness = sline -adjust = ref - float(loudness) -if abs(adjust) < 0.0001: - print 'No normalization needed for ' + ifile -else: - print "Adjust %s by %.1fdB" % (ifile, adjust) - norm_cmd = ['ffmpeg', '-i', ifile, '-af', 'volume=%fdB' % adjust] - norm_cmd += encopt + [ofile] - print ' => %s' % ' '.join(norm_cmd) - subprocess.call(norm_cmd) +#!/usr/bin/env python3 + +import argparse +import logging +import shlex +import subprocess + +HELP = ''' +Normalize audio input. + +The command uses ffprobe to analyze an input file with the ebur128 +filter, and finally run ffmpeg to normalize the input depending on the +computed adjustment. + +ffmpeg encoding arguments can be passed through the extra arguments +after options, for example as in: +normalize.py --input input.mp3 --output output.mp3 -- -loglevel debug -y +''' + +logging.basicConfig(format='normalize|%(levelname)s> %(message)s', level=logging.INFO) +log = logging.getLogger() + + +class Formatter( + argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter +): + pass + + +def normalize(): + parser = argparse.ArgumentParser(description=HELP, formatter_class=Formatter) + parser.add_argument('--input', '-i', required=True, help='specify input file') + parser.add_argument('--output', '-o', required=True, help='specify output file') + parser.add_argument('--dry-run', '-n', help='simulate commands', action='store_true') + parser.add_argument('encode_arguments', nargs='*', help='specify encode options used for the actual encoding') + + args = parser.parse_args() + + analysis_cmd = [ + 'ffprobe', '-v', 'error', '-of', 'compact=p=0:nk=1', + '-show_entries', 'frame_tags=lavfi.r128.I', '-f', 'lavfi', + f"amovie='{args.input}',ebur128=metadata=1" + ] + + def _run_command(cmd, dry_run=False): + log.info(f"Running command:\n$ {shlex.join(cmd)}") + if not dry_run: + result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) + return result + + result = _run_command(analysis_cmd) + + loudness = ref = -23 + for line in result.stdout.splitlines(): + sline = line.rstrip() + if sline: + loudness = sline + + adjust = ref - float(loudness) + if abs(adjust) < 0.0001: + logging.info(f"No normalization needed for '{args.input}'") + return + + logging.info(f"Adjusting '{args.input}' by {adjust:.2f}dB...") + normalize_cmd = [ + 'ffmpeg', '-i', args.input, '-af', f'volume={adjust:.2f}dB', + ] + args.encode_arguments + [args.output] + + _run_command(normalize_cmd, args.dry_run) + + +if __name__ == '__main__': + normalize() -- 2.25.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next reply other threads:[~2023-04-04 23:12 UTC|newest] Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top 2023-04-04 23:12 Stefano Sabatini [this message] 2023-05-08 19:47 ` Stefano Sabatini 2023-05-14 9:31 ` Stefano Sabatini
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20230404231210.70359-1-stefasab@gmail.com \ --to=stefasab@gmail.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git