Server-Side FFmpeg Converter: Flash, ARP, & SWFStudio

Preface

As part of my Flash & Flex speech I’ve been giving throughout the year, I wanted to create a real-world app where you would want utilize Flash & Flex together. Back in late July, I started creating a YouTube clone. There was a good blog entry posted awhile ago on this. The goal was to create a really rich front-end in Flex that pretty much required the use of Flash. I purchased a design from Templatemonster.com that looked impossible to do in Flex, and set out to implement it.

Introduction

The one thing you need for a YouTube clone is a server-side tier that can upload videos of various formats, and convert them to FLV’s. After receiving the cliche “You could of searched on Google instead of asking that question” on FFMPEG’s developer list, I realized I wasn’t going to get any help from the community on finding a scriptable executable, at least in my aggressive time frame, especially for Windows. Stefan from the chattyfig Flashcom list hooked me up with a Windows compiled ffmpeg.exe. I wanted to build the whole back-end in PHP, though, since although I’d prefer to use Ruby, I don’t really have the time with this specific project so had to go with what I know. I spent 3 days trying to get the FFmpeg php module to compile as a PHP add in. I even went so far as to try to learn MAKE and friends.

On the 4th day, exasperated, I gave up and took drastic action. I decided to create the back-end converter in Flash. I’ve only once before created a server program in Flash. Flash is typically used on the client as a front end technology, in a web browser, or as rich desktop apps. There was one time in the past, however, where it was perfect as a server application. Macromedia (now Adobe) had a program called Central. It was their first foray onto the desktop client world. In Central 1.5, they incorporated an API that allowed you to access AOL instant messenger & ICQ messaging capabilities via code. It was pretty neat. I couldn’t for the life of me figure out a good use for it on the client, though. Instead, I created a bot server. The bot, called FEEDBot, allowed people to IM it. If you were a buddy of FEEDBot, you could then ask it to monitor your favorite blogs. It’d check every hour, and if a feed was updated, it’d IM you with a link to the blog and an excerpt. I’d basically run the Central program, leave my computer running so it’d act like a server.

I did a few tests and found that via SWFStudio, I could talk to FFMPEG via Flash 8 pretty well. I didn’t have a legal license of Zinc back then, and didn’t want to create it in Flex 2/ActionScript 3 because for a quick and dirty server app, strong-typing was too slow to develop in. Flash 8 was perfect. So, I proceeded to create a video converter for the back-end in Flash 8, SWFStudio, and Flashcom. Flashcom allowed the client to convert video and get real-time updates. It also allowed the EXE to act as a service so to speak, so multiple clients could all ask Flashcom to convert videos after it uploaded them, and the EXE would then tell FFMPEG to churn away.

How does it work?

Through a few technologies and steps.

messages.gif

A client will upload a video. This video is uploaded via PHP. Upon a successful upload, the client then tells Flashcom to convert the video. Flashcom then tells the VideoConverter application, which also exists on the same server as PHP, to start converting the video. The VideoConverter then tells FFmpeg to convert the video to FLV with certain parameters. When FFmpeg is done, it tells the VideoConverter. The VideoConverter then tells Flashcom that it is done with that particular video. Flashcom then tells the client that it is done, and the client can now play the FLV via Flashcom.

flow.gif

Since the above process utilizes Flashcom, this allows the client to get real-time updates as to the process, unlike the “wait for frikin’ ever for a respone” one gets on YouTube. Additionally, you can use the same server to play back the video. Obviously having the same computer converting video via FFmpeg, running a Flashcom messaging server, as well as a Flashcom video serving server won’t scale. That wasn’t the point; the point was to get a proof of concept application up and running. Naturally, I bit off more than I could chew. The video conversion part works, but the actual client portion of the application is taking longer than expected, mainly because of my full-time consulting work; I’m traveling a lot, thus don’t really have enough time to devote to finishing it.

However, since the server portion DOES work, I figured I’d release the code in case it might benefit someone.

Points of Interest

One particular architecture challenge I had with the server portion is the same problem I’ve had with Flex Data Services and Cairngorm 2 for Flex 2. Cairngorm, as well as ARP, do not natively support a methodology for doing server push. They are built around a request / response model. This means that the client initiates a request and the server responds. The entire framework is built around this concept. Therefore, there is no real model built around the server pushing a message to the client, and the client acting upon it.

So, I came up with a concept an Observer. My boss & architect on a previous project, Thomas Burleson, helped me hash out the cleanest way to implement it into Cairngorm. I used that same 10 minute conversation to do it in this implementation via ARP since both frameworks are very similar, and Cairngorm 2 won’t work in Flash 8.

observer_pattern.gif

This Observer class basically listens for events coming from the server in a push fashion, in this case, utilizing Flash Media Server which supports a real-time binary socket connection with the Flash Player. This helps in 2 ways.

