Live video streaming using vp8enc and webm on Debian

2012-01-08 5-minute read

The vp8 video codec and webm container format (which are alternates for theora/ogg and h264/flv) are getting lots of attention, especially as more web browsers are supporting html5 - which includes a new video tag that plays video directly in a web page, rather than requiring a plugin. With Google fully behind these new formats (and converting YouTube videos) and even skype using vp8, it seems as though it could supplant h264/flash as the default video codec and container.

After years under the boot of the proprietary flash video, this change could usher in a lot of exciting developments.

While the shift in formats is also significant for on-demand video, I’m focusing on live streaming in this blog.

There are a lot of tools needed to successfully stream a live video. Enough of them support vp8 and webm to create a live video stream, however, not all of the right versions of these tools have landed in Debian.

Without any patches or changes, if you try to send a live video stream to icecast using vp8 encoding and webm, you’ll get something like this:

0 jamie@animal:~$ gst-launch v4l2src ! video/x-raw,width=320,height=240 ! vp8enc ! webmmux ! shout2send ip=icecast.server port=8000 password=secret mount=/test.webm
WARNING: erroneous pipeline: could not link webmmux0 to shout2send0
1 jamie@animal:~$ 

I’ve documented the steps for patching/upgrading gstreamer and icecast2 so you can get a live video stream using vp8 encoding and the webmc container that originates on a Debian wheezy machine using gstreamer and streams to a Debian squeeze server running icecast2.

On the workstation, you’ll need libshout3 version 2.3.0 or higher, which is at the moment available in experimental and installable without bringing in any dependencies. In addition, you will need to bring in gstreamer1.0 from sid and you will need to rebuild gstreamer1.0-plugins-good after libshout-dev has been installed from experimental.

So, begin by adding experimental and sid to your sources list by creating the files /etc/apt/sources.list.d/experimental.list and /etc/apt/sources/lists.d/sid.list with the respective contents:

deb http://mirror.cc.columbia.edu/debian experimental main 

and

deb http://mirror.cc.columbia.edu/debian sid main 
deb-src http://mirror.cc.columbia.edu/debian sid main 

In order to avoid upgrading your entire machine to sid (experimental packages won’t upgrade by default), you’ll also need to add the file /etc/apt/preferences.d/sid:

Package: *
Pin: release n=sid
Pin-Priority: 200

Then update and install:

apt-get update
apt-get install -t experimental libshout3
apt-get install gir1.2-clutter-gst-1.0 gir1.2-gst-plugins-base-1.0 gir1.2-gstreamer-1.0 gstreamer0.10-ffmpeg  gstreamer1.0-libav:amd64 gstreamer1.0-plugins-bad:amd64 gstreamer1.0-plugins-base:amd64 gstreamer1.0-plugins-base-apps gstreamer1.0-plugins-good:amd64 gstreamer1.0-pulseaudio:amd64 gstreamer1.0-tools gstreamer1.0-x:amd64 libclutter-gst-1.0-0:amd64 libgstreamer-plugins-bad1.0-0:amd64 libgstreamer-plugins-base1.0-0:amd64 libgstreamer-plugins-base1.0 libgstreamer1.0-0:amd64 libgstreamer1.0

Fortunately, the version of gstreamer1.0-plugins-good in sid includes a fix for a bug patched on November 31, 2012 that allows the use of the webm container. However, for it to work properly gstreamer1.0-plugins-good has to be built against libshout version 2.3.0 or higher (which is in experimental, not sid). Therefore, you have install libshout-dev from experimental and then rebuild gstreamer1.0-plugins-good.

sudo apt-get build-dep gstreamer1.0-plugins-good
sudo apt-get -t experimental install libshout-dev
apt-get source gstreamer1.0-plugins-good
cd gst-plugins-good1.0-1.0.4
dch -v 1.0.4-1+webmmux
fakeroot debian/rules binary
sudo dpkg -i ../gstreamer1.0-plugins-good_1.0.4-1+webmmux_amd64.deb

Now if you try the command, things should work on the client side. When streaming to an icecast2 server running squeeze, I don’t get any errors, however, when opening the streaming page via the icecast URL, there is a play button, which can be clicked, but no picture is shown. That’s because the version of Icecast2 in squeeze doesn’t support either vp8 or webm.

On the server side, you will need icecast2 version 2.4beta or higher. This version hasn’t landed anywhere in Debian as of this writing.

However, you can build it from source by following these steps (the patches I’m removing have all been applied to the new upstream version).

apt-get source icecast2
wget http://downloads.xiph.org/releases/icecast/icecast-2.4-beta.tar.gz
tar -xzvf icecast-2.4-beta.tar.gz
cp -r icecast2-2.3.2/debian icecast-2.3.99.0/
cd icecast-2.3.99.0/
rm debian/patches/{1001_autotools_avoid_debian-subdir.patch,1002_add_missing_xspf_file,1003_fix_memory_leak.patch,series}
dch -v 2.3.99.0-1
fakeroot debian/rules binary

When you install it, be sure to replace the icecast2.xml configuration file and update it with your server-specific customizations.

Hopefully this version of icecast2 will make it to experimental soon.

And now… you can successfully stream via:

gst-launch-1.0 v4l2src ! video/x-raw,width=320,height=240 ! vp8enc ! webmmux !  shout2send ip=icecast.server port=8000 password=secret mount=/test.webm

If you want full audio and video, here’s a more complete pipeline:

gst-launch-1.0 v4l2src ! queue ! video/x-raw,width=320,height=240 ! tee name=tscreen ! queue ! autovideosink tscreen. ! queue ! videorate ! video/x-raw,framerate=25/2 ! queue ! vp8enc ! queue ! webmmux name=mux pulsesrc ! queue ! audioconvert ! vorbisenc ! queue ! queue ! mux. mux. ! queue ! shout2send ip=hobo port=8000 mount=jamie.webm password=secret

Unfortunately, since I’m not sure how to deal with the python2.7 vs python3 dependecies, my elegant mobi python script that creates this pipeline for you using python-gtk as been reduced to a crude bash script.

Another item on the todo list is opus audio encoding. gstreamer doesn’t seem able to use opus in the webm container (although it seems to work with ogg).

In the course of this research I found directions for getting gstreamer-1.0 installed on debian independent of packages installed on the system. If you follow the directions above, these steps should not be necessary. I’m including in case you need the latest sources for another reason.

Extra steps I needed were:

  • Edit gst-rebuild, comment out gst-plugins-ugly from plugins var (line 14) and sources arg (line 14) - these caused errors for me.
  • manually install the following packages from experimental (apt-get build-dep gets confused about how to find them):
  • apt-get install -t experimental libavcodec-dev=6:9~beta3-1
  • apt-get install -t experimental libavformat-dev=6:9~beta3-1
  • apt-get install -t experimental libswscale-dev=6:9~beta3-1 libswscale2=6:9~beta3-1
  • Then follow directions as advertised