Blog on Ruby web and mobile applications development

We're hiring!

We are hiring now! If you would like to join our team and work on exciting Ruby on Rails projects read on.

Your responsibilities will include:

  • Ruby programming (using Rails and other web frameworks)
  • JavaScript programming (using jQuery, Dojo and Prototype)
  • HTML an CSS coding
  • writing tests (with RSpec and Cucumber)
  • using relational and document-oriented databases
  • working using Scrum techniques

Ability to work most of the time from our office in Białystok, Poland is a must.

Ideal candidate is independent programmer, but also a good team player, who enjoys working with cutting-edge technologies and exciting web applications. If you don’t program in your free time or you are not excited about ruby programming at all don’t bother applying! We require passion.

To apply, send your CV to: hubert.lepicki@amberbit.com and wojciech.piekutowski@amberbit.com

more…

Posted by Hubert Łępicki on 25 Nov 2009

Ruby FLV pseudostreaming implemented using Sinatra and Rack::Evil (useful for Rails too!)

There are many ways you could implement FLV video streaming. The most “proper” way to do it is to use RTMP (Flash Media) Server, which you can purchase directly from Adobe. A few cheaper/free/open source alternatives exist. For me, most promissing one is Mammoth, but it’s still in early stage of development. However, most popular alternative is Red5, however I didn’t find it either easy to configure or being reliable at serving files. Some big guys are using it, but it takes time and experience to set it up and maintain properly.

Here comes pseudostreaming

FLV pseudostreaming is a technique that allows you to simulate FLV streaming, without use of RTMP protocol. Most popular player that supports pseudostreaming if Flowplayer, and they also give you nice overview of this method on their site.

Implementations for pseudostreaming exist for Ngnix, Lighttpd, Apache or PHP, and it’s probably best if you use ones written in C (fastest). However, when you can’t use Lighttpd or need to integrate FLV streaming directly into your Ruby apps, you can use mine solution.

How it works?

Pseudostreaming of FLV files is possible when you insert special frame index into file header. Most popular tool to do it is flvtool2, and yes - it’s written in Ruby and available as ruby gem!

$ gem install flvtool2

To append FLV data to your movie file, use command:

$ flvtool2 -U video_file.flv

When player starts to buffer video file via standard HTTP protocol, first thing send out is metadata that sits in file header, and pseudostreaming is possible.

But applications that serve FLV files with pseudostreaming support, must respond to specified URI scheme, that accepts “start=XXX” parameter to make it work. XXX is just an offset in bytes from beginning of file, so our application must seek to given byte and start sending output from there. It is implemented almost identical in PHP, or C (in both Ngnix and Lighttpd), and we are going to do it in Ruby.

For example, if we seek to the middle of video, Flowplayer calculates that position should be, say 2343443 bytes from start, and sends request to: http://myserver.com/myvideofile.flv?start=2343443. We need to output file from this position. Dead easy.

Not quite dead easy

There is one problem with Ruby applications that use Rack (Rails included) - how do we actually stream a file? We could use sendfile or senddata methods from within Rails, but Rack architecture forces our file to be buffered in memory, which is something we don’t want to do for 1.5GB movies.

To work this around, we will use Rack::Evil module that allows us to throw and catch custom object that will be processed as HTTP response.

First, let’s get Rack::Evil, which is part of rack-contrib:

$ gem install rack-contrib

In your config.ru file or config/environment.rb you need to enable Rack::Evil:

require 'rack/contrib'
...                   
use Rack::Evil        
...

Now, in your application, in place where you need to output a file, you must construct object that responds to “each” method. You will throw this object and Rack::Evil will catch it, and call “each” on it. Each content that yields from this method, will be sent directly to user. If we implement actual file reading inside “each” method - we avoid loading whole file to memory.

...
 def each
   if @start_pos > 0
     yield "FLV\x01\x01\x00\x00\x00\x09\x00\x00\x00\x09" # If we are not starting from beggining
                                                         # we must prepend FLV header to output 
     @start_pos = 0                                                                             
   end                                                                                          

   begin (chunk = @file.read(4*1024)) # Go and experiment with best buffer size for you         
     yield chunk                                                                                
   end while chunk.size == 4*1024                                                               
 end                                                                                            
...

Easy! For more information look into application.rb and config.ru files! Have fun!

Using this example

First clone repository from Github:

$ git clone git://github.com/hubertlepicki/sinatra-flv-streaming-example.git sinatra_flv_streaming_example
$ cd sinatra_flv_streaming_example

Now, get dependencies and some Rack-compatible server (I’ll use Thin).

$ gem install rack rack-contrib thin

Start the server and visit demo page:

$ thin -C config.yml -p 4567 start

Demo page is located on http://localhost:4567/index.html. Please note that port 4567 is hardcoded in index.html file soyou must use it or change index.html file.

Notes

This is just an example how to use it, you shouldn’t use this code in production but develop your own solution based on this ideas.

You must not use Rack modules like mine responseassembler that iterates on response object and process it to one string - this way you’ll end up with loading all video file to memory at once.

Demonstration on how to set up Flowplayer to use pseudostreaming is in file index.html.

Flowplayer binaries distributed with this source code are licensed under GPLv3, and you should read their licensing policy before using it on your site read more.

Links

more…

Posted by Hubert Łępicki on 15 Apr 2009

Introduction to Rack middleware

Rack middleware is hot topic these days and anyone who is reading Ruby-related blog sites must have heard about it already. However, if you didn’t, here’s short quote from Rack site:

Rack provides an minimal interface between webservers supporting Ruby and Ruby frameworks.

During last couple of years, Rack has became de facto standard in Ruby web development world, providing unified and and simple interface for frameworks creators. Today, Ruby on Rails, Ramaze, Sinatra and many others use it by default to talk to web servers, including Mongrel, Thin or Apache via Passenger.

more…

Posted by Hubert Łępicki on 04 Apr 2009

Rails 2.3 - best release ever?

I have been using Ruby on Rails since the 1.1 release, and there have been more and less successful releases since. Rails 1.2 was amazing and brought us REST - most of us never looked back. However, the 1.2 series was still very buggy and was breaking backward compatibility several times between minor releases.

I wasn’t too much excited about Rails 2.0, particularly because it wasn’t backward-compatible and most of plugins had to wait for several months to be rewritten to work with 2.0. However, since then, Rails is evolving quite nicely and version 2.3 seems to be best you could ever get in Ruby web applications development. And here is why:

  • nested model mass-assignment significantly simplifies building complicated forms. At the time of writing, it’s still a bit buggy when it comes to validation (in RC1), but that is about to change before final release.

  • http digest authentication which is great news for everyone who build web services and need a bit more security in place.

  • metal, using which we can finally bypass routing monster and save some milliseconds for “mission-critical” requests.

  • overall performance boost, as pointed out by one of my friends. I didn’t see any benchmarks yet but overall feeling, especially with environment startup and running rake tasks is astonishing.

Now, let’s just wait for 3.0 revolution to come…

more…

Posted by Hubert Łępicki on 15 Mar 2009