-
-
Save rahimsiz/1552197 to your computer and use it in GitHub Desktop.
ffmpeg & carrierwave
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module CarrierWave | |
module FFMPEG | |
extend ActiveSupport::Concern | |
module ClassMethods | |
def faststart | |
process :faststart => true | |
end | |
def transcode options | |
process :transcode => options | |
end | |
def send_thumbnail_to method_name | |
process :send_thumbnail_to => method_name | |
end | |
end | |
def transcode *args | |
options = args.inject({}){|o, p| o[p.first] = p.last; o } # combining hash from array of pairs | |
options = {:custom => rotation_filters}.merge(options) | |
transcoder_options = { | |
:preserve_aspect_ratio => options.delete(:preserve_aspect_ratio), | |
:max_dimensions => options.delete(:max_dimensions) | |
} | |
with_temp_filepath do |temp_path| | |
FileUtils.mv current_path, temp_path | |
file = MovieWithRotationSupport.new temp_path | |
file.transcode current_path, options, transcoder_options | |
end | |
end | |
def faststart _ | |
with_temp_filepath do |temp_path| | |
FileUtils.mv current_path, temp_path | |
puts 'Applying qt-faststart' | |
`qt-faststart #{temp_path} #{current_path}` | |
end | |
end | |
def send_thumbnail_to method_name | |
with_temp_filepath ['thumbnail', '.jpg'] do |temp_path| | |
file = MovieWithRotationSupport.new current_path | |
file.transcode temp_path, :custom => "-ss 00:00:01 -vframes 1 -f image2 #{rotation_filters}" | |
model.send method_name, File.new(temp_path) | |
end | |
end | |
private | |
def with_temp_filepath basename = 'video' | |
tmpfile = Tempfile.new basename | |
tmpfile.close | |
yield tmpfile.path | |
ensure | |
tmpfile.unlink | |
end | |
def rotation_filters | |
case MiniExiftool.new(current_path).rotation | |
when 180 | |
'-vf "vflip,hflip"' | |
when 90 | |
'-vf "transpose=1"' | |
when 270 | |
'-vf "transpose=2"' | |
else | |
'' | |
end | |
end | |
class MovieWithRotationSupport < ::FFMPEG::Movie | |
attr_reader :rotation | |
def initialize path | |
super | |
@rotation = MiniExiftool.new(path).rotation | |
@resolution = @resolution.split('x').reverse.join('x') if rotated? | |
end | |
def transcode(output_file, options = EncodingOptions.new, transcoder_options = {}, &block) | |
TranscoderWithMaxDimensionsSupport.new(self, output_file, options, transcoder_options).run &block | |
end | |
protected | |
def rotated? | |
@rotation % 180 != 0 | |
end | |
end | |
class TranscoderWithMaxDimensionsSupport < ::FFMPEG::Transcoder | |
def apply_transcoder_options | |
super | |
return if @movie.calculated_aspect_ratio.nil? | |
if @transcoder_options[:max_dimensions] | |
new_height = @movie.height | |
new_width = @movie.width | |
if new_width > @raw_options.width | |
new_width = @raw_options.width | |
new_height = new_width / @movie.calculated_aspect_ratio | |
new_height = new_height.ceil.even? ? new_height.ceil : new_height.floor | |
new_height += 1 if new_height.odd? # needed if new_height ended up with no decimals in the first place | |
end | |
if new_height > @raw_options.height | |
new_height = @raw_options.height | |
new_width = new_height * @movie.calculated_aspect_ratio | |
new_width = new_width.ceil.even? ? new_width.ceil : new_width.floor | |
new_width += 1 if new_width.odd? | |
end | |
if @raw_options[:custom] && @raw_options[:custom]['transpose'] | |
@raw_options[:resolution] = "#{new_height}x#{new_width}" | |
else | |
@raw_options[:resolution] = "#{new_width}x#{new_height}" | |
end | |
@raw_options[:aspect] = new_width.to_f / new_height.to_f | |
end | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class VideoUploader < CarrierWave::Uploader::Base | |
include CarrierWave::MimeTypes | |
include CarrierWave::FFMPEG | |
storage :fog | |
def store_dir | |
"uploads/#{model.class.table_name}/#{mounted_as}/#{model.id}" | |
end | |
process :set_content_type | |
version :default do | |
process :send_thumbnail_to => :photo=, | |
:transcode => { | |
:audio_codec => 'copy', | |
:video_codec => 'libx264', | |
:video_bitrate => 500, | |
:resolution => '640x640', | |
:max_dimensions => true | |
}, | |
:faststart => true | |
end | |
def extension_white_list | |
%w(mov mp4 mpe mpg m4v) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment