通过paperclip上传视频并转换为flv格式

paperclip作为一个非常流行的文件上传的rails插件,最常被应用的就是上传图片,裁剪,格式转换等等,网上的demo也是一大堆,但是介绍视频上传的却很少。其实paperclip的处理模块定义非常清晰,可以很方便的实现视频的格式转换。

我们的案例是这样的:用户上传任何视频文件,我们都将其转换为flv格式,然后再显示在网页上。

首先,安装ffmpeg,所有的转换工作都是使用ffmpeg命令来执行的。安装文档网上有很多,这里就不重复了。不过我在mac下面用port安装之后,转换视频的时候总是报Audio encoding failed错误,需要将ffmpeg依赖的lame降版本到3.97_0。另外你需要安装paperclip插件。

接着,新建/lib/paperclip_processors目录,同时在该目录下新建flash.rb文件

module Paperclip
  class Flash  Processor

    attr_accessor :geometry, :file, :whiny

    def initialize(file, options = {}, attachment = nil)
      super
      @file = file
      unless options[:geometry].nil? || (@geometry = Geometry.parse(options[:geometry])).nil?
        @geometry.width = (@geometry.width / 2.0).floor * 2.0
        @geometry.height = (@geometry.height / 2.0).floor * 2.0
        @geometry.modifier = ''
      end
      @whiny = options[:whiny].nil? ? true : options[:whiny]
      @basename = File.basename(file.path, File.extname(file.path))
      data = attachment
    end

    def make
      src = @file
      flv = Tempfile.new([ @basename, 'flv' ].compact.join(.))
      flv.close

      command = %Q[-i #{File.expand_path(src.path)} -y ]
      command  -s #{geometry.to_s}  unless geometry.nil?
      command  %Q[#{File.expand_path(flv.path)}]

      begin
        success = Paperclip.run('ffmpeg', command)
      rescue PaperclipCommandLineError
        raise PaperclipError, There was an error processing the thumbnail for #{@basename} if whiny
      end

      flv
    end
  end
end

注意,一定要放在lib/paperclip_processors目录下面,这样paperclip才能找到这个视频转换的处理器。

然后,在model中声明使用视频转换处理器,并定义尺寸

class Video < ActiveRecord::Base
  has_attached_file :attachment, :styles = {
    :medium = {:geometry = 400x300, :format = flv, :processors = [:flash]},
    :large = {:geometry = 800x600, :format = flv, :processors = [:flash]}
  }
end

这样,当用户上传一个test.avi文件时,你会在服务器的上传目录下面找到test_original.avi, test_medium.flv和test_large.flv三个文件。

最后,在播放视频的时候,只需要把视频的url传给相应的flash播放器(player.swf)即可

video.attachment.url(:medium)

注:paperclip升级到2.3.3之后,command参数的写法需要修改为

options = [
  -i,
  File.expand_path(src.path),
  -y,
  -ar,
  22050,
  -b,
  1200K,
  File.expand_path(flv.path)
].flatten.compact

success = Paperclip.run('ffmpeg', *options)

Posted in  rails


blog comments powered by Disqus
Fork me on GitHub