Jim Neath

Manchester based Ruby on Rails & Facebook App Developer

Showing blog posts tagged as "FFMPEG"

So you’ve installed FFMPEG. Now it’s time to move onto converting the video. For this we’re going to be using a couple of plugins.

Paperclip

We will be using the paperclip plugin to upload the videos onto our server. Details of how to install paperclip can be found in my previous article: Paperclip: Attaching Files in Rails. To install you can use any of the following:

git://github.com/thoughtbot/paperclip.git # Github
https://svn.thoughtbot.com/plugins/paperclip/trunk/ # SVN
http://rubyforge.org/projects/paperclip/ # Gem version

Acts As State Machine

Acts_as_state_machine allows you to turn your model into a Finite State Machine (FSM).

A finite state machine (FSM) or finite state automaton (plural: automata) or simply a state machine, is a model of behaviour composed of a finite number of states, transitions between those states, and actions. A finite state machine is an abstract model of a machine with a primitive internal memory.

So let’s install acts_as_state_machine:

ruby script/plugin install http://elitists.textdriven.com/svn/plugins/acts_as_state_machine/trunk/ acts_as_state_machine

Creating the Model

First off, let’s create our video model. We’ll call it video. Inventive, eh?

ruby script/generate model video

Open up your new video model and let’s edit it to look like this:

class Video < ActiveRecord::Base
  # Paperclip
  # http://www.thoughtbot.com/projects/paperclip
  has_attached_file :source

  # Paperclip Validations
  validates_attachment_presence :source
  validates_attachment_content_type :source, :content_type => 'video/quicktime'
end

Nothing spectacular. If you’ve used Paperclip before then nothing should surprise you here. The has_attached_file :source line tells our model that it has an uploaded file called source. This is where we will be storing our video files. The rest of the file uses the built in Paperclip validations.

Adding States

Underneath your current model content, we want to add the following:

  # Acts as State Machine
  # http://elitists.textdriven.com/svn/plugins/acts_as_state_machine
  acts_as_state_machine :initial => :pending
  state :pending
  state :converting
  state :converted, :enter => :set_new_filename
  state :error
  
  event :convert do
    transitions :from => :pending, :to => :converting
  end
  
  event :converted do
    transitions :from => :converting, :to => :converted
  end
  
  event :failed do
    transitions :from => :converting, :to => :error
  end

This will setup acts_as_state_machine along with the states and transitions we want to use. It’s all pretty simple.

Run the Migrations

Open up the xxx_create_videos.rb migration file and edit it so it looks like the following:

class CreateVideos < ActiveRecord::Migration
  def self.up
    create_table :videos do |t|
      t.string :source_content_type
      t.string :source_file_name
      t.integer :source_file_size
      t.string :state
      t.timestamps
    end
  end

  def self.down
    drop_table :videos
  end
end

The columns starting with :source_ are all files for Paperclip. The :state column is used with acts_as_state_machine.

Run the migrations:

rake db:migrate

Adding the Conversion Methods

In your video.rb file add the following methods to your model. These methods take care of the converting the video file:

# This method is called from the controller and takes care of the converting
def convert
  self.convert!
  success = system(convert_command)
  if success && $?.exitstatus == 0
    self.converted!
  else
    self.failure!
  end
end

protected

# This method creates the ffmpeg command that we'll be using
def convert_command
  flv = File.join(File.dirname(source.path), "#{id}.flv")
  File.open(flv, 'w')
  
  command = <<-end_command
    ffmpeg -i #{ source.path } -ar 22050 -ab 32 -acodec mp3 
  -s 480x360 -vcodec flv -r 25 -qscale 8 -f flv -y #{ flv }
  end_command
  command.gsub!(/\s+/, " ")
end

# This update the stored filename with the new flash video file
def set_new_filename
  update_attribute(:source_file_name, "#{id}.flv")
end

The Controller

I’m not going to post the views in this article as they should be straight forward. Just make sure to add :multipart => true to your form otherwise your file’s won’t be uploaded and you’ll look stupid.

