class CarrierWave::Audio::Processor

Constants

DefaultConvertOptions
DefaultWatermarkOptions

Public Class Methods

convert(source, options={}) click to toggle source

Convert an audio file at the given filename with the given options.

Available options (all optional) are:

:output_format => Output file format

  Currently only :mp3 supported
  Default is :mp3.

:logger => IOStream to log progress to.

Example:

CarrierWave::Audio::Processor.convert("Kickstart My Heart.wav")
CarrierWave::Audio::Processor.generate("Kickstart My Heart.wav", :output_format => :wav)
# File lib/carrierwave/audio/processor.rb, line 38
def convert(source, options={})
  options = DefaultConvertOptions.merge(options)
  format = sanitized_format(options[:output_format])
  output_options = options[:output_options] || {}

  @log = Log.new(options[:logger])
  @log.start!

  ext = File.extname(source)
  input_options = { type: ext.gsub(/\./, '') }
  final_filename = tmp_filename(source: source, format: format)
  @log.timed("\nConverting...") do
    convert_file(
      input_file_path: source, 
      input_options: input_options, 
      output_file_path: final_filename, 
      output_options: output_options_for_format(format).merge(output_options)
    )
  end

  @log.done!("Converted audio file '#{final_filename}'")

  final_filename
end
watermark(source, options={}) click to toggle source

Watermark an audio file at the given filename with the given options.

Available options are:

:watermark_file => (REQUIRED) Watermark audio file path

:output_format => (Optional) Output file format

  Currently only :mp3 supported
  Default is :mp3.

:logger => (Optional) IOStream to log progress to.

Example:

CarrierWave::Audio::Processor.watermark("Kickstart My Heart.wav", { watermark_file: "#{Rails.root}/db/watermark.mp3" })
# File lib/carrierwave/audio/processor.rb, line 79
def watermark(source, options={})
  options = DefaultWatermarkOptions.merge(options)
  format = sanitized_format(options[:output_format])
  watermark_file_path = options[:watermark_file]

  raise ArgumentError.new("No watermark filename given, must be a path to an existing sound file.") unless watermark_file_path
  raise RuntimeError.new("Watermark file '#{watermark_file_path}' not found.") unless File.exist?(watermark_file_path)

  @log = Log.new(options[:logger])
  @log.start!

  source_samplerate = Soxi::Wrapper.file(source).samplerate.to_i
  watermark_samplerate = Soxi::Wrapper.file(watermark_file_path).samplerate.to_i
  watermark_ext = File.extname(watermark_file_path)
  watermark_options = { type: watermark_ext.gsub(/\./, '') }
  converted_watermark = watermark_file_path
  if source_samplerate != watermark_samplerate
    converted_watermark = tmp_filename(source: source, format: watermark_ext, prefix: "cnvt_wtmk")
    @log.timed("\nConverting watermarked file to source samplerate of #{source_samplerate}...") do
      convert_file(
        input_file_path: watermark_file_path, 
        input_options: watermark_options, 
        output_file_path: converted_watermark, 
        output_options: output_options_for_format(watermark_options[:type]).merge(rate: source_samplerate)
      )
    end
  end

  ext = File.extname(source)
  input_options = { type: ext.gsub(/\./, '') }
  final_filename = tmp_filename(source: source, format: format, prefix: "wtmk")
  @log.timed("\nCombining source file and watermark, limiting final output...") do
    combiner = Sox::Cmd.new(combine: :mix)
    combiner.add_input source, input_options
    combiner.add_input converted_watermark, watermark_options
    combiner.set_output final_filename, output_options_for_format(format)
    combiner.set_effects({ trim: "0 =#{Soxi::Wrapper.file(source).seconds}", vol: "0 db 0.01" })
    combiner.run
  end

  @log.done!("Watermarked audio file '#{final_filename}'")

  final_filename
end

Private Class Methods

convert_file(input_file_path:, input_options:, output_file_path:, output_options:, fx: {}) click to toggle source

Convert file using options

# File lib/carrierwave/audio/processor.rb, line 127
def convert_file input_file_path:, input_options:, output_file_path:, output_options:, fx: {}
  converter = Sox::Cmd.new
  converter.add_input input_file_path, input_options
  converter.set_output output_file_path, output_options
  converter.set_effects fx
  converter.run
end
output_options_for_format(format) click to toggle source
# File lib/carrierwave/audio/processor.rb, line 144
def output_options_for_format format
  shared_options = {
    channels: 2
  }

  if format.to_sym == :mp3
    {
      type: format.to_s,
      rate: 44100,
      compression: 128
    }.merge(shared_options)
  else
    {
      type: format.to_s,
      rate: 44100
    }.merge(shared_options)
  end
end
sanitized_format(format) click to toggle source
# File lib/carrierwave/audio/processor.rb, line 135
def sanitized_format format
  supported_formats = [:mp3]
  if supported_formats.include?(format.to_sym)
    format.to_s
  else
    raise ArgumentError.new("Unsupported audio format #{format}. Only conversion to #{supported_formats.to_sentence} allowed.")
  end
end
tmp_filename(source:, format:, prefix: nil) click to toggle source

Generate a temporary filename

# File lib/carrierwave/audio/processor.rb, line 164
def tmp_filename source:, format:, prefix: nil
  ext = File.extname(source)
  source_filename_without_ext = File.basename(source, ext)
  File.join File.dirname(source), "tmp#{prefix.present? ? '_' + prefix : ''}_#{source_filename_without_ext}_#{Time.now.to_i}.#{format}"
end