class Libis::Format::Converter::AudioConverter

Public Class Methods

input_types() click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 13
def self.input_types
  [:MP3, :FLAC, :AC3, :AAC, :WMA, :ALAC, :WAV, :AIFF, :AMR, :AU, :M4A]
end
new() click to toggle source
Calls superclass method Libis::Format::Converter::Base::new
# File lib/libis/format/converter/audio_converter.rb, line 22
def initialize
  super
end
output_types(format = nil) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 17
def self.output_types(format = nil)
  return [] unless format.nil? || input_types.include?(format)
  [:MP3, :FLAC, :AC3, :AAC, :WMA, :ALAC, :WAV, :AIFF, :AMR, :AU, :M4A]
end
sounds_like(file1, file2, threshold, rate, channels) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 81
def self.sounds_like(file1, file2, threshold, rate, channels)
  rate ||= 96000
  channels ||= 2
  threshold ||= 0.85

  if File.exists?(file1) && File.exists?(file2)
    # Convert input files into raw 16-bit signed audio (WAV) to process with Chramaprint
    file1_raw = File.join('', 'tmp', File.basename(file1) + '.wav')
    file2_raw = File.join('', 'tmp', File.basename(file2) + '.wav')
    FileUtils.rm(file1_raw, force: true)
    FileUtils.rm(file2_raw, force: true)
    cvt_cmd = Libis::Format::Config[:raw_audio_convert_cmd]
    %x"#{cvt_cmd % [file1, file1_raw, rate, channels]}"
    %x"#{cvt_cmd % [file2, file2_raw, rate, channels]}"
    file1_audio = File.binread(file1_raw)
    file2_audio = File.binread(file2_raw)

    # Get audio fingerprints
    chromaprint = Chromaprint::Context.new(rate, channels, Chromaprint::ALGORITHM_TEST3)
    file1_fp = chromaprint.get_fingerprint(file1_audio)
    file2_fp = chromaprint.get_fingerprint(file2_audio)

    # Cleanup files
    FileUtils.rm(file1_raw, force: true)
    FileUtils.rm(file2_raw, force: true)

    # Compare fingerprints and compare result against threshold
    cmp = file1_fp.compare(file2_fp)
    # puts "Threshold[#{File.basename(exp_file)},#{File.basename(tgt_file)}: #{cmp}"
    cmp > threshold
  else
    false
  end

rescue Exception => e
  error "Error comparing sound file #{file1} and #{file2}: #{e.message} @ #{e.backtrace.first}"
  false
end

Public Instance Methods

bit_rate(value) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 50
def bit_rate(value)
  @options[:bit_rate] = value.to_s
end
channels(value) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 58
def channels(value)
  @options[:channels] = value.to_s
end
codec(codec) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 34
def codec(codec)
  @options[:codec] = codec
end
convert(source, target, _format, opts = {}) click to toggle source
Calls superclass method Libis::Format::Converter::Base#convert
# File lib/libis/format/converter/audio_converter.rb, line 72
def convert(source, target, _format, opts = {})
  super

  FileUtils.mkpath(File.dirname(target))

  convert_file(source, target)

end
duration(seconds) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 42
def duration(seconds)
  @options[:duration] = seconds.to_s
end
format(format) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 30
def format(format)
  @options[:format] = format
end
preset(stream, name) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 68
def preset(stream, name)
  (@options[:preset] ||= {})[stream] = name
end
quality(value) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 46
def quality(value)
  @options[:quality] = value.to_s
end
quiet(v) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 26
def quiet(v)
  @flags[:quiet] = !!v
end
sampling_freq(value) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 54
def sampling_freq(value)
  @options[:sampling_freq] = value.to_s
end
start(seconds) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 38
def start(seconds)
  @options[:start] = seconds.to_s
end
web_stream(value) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 62
def web_stream(value)
  if value
    @options[:codec] = 'mp3'
  end
end

Protected Instance Methods

convert_file(source, target) click to toggle source
# File lib/libis/format/converter/audio_converter.rb, line 122
def convert_file(source, target)
  opts = {global: [], input: [], filter: [], output: []}
  opts[:global] << '-hide_banner'
  opts[:global] << '-loglevel' << (@options[:quiet] ? 'fatal' : 'warning')
  opts[:output] << '-vn' # disable input video stream in case it exists
  opts[:output] << '-codec:a' << @options[:codec] if @options[:codec]
  opts[:output] << '-map_metadata:g' << '0:g' # Copy global metadata
  opts[:output] << '-map_metadata:s:a' << '0:s:a' # Copy audio metadata
  opts[:input] << '-accurate_seek' << (@options[:start].to_i < 0 ? '-sseof' : '-ss') << @options[:start] if @options[:start]
  opts[:input] << '-t' << @options[:duration].to_s if @options[:duration]
  opts[:output] << '-q:a' << @options[:quality].to_s if @options[:quality]
  opts[:output] << '-b:a' << @options[:bit_rate].to_s if @options[:bit_rate]
  opts[:output] << '-ar' << @options[:sampling_freq].to_s if @options[:sampling_freq]
  opts[:output] << '-ac' << @options[:channels].to_s if @options[:channels]
  opts[:output] << '-f' << @options[:format].to_s if @options[:format]
  result = Libis::Format::Tool::FFMpeg.run(source, target, opts)
  info "FFMpeg output: #{result}"
  result
  target
end