Flivver: Building a SWF to FLV server application
Working in the ‘media sharing’ space, I’ve come across the need for a SWF to FLV application (swf2flv). There are a number of products out there, and some oldish Python scripts, but none of them really satisfied my needs. Some of the products out there are by Sothink and Scout. I needed something that could be called from a command line/console, and Scout does have a version that does that, though it costs $1000ish for a single server license. But it didn’t have one key feature I needed, so I started to look into what it would take to build my own. Hence Flivver (think FLV, not Aldous Huxley).
Here are the basic things that Flivver needed, with the one extra feature that I haven’t seen in any other SWF2FLV app:
- Process a SWF without any human interaction from a server: This won’t work with swf’s that require button presses, but for my needs I needed to take an audio/visual playlist created by a user and have it converted into something that user could possibly upload to YouTube.
- Video/Visual capture: Capture everything that happened in the FLV, including bitmap manipulations, and text, effects and transitions. While it wouldn’t be too hard to append a bunch of video files together, once you start adding affects like ‘Black & White’ to the video, you have to really consider how you are going to integrate you playlist with some pretty serious Adobe Premiere/iMovie type application to replicate it in a standalone video file.
- Audio Capture: In the same way as video, you need to be able to capture the audio as it occurs in the playlist, with transitions and effects.
- Be able to assign a playlist id to the SWF, so it can load the playlist from the internet. One of the key things missing in all of the SWF2FLV and SWF2AVI apps is the ability to set flashvars or otherwise interact with the SWF in any meaningful way. Specifically for my needs, I have to load the playlist from a web server application that stores the playlists created by the users. As far as all of the other server/console style converters, they don’t support any way of interacting with the swf being processed.
So as any good hacker would, I started searching google for info on how to do the various pieces: Video Capture, Audio Capture, Hosting Flash in an Application, & Talking to Flash from a Hosting Application. I found a lot of good information, but it is all about weeding out the bad. The first decision I made was that I was going to have to use the Windows environment for the application, simply because I am more familiar with it as far as GUI programming goes, and there was a lot more information on screen capture out there for it, as well as using video card acceleration to speed up the process. I had done some work with xine back in the day (dealing with the Via EPIA Hardware a few years ago, though nothing official), and just felt that for my needs the effort would have been to great to get a working version on linux. Also, in general our production servers didn’t have X11 running or sound cards anyway, so we needed our own GUI server for everything to work.
So then the question was whether to do it in C++ or C#. Although there are more examples in C++, I decided to go with C#, because I wanted to try something new. So that decision helped me narrow down my google searches.
First I needed to find C# versions of the DirectShow SDK, with examples, as I really didn’t want to learn all the ins and outs of dealing with DirectShow filters & COM. I finally came across the DirectX.Capture demo at CodeProject, which had about 50% of what I needed, and was the scariest part for me. The next piece I needed was a DirectShow Filter that did screen capture. I found a couple of those: UScreenCapture and VH Screen Capture filters. VH Screen Capture has a few more options I believe, but for now I am using UScreenCapture. So another 25% of the project down. Next I needed a way to capture the audio that was being played through the sound card. This is easily accomplished by setting the Audio source to ‘Stereo Mix’, and capturing with a reasonable volume at 44khz, 16 bit stereo. (NOTE TO LAPTOP/MACBOOK BOOT CAMP USERS: You may need to download some hacked SigmaTel HD Audio drivers or make some changes to your driver installation files to get ‘Stereo Mix’ to be an option for your Volume Mixer. Do some googling for “Sigmatel MacBook Stereo Mix”.) Finally, I needed a way to embed Flash into my C# application in a way that allowed me to call Flash methods. I found the instructions to this at this site. Note: that if you are using Visual Studio 2005 or newer, you will need to download a Flash ActiveX COM definition file as Microsoft stopped shipping one after VS2k3. You can find information here.
One challenge I wasn’t able to solve is having the output be in FLV format directly form the C# app. I specifically wanted to output On2 VP6 format rather than Sorenson, as it is much better quality at the same or even lower bitrates. I couldn’t find any free DirectShow filters for this, and the one’s from On2 cost $1000 per server again. The way to work around this is to use MPlayer’s MEncoder with the VP6.2 codec/filter installed (which even works on Linux although you need to create the settings vcf file on Windows). So Flivver is a bit of a misnomer, since it actually outputs AVI in xvid/mp3 formats, which is then converted by mencoder.
Now that I had all of my major technological hurdles taken care of, it was just a matter of integrating them into a single application. The basics pieces were:
- Add command line handling to the application so it could have information passed in from the server. Specifically, this app is called by a Ruby on Rails library. The app receives a post from the production Rails servers telling it which playlist needs to be processed, and this is then passed in on the command line.
- Get rid of any of the DirectX.Capture settings and UI that we don’t need. We know which specific filters we want to use, so we don’t need to deal with all of the selection menus, etc.
- Add some timing handling. There is no way I could tell to discover automatically the state of the SWF being loaded into the ActiveX control. The Flash onReadyStateChange didn’t really give me anything useful. Because I had access to the code for the SWF I wished to capture, I was able to add some communication between the the SWF and the C# app, so that things could be coordinated, like when to start capturing and when to end.
That’s basically it. I have created a SourceForge project for Flivver, though there is nothing there at the moment. I am still finishing up some of the integration details, and changing things from hard-coded stuff I needed for my particular usage to more flexible settings/command line based options. While there may be limited usage for something like this, I think it is still a cool little project and maybe will help someone else who has to solve a similar challenge. I’ve picked an MIT license for release, though I still need to go through all of the code I cribbed off of and see what the details for those licenses are, so that may change. At the very least you can use my instructions here to get going on your own if need be.
Sadly, flivver.com is a parked domain as a misspelling of ‘flower’.
And finally, thanks to my peeps at UGENmedia for paying my bills and encouraging me to put this out there for others.
Let me know what you think!
Trackbacks
Use the following link to trackback from your own site:
http://blog.slaingod.com/trackbacks?article_id=flivver-building-a-swf-to-flv-server-application&day=17&month=01&year=2008
Hi there,
I am trying to write an Online Multimedia Editor. The funny thing, my story is exactly yours until about half of your text. And this is where I am now!
I Started only with Java Knowhedge, with not even knowing a single line of flash or someth. So I first had to learn flash and AS which took about 1 month to perform everything what I wanted and press it into some object oriented data structure. I was about to start writing my own swf2flv encoder now. Met some 1500$ per CPU licences just like u in the internet which definitely exceeded my budget :D … So I was thinking and hoping I could help and support you in any possible way. Please contact me and let me know how I can help u :)