by

Broadcasting a video playlist to nginx-rtmp-module

With a few open source tools, you can stream a playlist of videos in real-time over RTMP, MPEG-DASH, and HLS in a fully automated manner.

In this case, we’ll be using several software packages:

  1. GStreamer/Libav for decoding and encoding
  2. Liquidsoap for playlist management
  3. nginx for the server
  4. nginx-rtmp-module for providing HLS/MPEG-DASH/RTMP streaming

Using Ubuntu 14.XX (or possibly anything Debian-based) will be your shortest path of resistance, as compiling these packages by hand is a considerable chore and other distributions will likely lack many of these packages. If you want to use a different OS, you can virtualize Ubuntu, possibly with a lightweight container. You will not get very far with older versions of Ubuntu (such as 12.04) as they will also lack many of these packages.

GStreamer and Liquidsoap

GStreamer is a multimedia framework similar to DirectShow, in that it allows the linking together of components such as decoders, encoders, and so on to handle media. You’ll want to install the entirety of GStreamer if you want to play a wide variety of video formats. In addition, the “gstreamer1.0-libav” package enables you to make use of the Libav library to decode media.

Note: Libav is a hostile fork of the FFmpeg project and the relevant package maintainer for Debian/Ubuntu has chosen to distribute Libav rather than FFmpeg (which is still alive and kicking).

sudo apt-get -y install libgstreamer1.0-0 gstreamer1.0-plugins-base \
   gstreamer1.0-plugins-ugly gstreamer1.0-plugins-good \
   gstreamer1.0-plugins-bad gstreamer1.0-tools gstreamer1.0-libav

Then you’ll want to install Liquidsoap. Liquidsoap provides a powerful language to tie together multimedia components, and we’ll need it for playlist support. (It does a lot more though.)

sudo apt-get -y install liquidsoap liquidsoap-plugin-all

Be aware that you’ll also be installing all of LiquidSoap’s plugins (and dependencies). In reality, you do not need the whole package to simply stream a playlist, but you’ll have more freedom to play with LiquidSoap’s various features if you choose to install everything.

nginx and nginx-rtmp

Next, you’ll want to install Nginx and the nginx-rtmp-module.

Nginx is most well known to be a high-performance web server and reverse proxy, but the nginx-rtmp-module turns nginx into a streaming media server capable of speaking RTMP, MPEG-DASH, and Apple HTTP Live Streaming (HLS) protocols.

Flash-based video players will use RTMP, but HTML5/mobile players will use MPEG-DASH or HLS. The latter two protocols provide adaptive streaming, where videos are spliced into small chunks in real-time, allowing the client to switch to a lower quality “stream” in the middle of a video (see: YouTube).

Compiling from source

While nginx is readily available in the repositories on Debian/Ubuntu, it does not come with the nginx-rtmp-module, so we’ll have to compile nginx ourselves.

sudo apt-get update
sudo apt-get install dpkg-dev git-core
mkdir ~/nginx-compile
cd ~/nginx-compile
apt-get source nginx
sudo apt-get build-dep nginx
git clone https://github.com/arut/nginx-rtmp-module.git
cd nginx-VERSION

You’ll then want to edit the debian/rules file and add the following to the “config.status.full” entry on a new line, after all the other --add-module lines.

--add-module=/path/to/nginx-compile/nginx-rtmp-module \

Proceed to compile the package.

dpkg-buildpackage -b

Afterwards, you can install both the newly created “common” and “full” packages. Make sure to apt-get remove nginx first if you have already installed nginx via the package manager.

cd ../
sudo dpkg --install nginx-common_1.4.6-1ubuntu3_all.deb
sudo dpkg --install nginx-full_1.4.6-1ubuntu3_amd64.deb

Configuring nginx

You’ll want to edit /etc/nginx/nginx.conf in your favorite editor and add the following section to the end of the file. Note that my snippet below will only configure nginx to provide a RTMP stream, but check out nginx-rtmp-module’s wiki to learn how to setup MPEG-DASH or HLS support.

rtmp {
  server {
    listen 1935;
    publish_time_fix off; # compatibility with GStreamer

    application example {
      live on;
      allow publish 127.0.0.1;
      deny publish all;
      allow play all;
    }
  }
}

Start nginx.

service start nginx

Streaming a test video

You can test whether your setup is sound using the gst-launch-1.0 program provided with GStreamer. (Be sure to change the path to the test video file.)

gst-launch-1.0 \
  filesrc location="/path/to/file.mp4" ! decodebin name=t \
  t. ! videoconvert ! x264enc bitrate=2000 ! queue ! flvmux name=mux \
  t. ! audioconvert ! voaacenc bitrate=128000 ! queue ! mux. \
  mux. ! rtmpsink location="rtmp://127.0.0.1:1935/example/live live=1"

