tools/loudnorm.rb
7b8445f0
 #!/usr/bin/env ruby
 
 require 'open3'
 require 'json'
 
 ffmpeg_bin = 'ffmpeg'
 target_il  = -24.0
 target_lra = +11.0
 target_tp  = -2.0
 samplerate = '48k'
 
 if ARGF.argv.count != 2
   puts "Usage: #{$PROGRAM_NAME} input.wav output.wav"
   exit 1
 end
 
 ff_cmd = Array.new([
   ffmpeg_bin,
   '-hide_banner',
   '-i', ARGF.argv[0],
   '-af', "loudnorm='I=#{target_il}:LRA=#{target_lra}:tp=#{target_tp}:print_format=json'",
   '-f', 'null',
   '-']);
 
 _stdin, _stdout, stderr, wait_thr = Open3.popen3(*ff_cmd)
 
 if wait_thr.value.success?
   stats = JSON.parse(stderr.read.lines[-12, 12].join)
   loudnorm_string  = 'loudnorm='
   loudnorm_string += 'print_format=summary:'
   loudnorm_string += 'linear=true:'
   loudnorm_string += "I=#{target_il}:"
   loudnorm_string += "LRA=#{target_lra}:"
   loudnorm_string += "tp=#{target_tp}:"
   loudnorm_string += "measured_I=#{stats['input_i']}:"
   loudnorm_string += "measured_LRA=#{stats['input_lra']}:"
   loudnorm_string += "measured_tp=#{stats['input_tp']}:"
   loudnorm_string += "measured_thresh=#{stats['input_thresh']}:"
   loudnorm_string += "offset=#{stats['target_offset']}"
 else
   puts stderr.read
   exit 1
 end
 
 ff_cmd = Array.new([
   ffmpeg_bin,
   '-y', '-hide_banner',
   '-i', ARGF.argv[0],
   '-af', loudnorm_string,
   '-ar', samplerate,
   ARGF.argv[1].to_s]);
 
 _stdin, _stdout, stderr, wait_thr = Open3.popen3(*ff_cmd)
 
 if wait_thr.value.success?
   puts stderr.read.lines[-12, 12].join
   exit 0
 else
   puts stderr.read
   exit 1
 end