Using VLC to transcode an Axis Camera’s video stream, and stream it out again

Recently, I’ve been working on streaming live video from IP cameras to a Flash player on a website.  It sounds simple, but not so much, (if you’re in a hurry, skip to the solution).

The problem is that most IP cameras are not made for streaming live, full-motion, events to the web.  They’re made for surveillance at 11 FPS in Motion JPEG format, (that’s just a bunch of JPEG images coming one after another).  This is obviously not ideal from a bandwidth perspective at all.  The cameras that our project uses are Axis 207 and 210 cameras.  These cameras are capable of streaming MPEG-4 video, and when you look at the video in a web browser it looks pretty good.  When I first saw that, I was excited – I could just stream into a Flash media server, (We’re using Wowza Media Server Pro at the moment), and that would send everything off to the player, right?  Wrong.

It turns out that most, if not all, Axis products stream in MPEG4-ES, which flash cannot understand, and therefore our server rejects.  I had to find a way to change MP4V-ES to h.264.

The obvious solution to transcoding the video stream from MP4V-ES to h.264 is VLC.  While it looks like a media player that can handle a lot of formats, under the surface lies a powerful, command-line based, transcoding and streaming program.  I discovered that, in theory, I should be able to issue one command to VLC and have it receive the MPEG4-ES stream from the camera, transcode it to h.264, and stream it to the Wowza, which would handle the rest.

I started by opening a file, transcoding it to h.264, and streaming it to Wowza:

vlc -vvv /path/to/file/Extremists.m4v --sout "#transcode{venc=x264,vcodec=x264,vb=500,scale=1,acodec=mp4a,ab=32,channels=2,samplerate=22100}:rtp{dst=SERVER-IP-ADDRESS,sdp=file:///path/to/wowza/content/myStream.sdp}"

It was a little rough, as the testing server doesn’t have a lot of processing power, but it worked.  Awesome.  Now I just have to hook it up to the stream from the camera, right?

I added the camera as the source and removed the sound:

vlc -vvv rtsp://camera-ip-address:554/mpeg4/1/media.amp --no-sout-audio --sout "#transcode{venc=x264,vcodec=x264,vb=200,scale=1}:rtp{dst=SERVER-IP-ADDRESS,sdp=file:///absolute/path/to/wowza/content/myStream.sdp}"

With Wowza already running on the server, I typed that in to terminal, and it started to look good.  Then PAF! I get this error:

[00000385] access_output_udp private debug: mmh, hole (147841635484807 > 2s) -> drop

VLC seems to think that a frame, or some piece of information has been delayed 147841635484807 seconds.  I highly doubt that, but VLC is convinced.  Try as I might, I was not able to get VLC to realize that the frame, (or whatever bit of info), was simply missing a timestamp or something.

So, I figured I would debug just the connection to the camera.  I opened a VNC session, and ran this:

vlc -vvv rtsp://camera-ip-address:554/mpeg4/1/media.amp

To see if I could view the video.  I could, so I tried saving it to a file:

vlc -vvv rtsp://CAMERA-IP-ADDRESS:554/mpeg4/media.amp --no-drop-late-frames --no-sout-audio --sout "#std{mux=ts,access=file,dst=/tmp/camstream.m4v}"

This worked also.  It appears that the problem only occurs when I am trying to open, transcode, and send out the stream all at once.

I realized, if I can transcode from a file and stream, and if I can capture a stream and save it to a file, I should be able to do both at the same time.  It works!  The steps are, make the pipe:

mkpipe /tmp/vpipe

Then capture the stream and save it to the pipe:

vlc -vvv rtsp://CAMERA-IP-ADDRESS:554/mpeg4/media.amp --no-drop-late-frames --no-sout-audio --sout "#std{mux=ts,access=file,dst=/tmp/vpipe}"

And finally read from the pipe, transcode, and stream to the flash server:

vlc -vvv /tmp/vpipe --no-sout-audio --sout "#transcode{venc=x264,vcodec=x264,vb=500,scale=1}:rtp{dst=SERVER-IP-ADDRESS,sdp=file:///path/to/wowza/content/myStream.sdp}"

Shazam!