class VideosController < ApplicationController
  def index
    @videos = Video.find :all
  end
  
  def new
    @video = Video.new
  end
  
  def create
    @video = Video.new(params[:video])
    if @video.save
      @video.convert
      flash[:notice] = 'Video has been uploaded'
      redirect_to :action => 'index'
    else
      render :action => 'new'
    end
  end
  
  def show
    @video = Video.find(params[:id])
  end
end

After the video is saved in the create method, the convert method is called. This should convert the video to a flash video file, update the database entry and set the state of the model. The state will be set to converted if everything went to plan, or error if everything went to shit.

You can view the full source of video.rb here.

Displaying the Video in a View

When you want to display the video in a view, you will need two things. The first, is swfobject, an unobtrusive way to include flash into a page.

SWFObject is a small Javascript file used for embedding Adobe Flash content. The script can detect the Flash plug-in in all major web browsers (on Mac and PC) and is designed to make embedding Flash movies as easy as possible. It is also very search engine friendly, degrades gracefully, can be used in valid HTML and XHTML 1.0 documents, and is forward compatible, so it should work for years to come.

The second is a flash video player. I highly suggest JW FLV Media Player.

The JW FLV Media Player (built with Adobe’s Flash) is an easy and flexible way to add video and audio to your website. It supports playback of any format the Adobe Flash Player can handle (FLV, but also MP3, H264, SWF, JPG, PNG and GIF). It also supports RTMP and HTTP (Lighttpd) streaming, RSS, XSPF and ASX playlists, a wide range of flashvars (variables), an extensive javascript API and accessibility features.

Make sure you include the swfobject.js file on the page you wish to display your video on:

<%= javascript_include_tag 'swfobject' %>

Next, copy the mediaplayer.swf to public/flash/mediaplayer.swf

<div id="player">
  You need to have <%= link_to 'Flash Player', 'http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash' %> installed to display this video
</div>
 
<script type="text/javascript">
  var so = new SWFObject('/flash/mediaplayer.swf', 'mpl', '480', '360', '8');
  so.addParam('allowscriptaccess', 'always');
  so.addParam('allowfullscreen', 'true');
  so.addVariable('height', '360');
  so.addVariable('width', '480');
  so.addVariable('file', '<%= @video.source.url %>');
  so.write('player');
</script>

The contents of the div will be replaced with the flash player, if flash isn’t installed the user is shown a message with a link to download flash player. The <%= @video.source.url %> line will output the path to the flv video file.

There’s a setup wizard on the JW FLV Player site located here.

Final Note

You shouldn’t really be converting videos with the user request. You should be using a background worker to do it for you. I’ll be showing you how to do this in the next article in this series.

Give it a whirl. As far as I know it should work fine. I’ve tested it on my local host and it seems to work. Admittedly, there should be a lot more error checking and whatnot, but for a simple example I think it does the job.

If you have any suggestions, improvements etc that I could incorporate into this article then leave a comment and I’ll sort it out.

More In This Series

This is the first of a three part series covering how to convert videos using the marvellous FFMPEG library. Video conversion is a must have if you are planning on creating a social network site.

In this part I’ll be covering how to install FFMPEG on Ubuntu Hardy Heron (8.04).

Install FFMPEG Dependencing

First off, you need to download and install the dependency packages for FFMPEG. Without these, it’ll all go tits. So it’s a good thing to sort out.

sudo apt-get install build-essential subversion libx264-dev libdts-dev libswscale-dev liblame-dev libfaad2-dev libfaac-dev libxvidcore4-dev liba52-0.7.4 liba52-0.7.4-dev 

The lib* files help you to convert various video formats into flash videos, or which ever format you wish. Subversion is needed so you can download the FFMPEG source.

Check Out FFMPEG Source

Next, you need to checkout the current FFMPEG source from subversion. So let’s do that:

mkdir src
cd src
svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
cd ffmpeg

Bosh! We now have the FFMPEG source on our server. So far so good.

