Using the AIR 2.0 Native Process API to control MPlayer

Adobe AIR has been a big step forward in creating cross-platform applications. Unfortunately, there are still some big gotchas. For us at our biggest issue are the lack of media playback options. Our AIR-based media center, cloudskipper, can play any media Flash supports, which has gotten better since Adobe added H.264 support in Flash 9.0.124, but still leaves out a lot (XVID, AAC audio supporrt, etc). This is particularly true with desktop media where there dozens of different codecs.

Luckily, a few weeks ago Adobe released the beta of AIR 2.0 and with that the NativeProcess API. The NativeProcess API essentially allows you to invoke any native process similar to how you would via the command line but in your AIR app. You then communicate with that process via STDIN and STDOUT. Jeff Swartz over at the Adobe Developer Connection wrote nice introduction to this, which I highly recommend.

Can we use this new capability to do something a little more interesting than “echotest”, like say play a video HD video encoded with XVID? I’m happy to say that with some caveats the answer is yes =)

Media Player Choice

The first thing we need to play media is well… a media player. Not just any media player, a media player with a few specific requirements:

  1. Plays many different media types (this probably means it has various media codecs packaged with it)
  2. Cross platform (mac, linux, windows)
  3. Can be invoked via the command line
  4. Can receive input and send out via STDIN/STDOUT
  5. Open source (distribution limitations and the inability to make modifications are show stoppers for commercial software)

From my research the only two media players I could find that meet both these requirements are VLC and MPlayer. Both MPlayer and VLC can be invoked via the command line. They also both have modes where they work with STDIN/STDOUT, “remote control” mode (use the argument -Irc) in VLC and “slave” mode (use the argument -slave) in MPlayer. You can find about VLC’s remote control mode here and MPlayer’s slave mode here.

VLC seems to actually be able to play a wider array of media, but the choice for me came down to what will work with AIR. Unfortunately, for some reason I just couldn’t get AIR to play nice with VLC in remote control mode. AIR seems to ignore the -Irc argument and just open up VLC. Maybe, I’m missing something with VLC, but I was able to get MPlayer to open up just fine in slave mode so that made my choice moving forward pretty easy.

MPlayer Installation

The easiest way to install MPlayer on OS X is via macports. Just open up the terminal and type the command “sudo port install mplayer-devel”. Now sit back make yourself a cup of coffee, maybe have lunch or go for a run around the block while macports compiles and installs mplayer and all of it’s dependencies. Note we’re using mplayer-devel, which I assume is the “latest” development release. This has some fixes to make MPlayer work on Snow Leopard and generally seems pretty stable (you can still install “mplayer” if you’re on Leopard or below). When MPlayer is done compiling/installing do a mplayer -v to make sure everything installed correctly. Then execute “which mplayer” and not the location (it will most likely be /opt/local/bin/mplayer). Note MPlayer’s location because we’re going to need this later.

Windows seems to be a bit tricker. MPlayer HQ seems to have both windows soure and binaries though so I’d recommend heading over there. I’d love to hear some first hand reports on this.

If your on linux I think app-get should work similiarly to macports, but I haven’t tested this.

AIR 2 SDK Installaton

You’re going to need to install the AIR 2 SDK to take advantage of the NativeProcess API. Luckily, I just posted a guide on how to do this =) You can check that out here: Installing the AIR 2 SDK on OS X (this is be pretty similiar for linux and windows).

The Code

Ok, finally, to the code! I’m not going to go through everything line by line here,  but I will go over the key parts.

Update Application Descriptor
Extended desktop mode needs to be enabled for NativeProccess support.


Set the location of mplayer

protected const MAC_MPLAYER_PATH:String = '/opt/local/bin/mplayer';
protected const WIN_MPLAYER_PATH:String = 'c:\\path\\to\\mplayer';

(Sorry, didn’t add linux, but it should be fairly trivial)

Create the arguments

The three arguments we’re passing to MPlayer are:

  1. slave – switches MPlayer to use STDIN/STDOUT, making communication with AIR possible. You can find more information about slave mode here.
  2. quiet – makes output less verbose. this speeds things up a bit and make STDOUT parasing more reliable. Read more on MPlayer’s man page.
  3. idle – supposed to keep mplayer open when a file finishes playing, but doesn’t seem to work though.

Note, file here is the platform specific mplayer executable.

var nativeProcessStartupInfo:NativeProcessStartupInfo =  new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = file;
var args:Vector.<String> = new Vector.<String>();
nativeProcessStartupInfo.arguments = args;

Send commands to STDIN

This is pretty straight forward. I wrote a little wrapper called “cmd” to handle error checking, but really all it does is write to the process’s standard input.

