ruby-av / paperclip-av-transcoder

Audio/Video Transcoder for Paperclip using FFMPEG/Avconv
MIT License
136 stars 83 forks source link

Move AV's `add_destination` after `convert_options` to permit second input (e.g. watermark). #58

Open joshuapinter opened 6 years ago

joshuapinter commented 6 years ago

When you call @cli.add_destination(dst.path), AV will add various output formats automatically, based on the destination filename. You can see that here:

https://github.com/ruby-av/av/blob/f00e6295e8f175262c99f2a5c3f1d4ed75c2c436/lib/av/commands/base.rb#L134

def output_format format
  @output_format = format
  case format.to_s
  when /jpg$/, /jpeg$/, /png$/, /gif$/ # Images
    add_output_param 'f', 'image2'
    add_output_param 'vframes', '1'
  when /webm$/ # WebM
    add_output_param 'f', 'webm'
    add_output_param 'acodec', 'libvorbis'
    add_output_param 'vcodec', 'libvpx'
  when /ogv$/ # Ogg Theora
    add_output_param 'f', 'ogg'
    add_output_param 'acodec', 'libvorbis'
    add_output_param 'vcodec', 'libtheora'
  when /mp4$/
    add_output_param 'acodec', 'aac'
    add_output_param 'strict', 'experimental'
  end
end

These output params will naturally come before the output_options specified in this gem, which is probably fine most of the time but it prevents some advanced but common uses, like adding a watermark overlay to your videos.

For example, creating a watermark overlay on a video would look like this:

mp4: { 
  format: 'mp4', 
  convert_options: { 
    output: { 
      'i': 'my-watermark.png',
      'filter_complex': 'overlay=10:10',
    } 
  } 
}

However, this generates an FFMPEG command that looks like this:

ffmpeg -i my-input-video.mkv -acodec aac -strict experimental -i my-watermark.png -filter_complex overlay=10:10 -y my-output-video.mp4

That causes a problem because it tries to apply the -acodec aac to the -i my-watermark.png, which is an image and you get an error message like this:

decoding for stream 0 failed
Could not find codec parameters for stream 0 (Audio: aac, 0 channels, fltp): unspecified sample rate
Consider increasing the value for the 'analyzeduration' and 'probesize' options

By moving the add_destination after we add our convert_options to the @cli, it generates a FFMPEG command like this:

ffmpeg -i my-input-video.mkv -i my-watermark.png -filter_complex overlay=10:10 -acodec aac -strict experimental -y my-output-video.mp4

This properly applies the "default" output options from the AV gem to the output file, and everybody is happy.