Topic: Streaming Flash Video via Ruby

Hey Everyone -

I've been doing some googling here and wanted to ask if anyone's done this before - streamed flash video (*.flv) via Ruby?

Basically, I'm doing some R&D on a possible future project to use RoR for the site/db access, and Flash to stream video.  Thing is, the user needs to be authorized for the video, and it needs to be streamed so it isn't cached on the client-end (for copyright protection purposes - yeah I hate it too, but gotta do it).

I've seen one tutorial using Ming to do that, but I'd prefer something that has a separate server-side application, and separate client-side application built in Flash, so I have more control over the look and feel of the application, as well as can embed other interesting things in there if I want.

I've taken a look at Red5 (http://osflash.org/red5), but seeing as it's in Java, I'm not too keen on working with it.

Part of the reason I want to do this in Ruby is obviously so I can work with it through Rails, -and- so I can use Ruby to fetch videos from Amazon S3.  That's where I'd like to store them (privately of course), then use ruby to fetch the video and re-stream the data to the Flash player.

Complex, I know.  Anyone have any thoughts on if this has been done, and if not, how it might be accomplished?

Thanks wink

Re: Streaming Flash Video via Ruby

OK, after some more research and a few tweaks, I've made a simple (very simple) ruby script work inside the rails environment.  Here's the existing code:

class StreamController < ApplicationController
  def index
    # Open the FLV.
    @file = File.open(File.join(RAILS_ROOT, "flv", "golfers.flv"))
   
    # Binary
    @bin = @file.read
   
    # Send data.
    send_data (@bin, :type => 'application/x-flv', :filename => 'golfers.flv', :disposition => 'attachment')
  end
end

Basically, going to http://localhost:3000/stream will give you the video.

(Note for cut&paste: YMMV.  This is a quick test hack to see if the concept is viable, you -will- have to change that code.)

My FLA code:

var nc:NetConnection = new NetConnection();
nc.connect(null);

var ns:NetStream = new NetStream(nc);

tvid.attachVideo(ns);
ns.setBufferTime(2);

statusID = setInterval(videoStatus, 200);

ns.onStatus = function(info) {
   
    trace(info.code);   
    if(info.code == "NetStream.Buffer.Full") {
        bufferClip._visible = false;       
        ending = false;
       
        clearInterval( statusID );
        statusID = setInterval(videoStatus, 200);
    }
    if(info.code == "NetStream.Buffer.Empty") {
        if ( !ending ) {
            bufferClip._visible = true;
        }
    }
    if(info.code == "NetStream.Play.Stop") {
        bufferClip._visible = false;
        //ending = true;
    }
    if(info.code == "NetStream.Play.Start") {
        ending = false;
    }
    if(info.code == "NetStream.Buffer.Flush") {
        ending = true;
    }
}

//Play it
ns.play("http://localhost:3000/stream");


Basically all that does is look at the instance on the first frame (only frame) of the move called "tvid" which is an instance of a Video object, and attach a NetStream to it, then plays the video called from this area.

Now as far as I can tell, when Flash Player uses NetStream to play a video, it does NOT cache it client side.  I don't know whether or not it's RTMP dependent - can anyone shed some light on this?

I haven't implemented seeking capability yet, or a scrubber.  That's a bit more complex than I'm able to do right now.  Luckily I've found a PHP version from www.flashcomguru.com.  Here's the code:

<?
/*/
security improved by by TRUI
www.trui.net

Originally posted at www.flashcomguru.com

//*/


//full path to dir with video.
$path = 'C:/.../clips/';


$seekat = $_GET["position"];
$filename = htmlspecialchars($_GET["file"]);
$ext=strrchr($filename, ".");
$file = $path . $filename;


if((file_exists($file)) && ($ext==".flv") && (strlen($filename)>2) && (!eregi(basename($_SERVER['PHP_SELF']), $filename)) && (ereg('^[^./][^/]*$', $filename)))
{
        header("Content-Type: video/x-flv");
        if($seekat != 0) {
                print("FLV");
                print(pack('C', 1 ));
                print(pack('C', 1 ));
                print(pack('N', 9 ));
                print(pack('N', 9 ));
        }
        $fh = fopen($file, "rb");
        fseek($fh, $seekat);
        while (!feof($fh)) {
          print (fread($fh, filesize($file)));
        }
        fclose($fh);
}
    else
{
        print("ERORR: The file does not exist"); }
?>


Now what's interesting here is how they handle a seek.  The scrubber in the included FLA sends an http GET request to the script, which looks for an integer (as a percentage of the total length of the video, I guess), and in turn, the script returns - apparently - that part of the video.  That's what I'm having a hard time with, is how this pack() function works.

Now I know Ruby has a pack() method, as part of the Array class.  What I'm not sure how to do is get a "Ruby equivalent" of this PHP script - a full port, if you will.

Any Ruby pros wanna help me out here? smile

Re: Streaming Flash Video via Ruby

It's quite a long time ago since you posted this "solution". What about the speed? Is ist mostly like RED5 ?