Simulated Live with Wowza and Apple HTTP Live Streaming

Last summer, we switched our primary Flash streaming over to 316 Networks partly because of the simulated live capability they offered, and partly for the Media Suite backend. We continued to use Wowza on EC2 for our mobile users, since the solution works very well. Unfortunately, simulated doesn’t work for our mobile users, who are limited to live.

We have 3 replays a week for each of our two web services: the traditional service from Sunday morning, and the praise service from Sunday night.

I should probably step back for a moment and explain what “Simulated Live” means. It’s a recorded event, but from a user standpoint, it behaves like a live event. There’s a set start time, and if you come in 20 minutes after the start of the event, you get the video 20 minutes in; there are no “trick play” DVR functions like fast-forward or rewind. This gives a shared experience for everyone who is watching, and also keeps us legit with the copyright restrictions, as our “live” events are considered extensions of the actual live event in the sanctuary. Simulated live is also known as “pseudostreaming”

Wowza doesn’t natively support pseudostreaming (although the Stream Class API does have some scheduling capability — see this post), so we needed some way of broadcasting recordings on a schedule. I could use the VT5 machine and the Scheduler to replay the recordings on a schedule, but the big downside is that it consumes local bandwidth, which is in short supply.

What I needed was a way of streaming the archive files (high and low bandwidth) that were created by the Kulabyte encoder during the live event. Ideally, since I already upload these to 316 for rebroadcast, I’d like to not have to upload it to two locations.

Enter the lovely open-source encoder, ffmpeg. My concern about using ffmpeg was that re-encoding an already encoded file had the potential of introducing compression artifacts and adding CPU load. I was very happy to find an obscure command-line setting that tells it to copy the input file’s audio and video codec directly. The only thing ffmpeg would be doing would be extracting the audio and video streams from the MPEG-4 container and stuffing them into a Flash container without molesting the actual streams at all. Added bonus: ffmpeg can also not only output to RTMP, but can take RTMP as an input as well.

Fortunately, Media Suite’s media bin makes videos available via direct RTMP and HTTP and helpfully provides the CDN URL for those files. Another method of storage would be to use Amazon S3 and get the files either via HTTP or Cloudfront RTMP.

Attempt #1: Installed ffmpeg on a local Ubuntu box via apt-get, no dice. It refused to connect to the RTMP server. After some research, I found that the version of ffmpeg on the Jaunty version of Ubuntu is 0.50, and seems to have some weird build options.

Attempt #2: I downloaded the ffmpeg 0.61 source, ran a quick configure/make/make install on it, and tried again. Success! I was taking an MP4 recording on a disk, and streaming to Wowza. I then changed the input from a local file to to the URL provided by 316, and weird stuff started happening. And then I realized that the URL had some GET parameters in it that left a question mark and two ampersands in the URL that I needed to escape before bash would parse it correctly. Once I fixed that, it started running happily, and I was seeing the stream on my iPod.

Attempt #3: I Downloaded the ffmpeg 0.61 source to my Wowza server on EC2 and crossed my fingers that the build would go off without a hitch. Success! I then transplanted the command line I used on my test box, tweaked the destination server to the local Wowza install, and fired it off. Success again!

Now that I’d proved the concept, it was simply a matter of putting that command into a cron job and waiting to see if it fired off. And then realizing that the server is in eastern time. And then realizing that I should probably correctly specify the path to ffmpeg (doh!). But once I got those silly details ironed out, off it went.

So now I have ffmpeg on my EC2 system, consuming virtually no CPU, pulling my archive files from 316 (only had to upload them once), streaming to Wowza on a scheduled basis, without chewing up T1 bandwidth at our main site.

Unfortunately, there’s a little bit of brain damage involved in pulling it from 316, because I’ll have to go change the filename in the cron job every week. Perhaps I’ll end up uploading it to S3 after all and just giving it a static name.

Here’s the commandline used:

/path_to/ffmpeg -i rtmp://rtmp.server/filename.mp4 -re -sameq -acodec copy -vcodec copy -f flv rtmp://localhost/live/stream

Commandline options used:

  • -i : specifies input. This can be either RTMP, HTTP, or a local file.
  • -re : near-realtime mode
  • -sameq : Keep quality settings
  • -acodec copy : send input audio stream unmolested to the output
  • -vcodec copy : send input video stream unmolested to the output
  • -f flv : Force output to FLV container

Making Sense of Mobile Streaming

Now that we’ve gotten streaming to computers down pat, I’ve set my sights on delivering a good experience for mobile users. Unfortunately, with the wide variety of mobile platforms out there, this is not an especially easy task. The Mac/PC/Linux issues are complicated enough, and it gets really tricky when the platform ecosystem has half a dozen major players (and a truckload of minor ones)

Since July or so, we’ve been using a preview version of the recently released Wowza V2 server software to deliver our video content to iPhone/iPod devices that support Apple’s new HTTP Streaming format. With minimal changes, Wowza V2 can also rebroadcast the same H.264/AAC stream over RTSP, which reaches a lot more devices. But this is where it gets complicated. BlackBerry has been supporting RTSP for some time, but it’s only recently that they’ve supported h.264/AAC media. According to their KB article on the subject, you can do H.264 on the following:

  • Bold 9000/9700
  • Tour 9630
  • Storm 9500/9520/9530/9550
  • Curve 8900/8520

Most HTC phones have a streaming media app that supports RTSP, but only recent versions seem support H.264. For example, my Mogul has the app, but I can only hear the audio. Brian‘s Touch Pro 2 gets both (and on the TP2’s WVGA screen, it looks amazing!).

Windows Media Player supports RTSP, but doesn’t come with an H.264 codec (even in Windows 7!!!! BOOO!!!!). I have yet to get the RTSP stream to work on Windows Media Player. The mobile player doesn’t support RTSP at all, just MMS and HTTP (but not the same HTTP as Apple! Grr!), and with the 9.5 generation of Windows Media Services (2008), MMS has gone away in favor of HTTP (which Microsoft calls Smooth Streaming, also not supported on WiMo).

The Palm Pre is supposedly able to do RTSP and H.264, but I’m waiting to hear back from one of our pre-wielding pastors to see if this is actually the case.

Thanks to Daryl Hunter at lifechurch.tv for letting me know that it works on his HTC Hero (Android 1.5). It seems that on Android you can’t manually enter an RTSP URL into the browser bar, but a web link or tinyurl redirect that goes to an RTSP URL does work.

Meanwhile, VLC player will play just about anything you throw at it, including the RTMP flash stream. Pity it’s not available in a mobile version.

So, as it stands now, in order to deliver a mobile experience to as many people as possible, I’m still going to need to run a separate Windows Media server for our Windows Mobile clients, But everyone else should be able to pull from the “iPhone” stream (which I’m probably going to need to rename), as long as the device supports H.264/AAC and RTSP.