Compiling FFMPEG

Now we’re ready to compile to beast. Make sure you’re in the ffmpeg directory that we just downloaded. Then run the configure command:

./configure --enable-gpl --enable-libmp3lame --enable-libvorbis --enable-libtheora --enable-liba52 --enable-libdc1394 --enable-libgsm --enable-libfaad --enable-libfaac --enable-libxvid --enable-pthreads --enable-libx264 --enable-shared--enable-postproc --enable-avfilter-lavf --enable-swscale --enable-avfilter 

Then we’re ready to compile:

make
sudo make install

This will take ages. So don’t worry if it seems to be going on for a while. The last time I did it, it took about 5 minutes or so.

Hopefully, once that’s finished, you should be ready to rock.

Testing FFMPEG

Now, hold your breath and type:

ffmpeg -v

You should now get a load of blurb along the lines of:

jim@jim-ubuntu:~$ ffmpeg -v
FFmpeg version SVN-r13207, Copyright (c) 2000-2008 Fabrice Bellard, et al.
  configuration: --enable-gpl --enable-libvorbis --enable-libtheora --enable-liba52 --enable-libdc1394 --enable-libgsm --enable-libmp3lame --enable-libfaad --enable-libfaac --enable-libxvid --enable-pthreads --enable-libx264 --enable-shared --enable-swscale --enable-avfilter --enable-postproc --enable-avfilter-lavf
  libavutil version: 49.6.0
  libavcodec version: 51.57.0
  libavformat version: 52.13.0
  libavdevice version: 52.0.0
  libavfilter version: 0.0.0
  built on May 21 2008 11:55:20, gcc: 4.2.3 (Ubuntu 4.2.3-2ubuntu7)
ffmpeg: missing argument for option '-v'

If you don’t get anything similar to the above, then you’ve fucked it. Check the FFMPEG docs or post here and I’ll try and help you out.

More In This Series

I’m not going to cover how to actually code an entire social network site in rails as all social network sites vary in their functionality (and it’ll take too long). I will cover plugins and other things you might find useful though.

Quick Start

If you don’t really want to do the coding but want to get a site up and running and soon as possible, you may want to have a look at Lovd by Less by the guys over at Less Everything. Lovd by Less contains user signups, galleries, blogs, comments and various other things that you might want, so it’s a great starting block for your site.

Social Network Plugins

Here’s a list of plugins that I’ve found to be useful while coding my own social networking site:

Restful Authentication

RESTful Authentication is pretty much the defacto standard for user authentication in rails. It allows easily set up user signups, login functionality and email notifications. The plugin doesn’t set up thing’s like forgotten password functionality but there is a great tutorial over Rails Forum.

# To Install
ruby script/plugin source http://svn.techno-weenie.net/projects/plugins
ruby script/plugin install restful_authentication

Paperclip

Paperclip is a brilliant plugin by Jon Yurek over at ThoughtBot. Paperclip is used for managing file uploads and attaching the files to models. You can read more over at my article: Paperclip: Attaching Files in Rails.

# To Install
svn export https://svn.thoughtbot.com/plugins/paperclip/tags/rel_2-0-2
piston import https://svn.thoughtbot.com/plugins/paperclip/trunk

Will_paginate

Will paginate is a great plugin for allowing paging of your records. Paging is a pain in the ass, but will_paginate makes it easy as pie.

# To Install
ruby script/plugin install svn://errtheblog.com/svn/plugins/will_paginate

Acts_as_slugable

Acts_as_slugable takes the pain out of generating URL slugs. Everyone prefers meaningful URLs, so instead of showing a users page with ‘/users/231’, you can use ‘/users/jim-neath’. Nice.

# To Install
ruby script/plugin install http://code.dunae.ca/acts_as_slugable

White_list

White_list is yet another brilliant from Techno Weenie. The white_list helper will html encode all tags and strip all attributes that aren’t specifically allowed. It also strips href/src tags with invalid protocols, like javascript: especially. It does its best to counter any tricks that hackers may use, like throwing in unicode/ascii/hex values to get past the javascript: filters.

