通过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


rails and facebook connect

最近项目需要做一些facebook应用,比如要允许用户登录facebook,要获取用户facebook的好友信息等等。登录facebook自然选用时下流行的facebook connect。代码写起来非常简单,用户的体验也非常好。

首先,进入facebook的开发者页面http://developers.facebook.com/,点击Start building for your site,开始创建你的facebook应用,按照提示一步一步继续。需要注意的是,你可能需要创建两个应用,一个针对本地development环境,一个针对production环境。

接着,安装facebooker的gem,并且加入到rails gem依赖。在config目录下创建facebooker.yml文件,内容为

development:
  api_key:
  secret_key:
  canvas_page_name: localhost
  callback_url: http://localhost:3000
  pretty_errors: true
  set_asset_host_to_callback_url: true
  tunnel:
    public_host_username:
    public_host:
    public_port: 4007
    local_port: 3000
    server_alive_interval: 0

production:
  api_key:
  secret_key:
  canvas_page_name:
  callback_url:
  set_asset_host_to_callback_url: true
  tunnel:
    public_host_username:
    public_host:
    public_port: 4007
    local_port: 3000
    server_alive_interval: 0

在application_controller文件中增加如下代码

before_filter :set_facebook_session
helper_method :facebook_session

facebook_session即为用户登录facebook之后所获取的session,通过它可以获取facebook用户相关的所有信息。

然后就是在html header中引入facebook所需的javascript

<%= fb_connect_javascript_tag %>
<%= init_fb_connect "XFBML", :js => :jquery %>

最后就是在页面上显示facebook登录的图片和文字

<%= fb_login_button %>

你也可以只显示facebook的icon,并且在用户登录之后刷新页面

<%= fb_login_button("window.location.reload(true);", :size => "icon", :v => "2") %>

用户登录facebook之后,你就可以获取到用户和其好友的信息,比如

<%= facebook_session.user.name %>

<% facebook_session.user.friends.each do |friend| %>
  <%= image_tag friend.pic_square if friend.pic_square %>
  <%= friend.first_name %>
  <%= friend.last_name %>
<% end %>

详细的接口可以看看facebooker的rdoc。

Posted in  rails facebook


button_to的使用

页面间的跳转或者请求,用得最多的就是link_to和form_for,一个发送get或delete请求,一个post或put请求。但是碰到投票之类的链接,虽然是一个post请求,但是form里面却不需要任何数据,碰到这样的情况,我们希望像link_to那样一行搞定。

也许你会通过link_to 'xx', 'xx', :method => :delete联想到link_to 'xx', 'xx', :method => :post,但是很不幸,没有这样使用的。还好,rails提供了一个简单的helperbutton_to

button_to 'Vote', post_votes_path(post), :class => 'vote_icon'

生成的html代码如下

<form class="button-to" action="/post/1/comments" method="post">
    <div>
        <input type="submit" value="Vote" class="vote_icon" />
        <input type="hidden" value="zbT/x/CpCjDQdTb2IZQ+ttGqNfv5PfsAJ3/BRK+wBqM=" name="authenticity_token" />
    </div>
</form>

另外说一下页面的显示吧,我们使用vote_icon的class,定义一个background image,问题出来了,使用input会出现一个边框,鼠标放上去是箭头,另外vote icon上面还会显示出字来,解决的方法就是

.vote_icon {
    border: 0;
    text-indent: -999px;
    cursor: pointer;
}

嗯,现在就和link image完全一样了。别急,打开IE7和IE6看看,vote icon上面仍然显示出字来,原来IE7和IE6不支持input上面的text-indent,所以要额外加上

.vote_icon {
    border: 0;
    text-indent: -999px;
    cursor: pointer;
    font-size: 0;
    line-height: 10px;
}

现在一切就都OK咯!

Posted in  rails css


2009年总结

现在才想起来写2009年的总结好像有点晚哦,不过有总比没有好啊。

2009年可以说是先抑后仰的一年,年初在欧酷的工作不是很开心,发觉自己并不是很适合那种不以技术为核心的创业,自己的价值无法得到体现,同时又没有被认同的感觉,所以打算换个工作。

3月份拿到ekohe的offer,完全的技术活,工作以Ruby和Rails为主,是自己的兴趣所在,再加上不加班和免费的午餐,让我坚定了选择ekohe的工作。开始工作没多久就接触了很多新的技术,git, postgres等等。同时知道了github这个网站,3月份给rack做了第一个patch,4月份做了 第一个rails plugin。

4月份在hostmonster买个共享主机,架设自己的博客以及其它的网站。

5月份在上海举行了RubyConf,我做了Desgn Pattern──from Java to Ruby的主题演讲。第一次给这么多人做主题演讲,不免有些紧张,不过能够与这么多Ruby开发者一起交流,感觉还是很不错的。这一次会议对我的自信心有了很大的提高。

之后开始不断为rails写plugin,最成功的就算是bullet plugin了,不仅登上了railslab的视频,也被rails的官方blog所推荐。一种极大的认同感让我积极地投身于社区的开发。

6月份买了几次彩票,不过基本是投入大于产出,所以就放弃了。

7月份题集网上线,不过需要审核,让我消耗了不少时间。

8月份参加了Nike的10公里长跑,70分钟完成,比去年有所退步,应该是工作之后晚上跑步的次数减少的缘故吧。然后养个两只小仓鼠,蛮好玩的,可惜一只已经夭折,不过另一只却是胖一塌糊涂。

10月份参加了Kungfu RailsConf,做了Contributing to Rails by Plugins and Gems主题演讲,同时对于ihower的Rails Best Practices的演讲感同身受,会后把他ppt中的规则做成了一个ruby的静态代码分析工具rails_best_practices,反映也相当不错。

之后两个月好像都比较平静,没什么波澜呢。

2009年看电影的次数差不多是之前10多年的总和,女朋友也被我带动这晚上去跑步锻炼,呵呵。就写这么点吧

Posted in  life


hover and png for ie6

IE6可以说是前端设计师们的最大梦魇,不支持圆角,margin double等等问题,使得书写css的时候不得不专门针对IE6浏览器增加额外的规则。

hover和png透明也是IE6所不支持的,解决方法如下:

hover可以通过Whatever:hover脚本来hack,使用方法很简单,在ie6.css文件中定义

.need_hover_element {
  behavior: url("/stylesheets/csshover3.htc"
)

png透明需要iepngfix脚本来hack,使用方法稍微复杂些,首先在ie6.css文件中定义

.need_png_transparent_element {
  behavior: url("/stylesheets/iepngfix.htc")
}

接着在html文件中引入iepngfix_tilebg.js

然后修改iepngfix.htc文件,修改其中的blank.gif文件路径

IEPNGFix.blankImg = '/images/blank.gif';

好了,你的网站现在能够使IE6支持hover和png透明了,不过当png文件是在hover之后才出现的,png透明似乎就不起作用了。

Posted in  css


Fork me on GitHub