Streaming to Steam from the command line with ffmpeg
11 November 2022

We were lucky enough to show We'll always have Paris in the AdventureX Steam event last week. We've participated in a few Steam events now, and as the event stream has so far been the largest part of staying visible during an event, it has been a focus for us. It is possible to stream live, but like most developers we streamed a prerecorded video for the duration of the event. In the past we have had to dedicate a development machine to the stream for the entire week. That wasn't possible this time as we were exhibiting at the AdventureX event in London at the same time as the Steam event, so we wrote a script to stream our video to Steam from a cloud server using ffmpeg.

The script is straightforward to use, frees your computers up during the event, and it can be found here. The core of the script is an invocation of ffmpeg similar to the following (some parameters are derived from Steam's documentation, and some were arrived at by experimentation):

ffmpeg \
    -re -stream_loop -1 \
    -i /path/to/source \
    -f flv \
    -vcodec libx264 \
    -acodec aac \
    -pix_fmt yuv420p \
    -b:v "2500k" -minrate "2500k" -maxrate "2500k" -bufsize "2500k" \
    -b:a "160k" \
    -s "1280x720" \
    -filter:v fps=30 \
    -g 60 \
    -flvflags no_duration_filesize \
    -preset "medium" \
    "rtmp://ingest-rtmp.broadcast.steamcontent.com/app/rmtp_token_goes_here"

Preparation

First, you need a video to stream. OBS is the obvious recommendation for taking footage, but there are many alternatives. Whatever you use, it is best to export at the resolution and framerate you intend to stream it at, 720p @ 30fps in the example above. This limits the processing ffmpeg needs to do on upload.

Next, set up your stream settings in your Steamworks account as described here. Take note of the RMTP Token; the script will use it to authenticate with Steam. When you do this, you need to set the game ID on the broadcast page, AND add yourself as an allowed broadcaster in the game's store settings.

Finally you need a server. In general I would try the cheapest offering of your favourite hosting provider first, then test the stream upload, and if the CPU is maxed out move to the next most powerful option until the CPU is comfortably below 100%. A maxed out CPU risks dropping frames in the upload, or dropping the stream entirely.

In our case we used Digital Ocean's minimum "Premium AMD" instance (about $2 for the week) as the minimum normal CPU instance maxed out the CPU and failed the upload when we tested it. Whatever hosting provider you choose, check their bandwidth quota, and excess charges. During the festival we uploaded the same 20 minute loop almost 500 times, and even at 720p @ 30fps that was around 100GB. If you stream at higher quality it could easily exceed a Terabye of data, and that could trigger excess bandwidth charges from some providers.

Once the server is set up, SSH in and install ffmpeg (e.g. sudo apt install ffmpeg on Debian/Ubuntu).

Streaming

With the preparation out of the way, scp your video file and steam-stream.sh into your cloud server and run bash steam-stream.sh /path/to/video.mkv rmtp_token_goes_here. This should not return unless there is an error. Once started you will see the video in the broadcast page described in the Steam documentation above.

If you want to run this as a background service that starts on boot and gets restarted on failure, you can use the systemd configuration below.

[Unit]
Description=steam-stream
After=syslog.target

[Service]
Type=simple
ExecStart=/bin/bash /root/steam-stream.sh /path/to/video rmtp_token_goes_here
Restart=always

[Install]
WantedBy=multi-user.target

Replace the paths, insert your RMTP token, save this in /etc/systemd/system/steam-stream.service and run

systemctl daemon-reload
systemctl start steam-stream
systemctl enable steam-stream

This should run it automatically on boot until you delete the server at the end of the festival. systemd will restart the script if it fails due to a dropped connection or a power cycle, so you can largely forget about it.

Alternatives to cloud servers

The most similar alternative to a cloud server would be to stream from one of the newer Raspberry PIs. I've not personally tried this, so you should test it ahead of time to be sure the processor can handle the load.

ffmpeg runs on Windows, Mac and Linux, so if you don't want to set up a cloud server, but do want to stream from the command line you can use it on any computer. Mac is identical to Linux in this respect: just run the bash script from Terminal, but you would need to use launchctl rather than systemd if you want to run it as a background service.

On Windows you can also run it unmodified if you are using WSL, it is even possible to run it as a background service as long as you configure systemd. Alternatively it should not be hard to translate the script to Powershell.

Framing your video

This is slightly unrelated to streaming, but if you want to apply a frame to your video using ffmpeg you can do so using a command such as:

ffmpeg \
    -i background-frame.png \
    -i unframed.mp4 \
    -i overlay-frame.png \
    -filter_complex \
    "[1:v]scale=w=1614:h=908[va];[0][va]overlay=x=49:y=134[vb];[vb][2]overlay[out]" \
    -s "1280x720" \
    -map [out] -map 1:a? \
    framed.mp4

It is handy if you want to put your socials on a frame around the video, but like me are more comfortable with command line than you are a video editor. This will:

Please enable javascript

By signing up you agree to our privacy policy