There are a couple of caveats, though:

  • This sucks major processing horsepower.  Make sure you’ve got enough
  • To make a stream work this way you have to have 2 copies of VLC running, plus your flash server.  That’s a lot of parts that could have a problem

Because of these caveats, I am still looking for an alternate solution, and may stream MPEG-4 to browsers until Axis has its h.264 products ready later this year.

Yesterday, I did find a second possible solution.  Instead of using the first instance of VLC to capture the stream, it is sometimes possible to use Darwin Streaming Server to capture the stream, then use 1 instance of VLC to transcode it. This seems to use much less processing power, but is not 100% reliable either.

Coding in a Vacuum: Subversion Hooks

A month ago I wrote about setting up an in-house subversion server on the cheap. After a month of using my setup it’s been pretty successful, and I’ve learned even more about subversion.

One of the things I had to do was set up a post-commit hook to publish changes to a webserver.  The site I did this for is still in development, and every commit needed to be pushed to the webserver for testing.  I did this using rsync, (or, since the SVN server is in Windows, cwRsync), and it’s a pretty basic rsync/openSSH setup, but that’s for another day.

What I am talking about today is actually creating the hook script.  What a pain in the ass.  It’s not actually hard to create the script and run it.  On Windows you just write a batch file, debug it, call it post_commit.bat, and drop it in the hooks folder of the repository you want to use.  Sounds simple, doesn’t it?  Why then, when you commit a revision, does Subversion hang, and the script not execute?  Because subversion runs hooks in a near-null environment. This means that nothing is set.  In Windows, not PATH variable.  In everything, pretty much no environment variables of any kind.  So, when you tested your script yourself it ran great because it had lots of support, but now Subversion is running it entirely alone.  Poor, lonely script.

It gets even more frustrating.  Since Subversion is running the script, there’s nothing being printed to the screen to tell you what’s going on, so debugging is like shooting bugs in the dark.

There are a couple of things you can do, however, to make your script work.  First, use an absolute, full, path for everything.  For Windows this means start with the drive letter.  For *nix this means start with a slash.  If that doesn’t work, there’s a trick that allows you to see what’s going on.  You can log the hook’s output to a file.  This way you can find out what’s going on, read the errors, and fix them.  Thanks to Dan Switzer for posting about it. His blog showed up in a Google search and ended my frustration.  In my case, it was some more environment that had to be set up for cwrsync to work properly.

Would the MacBook Touch Really be Useful?

There’s been a lot of talk recently about a MacBook Touch – a Mac laptop with a touch screen, perhaps in tablet form, but each time I read a speculation like this I wonder – would a MacBook Touch really be useful?

Found at shinyshiny.tv/2008/07/rumour_macbook.html
Image found at http://www.shinyshiny.tv/2008/07/rumour_macbook.html

I sit at a desk, (or on a couch sometimes), and work on my MacBook Pro.  I spend most of my time coding in PHP, Javascript, HTML, or CSS, and I use the trackpad to control the mouse.  This way I rarely have to move my hands, (I know it sounds lazy).  I find that I can get things done fastest working like this.  If my computer were to have a touch, (or multi-touch), screen I would have to lift my arms, touch the screen, then find my position again on the keyboard.  I know it would be fast, but multiplied by a thousand, (or however many times I interact with the mouse), per day it would take a lot of time.  Really, if I can drag something across the screen by moving one finger five cenimetres on the trackpad, why would I involve my whole arm in dragging something twenty-five centimetres across the screen?  Call me lazy, but it seems like a lot of unneeded work to me.

Another more minor issue would be the dirty, dirty screen.  My screens, (on all of my computers, not just the MacBook Pro), get pretty dirty, I they would probably get pretty disgusting if I was touching them all of the time, instead of just sometimes as I do now.  True, I could, (and would), clean the screen, but it’s not just a one and a half second wipe like on an iPhone or iPod Touch – I imagine that it would get annoying after a while.

A tablet form factor would reduce these problems.  I have never owned a Tablet PC myself, but the demos I’ve seen were pretty cool and I can see how they would be useful in some situations, but for everyday computing I don’t really see how the added cost of a touch screen would give a MacBook Touch any added value.

Of course, they usually seem to figure out how to do it down there at Apple, so if they are actually working on a MacBook Touch, it may be excellent, we’ll have to wait and see.