From 2000 through 2009, we used to use RealVideo for our
streaming video webcasts.
Since 2009, we've switched over to a much simpler Flash-based
Keeping the RealVideo server up and running was no trivial matter.
I eventually came up with a set of scripts that made it operate
itself mostly unattended.
But, by 2009, Flash-based video was high enough quality (and
so much easier to use) that there was really no reason to keep
beating my head against the RealVideo software.
Here is how video gets from us to you:
- The various cameras feed into a video
switcher. From there, a single baseband NTSC video signal
- That signal goes into two different video encoder
machines. The first machine is a Mac, running the Justin.TV software
that uploads video for the Flash version. Simple.
When we were still doing RealVideo, these next steps happened as well:
- The second machine was a 1.4GHz Linux PC running with an
Osprey 100 video capture card. (I don't remember what the audio
capture card was, but it was nothing unusual.) That machine ran
realproducer, the software that encodes a raw video feed into
RealVideo. Getting this working was a huge pain in the ass:
realproducer is very flaky and hard to configure.
- The realproducer program sent a single stream of
video over our T1 to the machine that actually served video to
the outside world. That server machine was owned and operated by
our friends at
and Jolokia Networks,
who graciously let us piggyback off of their server for a full
decade. Because of their generosity, I didn't have to shell out
a small fortune to Real for my own server license and video
bandwidth. Thanks, guys!
- Finally, you clicked on the link to the RealVideo stream on
our Webcasts page, which
instructed your browser to launch RealPlayer and connect to the
stream on GrooveFactory's server.
Here are the shell scripts that made all that work. The whole
setup was pretty much held together with spit and bubblegum, but it
worked pretty well for me.
|| This is a script that probes whether a
realvideo stream is alive. ``RTSP'' is the HTTP-like
protocol that realserver uses. This script knows how
to generate the proper headers to ask whether the given
URL has data on it.
|| This is the /etc/rc.d/init.d/ script
that launches realproducer: this is where all the
arguments to the video encoder are specified, including
quality settings and the password.
|| Since realproducer, well, kind of
sucks, it occasionally loses its mind and wedges (or
otherwise stops communicating with the server) without
actually exiting or crashing. So
realprod-nanny is a script
that periodically probes the server: if there is not a live
stream where one is supposed to be, then it kills and
restarts realproducer (by running
realprod-initd stop followed by
|| This is the /etc/rc.d/init.d/ script
that launches realprod-nanny.
Getting RealProducer to talk to RealServer through a firewall that
is doing NAT is also a bit... challenging. I finally figured out how
to do it, though, and here's how.
RealProducer communicates with RealServer over some or all of the
||80, 554, 4040, 5050, 7070, 8080, 50001-50050
So at the least, your firewall has to allow those to pass between
the encoder and the server.
But if you're doing NAT (Network Address Translation, meaning
that the machines on the inside of the firewall have a different
idea of what their IP addresses are than what the outside world
sees) then life is harder.
The bottom line is, you can't use the Linux ipchains package
if you want to use RealProducer through the firewall, no matter how
many ports you open up. However, OpenBSD's ipf package
works fine. (I have not tried ipfw.)
The reason is this: say you have three machines:
So firewall is doing 1:1 NAT for encoder, so that
encoder itself thinks that it has the address ``172.28.1.5'',
but the outside world thinks that it has the address ``18.104.22.168''.
If you do this on Linux, then the packets that arrive at
server from encoder will have a source address of
22.214.171.124 (the external address of firewall.) If you use
OpenBSD, they will have a source address of 126.96.36.199 (the
external address of encoder.)
For most protocols, either way works; but for Real, only the latter
works. I don't know why.
My only guess is that somehow, Real is encoding its vision of the
address of the encoder machine in the protocol data itself, instead
of getting it out of the TCP and UDP layer. So the firewall doesn't
know how to reach into the data and rewrite those IPs. I can't
imagine why the software would be doing this, but that's the only
explanation I can come up with for the observed behavior.
Here's how you make it work:
On the firewall machine, set up the ethernet interface that is
attached to the outside world to bind to multiple addresses in
/etc/hostname.xl0 (or whichever it is):
inet 188.8.131.52 0xffffff00 NONE
inet alias 184.108.40.206 0xffffffff NONE
Set up a bidirectional mapping in /etc/ipnat.rules:
bimap xl0 172.28.1.5/32 -> 220.127.116.11/32
In /etc/ipf.rules, let your encoder send packets
out to the Real ports, and also get replies back (that's what
``keep state'' is):
pass out proto tcp from 172.28.1.5 to 18.104.22.168 port = 554 keep state
pass out proto tcp from 172.28.1.5 to 22.214.171.124 port = 4040 keep state
pass out proto udp from 172.28.1.5 to 126.96.36.199 keep state
And that's about it. I would rather have had all of my machines
running the same operating system, for simplicity and ease of upgrades,
but the only sensible thing was to use OpenBSD for my firewall, because
the Linux firewall code was simply not up to the job.
I understand that the development Linux kernels have a brand new
firewall package in them. Great, this is the third rewrite of the
Linux firewall code in three years (with a third incompatible syntax,
mind you.) It's as if whoever is responsible is treating this as a
learning process or something. What they should do is just port
the BSD code to Linux, since it's more powerful, older, widely used,
and stable. But the free Unixes believe in nothing if not the doctrine
of ``Not Invented Here.''