./blog
X11 Streaming to RTMP Server with FFmpeg
22 Jul 2013

Today we're gonna do what the title says we're gonna do. I'm assuming you already have ffmpeg installed and are running X. Let's dive straight into the command:

The Command

URL="rtmp://example.com/app/channel" \
CAPTURE_SIZE=1366x768 \
FRAME_RATE=15 \
STREAM_SIZE=342x192 \
eval ffmpeg -f x11grab -s '$CAPTURE_SIZE' -r '$FRAME_RATE' -i :0.0 \
     -c:v libx264 -preset ultrafast -pix_fmt yuv420p -s '$STREAM_SIZE' -f flv '$URL'

Please note the eval and single quotes around the variables are so that they can be evaluated in the new environment made by the variables.

The Breakdown

URL

Determining the URL is probably the hardest part. The domain is obvious, but app and channel are less intuitive. Most of the time you will get this from your your streaming host, but say (for example) you have configured your own server with nginx and RTMP and the following happens to be your settings.

1
2
3
4
5
6
7
8
9
10
11
12
13
rtmp {
    server {
        listen 1935;
        ping 30s;
        notify_method get;

        application play {
            live on;
            allow publish all;
            allow play all;
        }
    }
}

The play name on line 7 above is the app part of the URL. Now let us say (for the sake of argument) the flash player you have set up to read the stream is setup in HTML like the following

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script type="text/javascript" src="jwplayer/jwplayer.js"></script>

<div id="container">Loading the player ...</div>
    <script type="text/javascript">
        jwplayer("container").setup({
        modes: [
            {   type: "flash",
                src: "jwplayer/player.swf",
                config: {
                    bufferlength: 0.25,
                    file: "test",
                    streamer: "rtmp://example.com/play",
                    provider: "rtmp",
                }
            }
        ]
});
</script>

The test on line 11 would correspond to channel of the URL. Putting those all together makes rtmp://example.com/play/test.

Video Parameters

Parameter Description
CAPTURE_SIZE The resolution to capture the screen at in WIDTHxHEIGHT format
FRAME_RATE The number of frames per second to capture
STREAM_SIZE The resolution to encode the stream at in WIDTHxHEIGHT format. I recommend this be some power of two factor (e.g. half height and width) of CAPTURE_SIZE

Other Video Arguments

Argument Description
-f x11grab Tells FFmpeg to use the output of the X screen as its video input
-i :0.0 Specifies which screen to capture (this one is display 0, screen 0)
-c:v libx264 Tells FFmpeg to use the libx264 encoder. It's pretty good quality and speed, but not every version of FFmpeg out there has it built in. Make sure your copy does.
-preset ultrafast The encoder likes to buffer many frames to improve quality, but that introduces latency in the stream, which is not great for video games. This preset configures the encoder to minimize that and other slow computations.
-pix_fmt yuv420p Tells the encoder to use that pixel format. I recommend the awesome Digital Media Primer over at xiph.org if you want to know more about these.
-f flv This tells FFmpeg to wrap the encoding into the flv container. RTMP is all about flash, and flv is the FLash Video format.

See Also

Much of the command line was taken from examples on this streaming guide at ffmpeg.org. It has many more examples to help you out with different platforms.