public function cmd(cmdStr:String):void
  if(process && process.running){
    process.standardInput.writeUTFBytes(cmdStr + "\n");

Receive commands from STDOUT and parse

MPlayer sends back information in a standard format. This means we just have to parse out certain strings to get the information we want. In this case we’re looking for the video’s position and length to update the scrubber.

process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
protected function onOutputData(event:ProgressEvent):void
  var output:String = process.standardOutput.readUTFBytes(process.standardOutput.bytesAvailable);
  outputText += output;
  textReceived.verticalScrollPosition = textReceived.maxVerticalScrollPosition;
  var arr:Array;
  if(output.indexOf('ANS_TIME_POSITION') > -1){
    arr = output.split('ANS_TIME_POSITION=');
    vidPosition = parseFloat(arr[1]);
  if(output.indexOf('ANS_LENGTH') > -1){
    arr = output.split('ANS_LENGTH=');
    vidLength = parseFloat(arr[1]);

Scrubbing is a little tricker because we have to worry about states (paused or playing). I also added the volume hack you see people because issuing all commands unpauses MPlayer and causes an audible pop.

protected function onScrub(event:SliderEvent):void
  if(!playing) {
    // cmd('volume 0 1');
    cmd('mute 1');
  cmd('seek '+ (event.currentTarget as HSlider).value + ' 2');
  if(!playing) {

Download source:

AIRmplayer.mxml and AIRmplayer-app.mxml

Playing Audio

From my tests MPlayer actually performs very well with audio. Not only does it seem to play mp3, m4a, ogg, flac, it also handles large files MUCH better than flash and even iTunes. There also aren’t the same windowing issues you have with video (except for m4a’s with visual content).

Issues and Final Thoughts

This is by no means a complete solution. There are several issues that need to be addressed before I would consider it viable in production environment:

  1. windowing – communicating between the MPlayer window and the AIR app is challenge if you want to integrate video playback
  2. separate app – as stands MPlayer opens up it’s dock icon (on os x) when it opens up a new movie window
  3. distribution – it will be tricky to compile mplayer with all dependencies localized in order to distribute it as native installer

Challenges aside, I think this still serves as an interesting demo of the possibilities of what we can now do with AIR 2 and the NativeProcess API.


  • Gabesz84

    great demo!
    You can disable showing mplayer in the taskbar, ba giving mplayer a window handle it can use to display the picture (-wid option). But here comes the problem: How can i determine from inside the air application, the applications own window handle?
    The other problem is, that in this way mplayer uses the bounds of the given window, so i can not position it inside an air app. The solution coul be, to use a sub component in air that has his own window handle, but as long as i know, this is not possible, or am i wrong?

  • squep

    I think you missed a space in the -Irc command for VLC.
    It's -I rc and not -Irc
    hope that helps.

  • squep

    the “–rc-fake-tty” switch is also required

  • Blake Eaton

    For the VLC app did you pass in arguments using arguments property of NativeProcessStartupInfo?


    var v:Vector.<String>;
    v = new Vector.<String>();


    var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
    nativeProcessStartupInfo.executable = file;
    nativeProcessStartupInfo.arguments = v;

    That should work

  • squep


    yes i used:

    var processArgs:Vector.<String> = new Vector.<String>();
    processArgs[0] = “-v”;
    processArgs[1] = “-I rc”;
    processArgs[2] = “–rc-fake-tty”;
    processArgs[3] = m_inputPathVideo;

    nativeProcessStartupInfo.arguments = processArgs;
    vlcProcess = new NativeProcess();

    then you should be able to control vlc over the standardInput:

    hope that helps

  • Michael Christoff

    Thanks for clearing this up squep. I'm going to have to give vlc a try again.

  • Michael Christoff

    You hit the nail on the head. The challenge is that you have no idea what the window id is if you were going to attempt the wid strategy. The other issue is that I'm not sure if the wid flag would even work in cocoa because it says in the mplayer docs it only works with x11, directx or opengl.

  • Gabesz84

    well, i found out how to get a window handle under linux: you can use the xwininfo -int -name <windowname> shell command, and parse its output with the air app, but the other problem remains (positioning inside air app).

  • Michael Christoff

    interesting, i'll have to give this a try when i do some testing on linux. think this same strategy is possible on windows, or even possibly os x?

  • Yuri Cauwerts

    Hi Michael,

    Very interesting article, I am doing the same kind of thing with video.

    My solution:
    I wrote a Java borderless application that uses Quicktime for Java (which is deprecated since a few months :-( ). this java-app listens to stdin and outputs some useful information to stdout. By sending the right commands you can also make the video always stay on top. Sending setPosition and setSize calls the methods of the java-app, so it can be bound to the AIR-app.

    The Quicktime API is *very* powerfull, but it takes time to get the hang of it.
    I can switch audiotracks on/off, change audio balance, add timetracks, add text on top of the video, change speed, …
    Quicktime gives me the possibility to scrub in realtime without any delays.
    I have read that MPlayer is also very good at scrubbing in realtime, it also depends on the IPB-frame structure of the video probably… (anyone?)

    Maybe I should try adding MPlayer as a possible choice of videoplayers in my java-app… I suppose it has a better future…

    I'll post some more information about my java-app, someplace, somewhere sometime… If anyone is interested offcourse…

    Yuri Cauwerts

  • Michael Christoff

    Intersting work Yuri! I'd love to see your code so I encourage you to post.

    A few questions I have…

    Is the Quicktime Java API self-contained or do you need quicktime installed?
    What's the licensing like?
    What are you using for the GUI layer? Java swing?

    It would be great to even see a little screen cast.

  • Shane Doolan

    I may be off target, but couldnt you position mplayer or vlc behind the Air app matching the size and location of a target rectange filled with the color #000001?

    As long as Video output is accelerated (therefore using an Overlay) the video should appear in place of the rectangle.

    Its not pretty, but as long as you could keep mplayer/vlc in the backgroud and the rectangles lined up it would appear as if the video was in the Air app.

    To try it out simply create an empty app or or open paint and give something a backgroud color of #000001 and drag it over a vlc/mplayer window…

  • Michael Christoff

    I get what your saying Shane. From what I can see though it doesn't look like mplayer already has an API for controlling the video rectangle so that would be something that definitely could be done but would require moderately extensive mplayer source digging and a pretty good understanding how the GUI layer works on all of the platforms (the part that AIR abstracts!). Also, like you mentioned, it could get messy for certain interaction cases in the window, for example double click for full screen, showing on screen controls when the mouse moves, capture hot keys properly.

    Also, what do you mean by #000001? Don't you mean #000000 (black)? What is the purpose of having a slightly non-black target?

  • Shane Doolan

    The color #000001 is the key color VLC selects to be replaced when the graphics card performs a video overlay, MPlayer uses #020202. To see what I mean press print screen on a playing video, you will get an (almost) black box in your screenshot where the video was playing. Take the same screenshot and drag it infront of the playing video and you will see the playing video appear in the screenshot.

    In this way you could control the size and location of mplayer or vlc in the background. All clicks, mouse moves, hot keys would be captured and handled by the Air application as the Air app maintains focus.

    Like I said its not pretty, and I have not tried this on anything other than windows xp. Just thought it could be an interesting approach to try.

  • Michael Christoff

    That is pretty interesting! I was unaware that video overlays worked like this. So what your saying is that if I create an AIR window with the background color #000001, startup a video with mplayer, then position the AIR window in front of the video (keeping the size the same) the video will show in the AIR window?

  • Shane Doolan

    thats exactly what I am saying, except that mplayer uses a key color of #020202.

    And again thats only tested in xp but I since the overlay is done by the graphics hardware I presume it would work the same in any operating system.

    Let me know if you try it.

  • Michael Christoff

    Not sure, I'm missing something, but I gave it a try on os x and it didn't
    seem to work. Checkout this screenshot:

    I didn't size the AIR window to be exactly the size of the mplayer window…
    is that a requirement? I figured I would get a cut off picture, but it would
    at least prove or disprove the theory. Maybe I'm still misunderstanding how
    the overlay works.

  • Shane Doolan

    No you are not missing anything, I must be wrong in presuming os x would work in a similar way to windows. It would appear that os x does not use a color key and/or also takes into account if the window is clipped when determining which pixels to replace with video when performing the overlay.

    I tried it on my machine running xp and can confirm it works, but I cant supply you a screenshot as the screenshot fails as expected when using video overlays…

    Sorry for leading you up the garden path!

  • Michael Christoff

    No worries, at least I learned something =)

    Btw, it looks like Visa and above do things without an overlay according to
    the wikipedia article.

  • Rohit

    This comment thread really got me thinking. I too am working on a video player application in air and was wondering if somehow i can actually play videos with mplayer and add a transparent canvas in air to cover this. I understand after xp this is not possible in the way discussed, but is there any other way? I would love it if I could add multiple format support to my AIR application.

    One way is alchemy port of ffmpeg…but thats a lot of work..any suggestions??

  • Rohit

    This comment thread really got me thinking. I too am working on a video player application in air and was wondering if somehow i can actually play videos with mplayer and add a transparent canvas in air to cover this. I understand after xp this is not possible in the way discussed, but is there any other way? I would love it if I could add multiple format support to my AIR application.

    One way is alchemy port of ffmpeg…but thats a lot of work..any suggestions??