# To Install
ruby script/plugin install http://svn.techno-weenie.net/projects/plugins/white_list/

Acts_as_commentable

Acts_as_commentable allows you to add comments to your models. It takes care of all the polymorphic associations for you, which is nice.

# To Install
ruby script/plugin install http://juixe.com/svn/acts_as_commentable

ReCAPTCHA

Fucking captchas. Unfortunately a necessary evil. If you’re going to use captchas then you might as well help to digitalise books. The reCAPTCHA plugin utilises the reCAPTCHA service which digitalises books by making users input the text.

# To Install
ruby script/plugin install svn.ambethia.com/pub/rails/plugins/recaptcha/

Acts_as_taggable_on_steroids

Everybody loves tagging, surely? Tag pictures, videos, blog posts, whatever you want. Acts_as_taggable_on_steroids is a great plugin for allowing your users to tag their stuff. It allows tag clouds and all that web 2.0 jazz everyone seems to love.

# To Install
ruby script/plugin install http://svn.viney.net.nz/things/rails/plugins/acts_as_taggable_on_steroids

Exception Notifier

Exception Notifier is a must have. It emails you when your live application fails. No matter how much testing you do, no doubt there’s going to be a scenario where it fails and when that happens you want to know.

# To Install
ruby script/plugin install exception_notification

Throttler

This is one of my favourite plugins. Say your site get’s slashdotted of dugg and you end up with immense traffic, the main thing is to keep your site up and running. This is where throttler comes in. You can throttle certain actions on your site when your server load is above a certain level. So you could disable video uploads while your server load is above x to prevent your server from crumbling.

# To Install
ruby script/plugin install http://svn.kabisa.nl/rails/plugins/throttler

Backup_fu

You’ve been working on your social network site for months and finally the traffic is coming in and you have a decent user base. Then one day your server dies and you lose all your data. Woe is you. You should have backed up. Using Backup_fu you can automatically backup your database and files to Amazon S3.

# To Install
sudo gem install aws-s3
ruby script/plugin install http://backup-fu.googlecode.com/svn/backup_fu/

Fischy Friends

Fischy_friends is a plugin by Daniel Fischer. It’s a great starting point for a friends system. I’ve used it on a couple of my own projects and it’s worked great for me.

Other Useful Tools

SWFUpload

I love SWFUpload. It uses a small flash file to allow users to upload multiple files at once. The front end is completely open and coded in javascript so you can customise it how you like. You can see the demos here.

Download: http://swfupload.googlecode.com/files/SWFUpload%20v2.0.2.Release.zip

TinyMCE Text Editor

TinyMCE is WYSIWYG editor coded entirely in javascript. It’s useful for the less techno savvy of your users (which will no doubt be most). There’s a whole load of plugins available for the editor so it’s highly extensible.

Download: http://prdownloads.sourceforge.net/tinymce/tinymce_3_0_7.zip?download

FFMPEG/Mencoder

FFMPEG is a command line utility to convert various formats of video into other formats. The main use you’ll want to use this for is to convert videos into flv files for use with a flash video player.

JW FLV Media Player

The JW FLV Media Player (built with Adobe’s Flash) is an easy and flexible way to add video and audio to your website. It supports playback of any format the Adobe Flash Player can handle (FLV, but also MP3, H264, SWF, JPG, PNG and GIF). It also supports RTMP and HTTP (Lighttpd) streaming, RSS, XSPF and ASX playlists, a wide range of flashvars (variables), an extensive javascript API and accessibility features.

Rails Hosting

Once you’ve got your wonderful social network finished, you’re going to want somewhere to host the beast.

I highly recommend checking out Brightbox for all your hosting needs. They offer affordable servers complete with Five Runs.

I am available for freelance work! Click here to email me.

Jim Neath is a Freelance Ruby on Rails & Facebook app developer from Manchester, UK, currently working for Engine Yard.