First, Flash Player 9 doesn’t seem to support the old slash syntax that has been in Flash for years, at least with regards to how the old Flashcom server-side framework expects it to. A lot of my server-side code expects this to work, so I had to find a way that didn’t require a major rewrite of the existing Flashcom server-side component framework since I like how it works and didn’t have time to invent a new one. The client to server method calls work, but the server to client ones did not. Therefore, I merely pass in the namespace string and have the Observer parse it to something useful. This requires a very minute change in the ASC code on the Flashcom server; instead of passing a namespace as a method call, you merely pass the method name as the first call, and the namespace as the first parameter.

Second, I can segregate the server push, the part that doesn’t fit well into Cairngorm/ARP, into it’s own class. This base class is extended by business specific classes. For the VideoConverter, I extend this Observer class, and act on specific messages by dispatching events. The Observer doesn’t actually respond to the server, nor does it send messages. Instead, it dispatches events like normal. This allows Cairngorm/ARP Commands to determine if there is a need to send a message to the Flashcom server in the classic request/response way. Since I can encapsulate the fact I’m talking to a real-time server in the Business Delegates, Cairngorm/ARP work great!

One minor detail is that you can, via a Command, turn the Observer on and off. Additionally, I’ve hacked ARP to have a singleton event dispatcher much like Cairngorm 2 does.

SWFStudio API Parameters

Another thing is that SWFStudio uses vanilla (un-typed) Objects as parameters to it’s methods. I despise this. While I enjoy the ability to get away some loosely typed things in Flash, those particular cases make it extremely challenging to debug. So, for the relevant methods, I created strongly typed ValueObjects so I can ensure all my calls to SWFStudio are correct; if something messes up, I clearly know where to look for the problem. It makes unit testing the SWFStudio to FFmpeg calls easier & quicker.

I’ve only implemented one shell method and one file copy method for SWFStudio but because I used ARP, it’ll be easy to add more as time goes on. Hopefully the Northcode peeps could uh… you know… do it themselves, hehe! I know most Flash devs don’t really strongly type everything, so I highly doubt it’s a common enough use case to support development effort on. Since they DO support Flex 2, I know they care, but probably not enough for Flash 8 and below.

Anyway, here’s the code, hope it is helpful/beneficial to you in some way.

Video Converter – Source ZIP

7 Replies to “Server-Side FFmpeg Converter: Flash, ARP, & SWFStudio”

  1. This is an amazing post. Thanks for all the details and rich information. The server side Flash implemented using Central is particularly interesting to me. Wish this give Adobe a good dosage of inspiration. If Flash can run virtually within every browser, why not every OS, especially as a server side technology.

  2. wow I don’t think I understood half of what you were doing but no doubt it rocks :-)
    Not sure if this helps Jesse or anyoen else but I built a little snapshotter app (using that very same ffmpeg executable) which also leverages Flashcom and a few lines of CF to produce a jpg image from a captured flv.
    totally different to what Jesse’s doing but nevertheless somehow related, if only for ideas:
    http://www.flashcomguru.com/index.cfm/2006/7/31/snapshottersources

    Stefan

  3. Jesse.

    Great article.

    Just a few questions to clarify things:

    1. So in regards to compiling the VideoConverter.swf in SWFStudio, I take it you are using v3 (.2?). What plugin modules are you including? Is it just filesys to do the file copy?

    2. Was there a specific build of FFPMEG you are using? I am currently using a windows build : ffmpeg.rev5498.

    3. You have an FLV_CONVERSION_BAT constant. Is the batch file actually getting used? If so what is supposed to be in it?

  4. 1. Version 3.2 Build 136. Yep, just filesys.

    2. ffmpeg version prints out:

    ffmpeg version
    ffmpeg version 0.4.9-pre1, build 4751, Copyright (c) 2000-2004 Fabrice Bellard
      configuration:  --enable-memalign-hack --enable-mp3lame --enable-mingw32 --ext
    ra-cflags=-I/local/include --extra-ldflags=-L/local/lib --enable-amr_nb
      built on Mar 29 2005 07:26:02, gcc: 3.2.3 (mingw special 20030504-1)

    3. The bat deletes the previous log, previous flv, and then calls ffmpeg with the parameters as well as logging the output to a text field. I thought about writing a parser for the log to get better error messages, but… uh.. that’s a lot of work for little gain.

    del %1.txt
    del %1.flv
    ffmpeg.exe -i %1.mpg %1.flv > %1.txt 2

    Props to Thomas Burleson for getting that dang bat file format logging syntax correct!

  5. Hi Jesse,

    This is really cool. Can you just write down steps to use your codes or check it out how your code is working. I tried to setup things but no setup instruction from your side lead me no where to check your example/code in action.

    I guess its abs. cool and i really want to try it out.

Comments are closed.