To actually watch the stream, you can use the rtmpdump program and pipe the result to something like VLC Media Player (VLC does not yet offer native support for viewing RTMP streams).

You can also configure one of the freely available Flash streaming video players to play your stream.

Configuring Liquidsoap

With your favorite text editor again, create a stream.liq file and in it, place the following code.

set("frame.video.width", 1280)
set("frame.video.height", 720)
set("frame.video.samplerate", 25)
set("gstreamer.add_borders", true)

s = single("/path/to/video.mp4")

s = fallback([s, blank()])

output.gstreamer.audio_video(
  video_pipeline=
    "videoconvert ! x264enc bitrate=2000 ! video/x-h264,profile=baseline ! queue ! mux.",
  audio_pipeline=
    "audioconvert ! voaacenc bitrate=128000 ! queue ! mux.",
  pipeline=
    "flvmux name=mux ! rtmpsink location=\"rtmp://127.0.0.1:1935/example/live live=1\"",
  s)

Run your script file by executing liquidsoap stream.liq in your terminal. If all goes well, you should be able to watch your video by connecting to nginx as you had done before with the gst-launch tool.

Setting up a playlist

At this point, you can change

s = single("/path/to/video.mp4")

into

s = playlist("/path/to/playlist.ext")

(See Liquidsoap’s supported playlist formats.)

In conclusion

While the method I have outlined does work, it is not the only way to go about doing this. For example, you could concatenate a list of videos together with FFmpeg and send it off to your media server using the -realtime flag, skipping half of the steps in this article. You could even use one of those “screen streaming” programs with playlist support.

Remember also that video encoding (and to a smaller degree with most formats, decoding) is a CPU-intensive task. If you do not provide enough resources, the stream will stutter.

  • Ali Moghnieh

    Awh yeah. I’ve wanted this for a long time! <3 Posted on my birthday as well haha!

  • Dima Kruk

    thanks for the nice post!
    I had a problem with running stream. Maybe you can help me understand what the problem is.

    This is log:

    $ gst-launch-1.0 filesrc location=”/home/user/Videos/output.mp4″ ! decodebin name=t t. ! videoconvert ! x264enc bitrate=2000 ! queue ! flvmux name=mux t. ! audioconvert ! voaacenc bitrate=128000 ! queue ! mux. mux. ! rtmpsink location=”rtmp://127.0.0.1:1935/example/live live=1″
    Setting pipeline to PAUSED …
    Pipeline is PREROLLING …
    Redistribute latency…
    Redistribute latency…
    Pipeline is PREROLLED …
    Setting pipeline to PLAYING …
    New clock: GstSystemClock
    ERROR: RTMP_Connect0, failed to connect socket. 111 (Connection refused)
    ERROR: from element /GstPipeline:pipeline0/GstRTMPSink:rtmpsink0: Could not open resource for writing.
    Additional debug info:
    gstrtmpsink.c(214): gst_rtmp_sink_render (): /GstPipeline:pipeline0/GstRTMPSink:rtmpsink0:
    Could not connect to RTMP stream “rtmp://127.0.0.1:1935/example/live live=1″ for writing
    Execution ended after 0:00:00.001127881
    Setting pipeline to PAUSED …
    Setting pipeline to READY …
    Setting pipeline to NULL …
    Freeing pipeline …

    • http://www.sk89q.com sk89q

      Well it says “failed to connect socket. 111 (Connection refused)” so make sure that something is running in port 1935?

  • Zohar Smith

    Hello, i installed gstreamer in windows, how can i use this in command line:

    gst-launch-1.0
    filesrc location=”/path/to/file.mp4″ ! decodebin name=t
    t. ! videoconvert ! x264enc bitrate=2000 ! queue ! flvmux name=mux
    t. ! audioconvert ! voaacenc bitrate=128000 ! queue ! mux.
    mux. ! rtmpsink location=”rtmp://127.0.0.1:1935/example/live live=1″

    i got error of syntax with this

    • http://www.sk89q.com sk89q

      Sorry, I am not familiar with GStreamer on Windows.

      However, you can’t use on Windows if I recall.

      • Ilimaan

        It’s playing well if I use single Video. But if I use playlist( with any of the supported playlist format, I got a Blank Screen (seems to be the failback).
        Can you help determine what should be the cause and how to fix it?

  • Ilimaan

    It’s playing well if I use single Video. But if I use playlist( with any of the supported playlist format, I got a Blank Screen (seems to be the failback).
    Can you help determine what should be the cause and how to fix it?

    • http://www.sk89q.com sk89q

      I’m not sure. You can ask the Liquidsoap mailing list / IRC channel.