Skip to main content

Convert videos using ffmpeg by ffmpeg_paperclip-Rails

Recently i implemented video uploads at S3 using ffmpeg-paperclip and ffmpeg where my uploaded videos get converted into mp4,webm and ogg(most required formats) along with 2 screenshots(with diff sizes) and stored at S3.
its so wonderful in many ways:-
  1. your uploaded videos get converted into required formats(compatible on all browsers) before saving using ffmpeg through ffmpeg-paperclip
  2. moreover,you will also get screenshot(2 different images)of every video uploaded + AMAZON S3(you can even store locally,refer Paperclip)
  3. if you want the background job to process video conversion then,use delayed_paperclip 
i will show you how you can convert your uploaded videos into required formats and why we need to convert ....well refer this .Before starting make sure that you have ffpmeg installed with all libraries needed,so click the above link instead of searching for how to install ffmpeg and install it(will take around 30mins.but its worthy).
Here i am using mediaelement.js and Rails 3.2.13
The below code is expecting that:
  1. you have a working upload using paperclip(usually 3.5.1)
  2. Amazon s3 configured,if not then view my recent post to configure S3 on rails
  3. you must have ffmpeg installed 
my Gemfile looks like this:

gem 'paperclip', '3.5.1'
gem "aws-sdk"
gem "paperclip-ffmpeg"
gem 'delayed_paperclip'

video.rb(convert to mp4,webm and ogg with two screenshots )

class Video < ActiveRecord::Base
  default_scope order: 'created_at DESC'
  has_attached_file :source,
  :default_url => '/dashboard/default_avatar.jpg',
  :styles => {
      :mp4video => { :geometry => '520x390', :format => 'mp4',
        :convert_options => { :output => { :vcodec => 'libx264',
          :vpre => 'ipod640', :b => '250k', :bt => '50k',
          :acodec => 'libfaac', :ab => '56k', :ac => 2 } } },
      :oggvideo => { :geometry => '520x390', :format => 'ogg',
        :convert_options => { :output => { :vcodec => 'libtheora',
          :b => '250k', :bt => '50k', :acodec => 'libvorbis',
          :ab => '56k', :ac => 2 } } },
      :webmvideo => { :geometry => '520x390', :format => 'webm',
      :convert_options => { :output => { :vcodec => 'libvpx',
        :b => '250k', :bt => '50k', :acodec => 'libvorbis',
        :ab => '56k', :ac => 2 } } },  
      :view => { :geometry => '520x390', :format => 'jpg', :time => 2 },
      :preview => { :geometry => '160x120', :format => 'jpg', :time => 2 }
    },
    processors: [:ffmpeg],
    :max_size => 300.megabytes, 
    :storage => :s3,
    :s3_credentials => S3_CREDENTIALS
  ##here comes delayed video processing using delayed_papeclip
  process_in_background :source , :processing_image_url => "/images/loading.gif" 


if you want to use default styles as let FFMPEG decide the best specifications for the videos to convert,then you can just use:-


 :styles => {
    :mp4video => { :geometry => "640x480", :format => 'mp4', :convert_options => {:output => {:ar => 44100}} },
    :webmvideo =>{ :geometry => "1024x576", :format => 'webm', :convert_options => {:output => {:ar => 44100}} },
    :oggvideo => { :geometry => "1024x576", :format => 'ogg', :convert_options => {:output => {:ar => 44100}} }
  }

Access the uploaded video:-

  1. video.source.url-gives original uploaded video
  2. video.source.url(:mp4video)-gives uploaded video in mp4
  3. video.source.url(:small)-gives uploaded video screenshot(for poster attribute in video_tag)

Comments

jusaf said…
Hi. This is nice but if for example the original video is a MP4 already, it gets encoded again. how could we change this so that if the original video is already one of the target styles then it should skip that encoding?
Milind said…
Apology for the late reply, you can upload any video and this will get converted in the three formats supported by almost all the browers today.
However, its good if you can test different formats like mp4, mov/quicktime, mkv, flv, avi, webm and 3gp.

Popular posts from this blog

Access files on AWS S3 bucket using aws-sdk-s3 with Rails 6

This is a quick post to share few easy methods to access files on AWS S3. The below custom utility methods uses  aws-sdk-s3 Firstly lets define a constant to access files on S3 -  ##to manage S3 Resources S3 = Aws::S3::Resource.new( region: "YOUR-REGION", access_key_id: "YOUR-AWS-KEY", secret_access_key: "YOUR-AWS-SECRET") ##to query S3 S3_client = Aws::S3::Client.new( access_key_id: configatron.aws.s3.credentials.access_key_id, secret_access_key: configatron.aws.s3.credentials.secret_access_key, region: configatron.aws.s3.region ) Now, lets use the S3 OBJECT to access files in different ways -  1. Get all files in a S3 FOLDER     ##this gives a array of file paths present in the folder specified by prefix attribute          s3objects = S3.bucket("my-output-bucket").objects({prefix: "/inputs/any-random-user-folder"}).collect(&:key) ##you can also delete the file if found ...

Setting Axios to put/post dynamically

 Let me avoid wasting more time and quickly jump on the problem statement. What is the problem statement -  - I want to use the same React component both for Create/Update. How I achieved it -  - Firstly for new object, it worked smoothly and I wanted to reuse the same component again for edit/update too. - I sent the existing values as props and saved them into the corresponding states. - I reused the existing method ( axios server call ) so that it dynamically POST/PUT as needed.This is show below -         //this method calls post/put dynamically - simple code here..no rocket science methodCall = () => { const { Id, editable, details } = this.state; //check if new or existing record if (editable) { return API.put(`/post/${Id}`, details); } else { return API.post("/post", details); } }; //call this method onClick/onSubmit - as you want to handleSubmit = (event) => { event.preventDefault(); ...

So easy to install ruby on rails on ubuntu 12.04/centos 6 and start development

Its easy to start development on ubuntu/centos using vmware and start development.i will start the code on certain assumptions : you know ruby on rails you are aware of how to make use of google(in case u are stuck and want to explore more without spoon feeding) LAST BUT NOT LEAST---you love coding short preview of sequence you need to follow:  START -> get vmware -> get ubuntu/centos -> get rvm -> get ruby -> get rails----END--THAT'S IT Lets start and finish this quickly using below mentioned steps: install vmware player if you are using windows/mcintosh from https://my.vmware.com/web/vmware/downloads  NOW.vmware player need image file of the operating system you want,so hit the url and get centos at http://vault.centos.org/6.2/isos/ OR ubuntu at http://www.ubuntu.com/download/desktop ONCE both vmware player and ubuntu/centos are downloaded,follow the steps to first install vmware(very simple) and mounting ubu...