1#!/usr/bin/env ruby 2 3require 'open3' 4require 'json' 5 6ffmpeg_bin = 'ffmpeg' 7target_il = -24.0 8target_lra = +11.0 9target_tp = -2.0 10samplerate = '48k' 11 12if ARGF.argv.count != 2 13 puts "Usage: #{$PROGRAM_NAME} input.wav output.wav" 14 exit 1 15end 16 17ff_cmd = Array.new([ 18 ffmpeg_bin, 19 '-hide_banner', 20 '-i', ARGF.argv[0], 21 '-af', "loudnorm='I=#{target_il}:LRA=#{target_lra}:tp=#{target_tp}:print_format=json'", 22 '-f', 'null', 23 '-']); 24 25_stdin, _stdout, stderr, wait_thr = Open3.popen3(*ff_cmd) 26 27if wait_thr.value.success? 28 stats = JSON.parse(stderr.read.lines[-12, 12].join) 29 loudnorm_string = 'loudnorm=' 30 loudnorm_string += 'print_format=summary:' 31 loudnorm_string += 'linear=true:' 32 loudnorm_string += "I=#{target_il}:" 33 loudnorm_string += "LRA=#{target_lra}:" 34 loudnorm_string += "tp=#{target_tp}:" 35 loudnorm_string += "measured_I=#{stats['input_i']}:" 36 loudnorm_string += "measured_LRA=#{stats['input_lra']}:" 37 loudnorm_string += "measured_tp=#{stats['input_tp']}:" 38 loudnorm_string += "measured_thresh=#{stats['input_thresh']}:" 39 loudnorm_string += "offset=#{stats['target_offset']}" 40else 41 puts stderr.read 42 exit 1 43end 44 45ff_cmd = Array.new([ 46 ffmpeg_bin, 47 '-y', '-hide_banner', 48 '-i', ARGF.argv[0], 49 '-af', loudnorm_string, 50 '-ar', samplerate, 51 ARGF.argv[1].to_s]); 52 53_stdin, _stdout, stderr, wait_thr = Open3.popen3(*ff_cmd) 54 55if wait_thr.value.success? 56 puts stderr.read.lines[-12, 12].join 57 exit 0 58else 59 puts stderr.read 60 exit 1 61end 62