How to record 4K game-play on Linux

The problem

I know what you people think, that I am going to present you with a solution evolving OBS fixing all the crashes and staggering that we all get when we try to record beyond 1080p@60fps.

In matter of fact I tried all possible settings combinations with OBS but I never came up with a video file having an acceptable quality.

It was about time to start working on the CLI…

Linux 4K Recording with FFMPEG

So I tried to use FFMPEG to do a straight up recording of the entire screen while playing on native resolution.

Obviously I did a google search and I came up with a page about Screen Recording.

After I did few tests I remembered I have tried all these long time ago, the problem here was x11grab. It performs miserably slow…

So I started digging around on the FFMPEG documentation, until I realized the kmsgrab could be an alternative…

The cryptic description of kmsgrab made me to misunderstood its usage…

And then when I finally read the description properly a miracle happened! I used kmsgrab as the input device and immediately I was able to record flawlessly 4K gameplay! Of course I tried different settings to make it faster and I ended up with the following command

LIBVA_DRIVER_NAME=radeonsi ffmpeg -vaapi_device /dev/dri/renderD128 -device /dev/dri/card1 -framerate 60 -thread_queue_size 140048 -f kmsgrab -i - -vf 'hwmap=derive_device=vaapi,crop=3840:1600:0:1600,scale_vaapi=w=3840:h=1600:format=nv12' -c:v hevc_vaapi -sei hdr -qp:v 0 ~/Videos/screen.mp4

Now this command I used specifically for my computer so let me decipher and explain its usage

Before the actual command we define the system variable

LIBVA_DRIVER_NAME

this I used to specify into the Video Acceleration API which driver will be used. For my case as I wanted to use my AMD GPU the driver was radeonsi.

Given the fact that we want to enable Video Acceleration – meaning we want to use our GPU with FFMPEG – we have to specify which card FFMPEG will use

-vaapi_device <device path>

My device path was /dev/dri/renderD128.

Moving along, I had to increase the thread_queue_size to a larger number as I was getting few warning messages about it.

Other settings here like the framerate etc are self-explanatory. The most important thing that you need to calculate though is how to tell FFMPEG what to record, especially if you have multiple monitors like me.

On this computer at this time I had 2x monitors with a 3840×1600 resolution each. So if I haven’t added the crop=3840:1600:0:1600,scale_vaapi=w=3840:h=1600 options I would have gotten a nice video file with the recording of both my screens.

The trick here is to calculate your overall resolution and then use the crop and scale to define your recording.

My 2 monitors are stacked up vertically, so my total width is 3840 and total height is 3200

For my setup I specify a video recording window of W,H = 3840:1600 with an absolute position to start recording at W,H = 0:1600

I also specify the following parameter to get almost lossless quality (output is now a large file)

-qp:v 0

Before you run the command we need to grant the CAP_SYS_ADMIN privilege to the FFMPEG binary

sudo setcap cap_sys_admin+ep /usr/bin/ffmpeg

Thats it!

Audio Recording

I believe by now you are wondering that I missed the audio recording! Well, yeah… I tried several encoders but if I tried to record video and audio at the same time with the same ffmpeg command I run into performance issues, mostly on the audio part!

And then I thought, I am going to anyway do things via command line, so whats the issue? I can easily separate them and join them together later on!

The audio command I used

ffmpeg -thread_queue_size 140048 -f pulse -ac 2 -i alsa_output.pci-0000_0a_00.3.iec958-stereo.monitor  ~/Videos/audio.opus

Its very important to use pulse + alsa as otherwise my tests would fail.

This way you can use the monitor device of your output audio device to capture the audio playing in your speakers!

My device is alsa_output.pci-0000_0a_00.3.iec958-stereo.monitor mind the .monitor at the end. You can get a full list of your audio devices and find yours by issuing the command

pactl list

Using Tmux to rule the recordings

The final touch was to find a way to manage both recordings and auto start them at the same time. Thank god we are on a Unix-based operating system, lots of options! I picked tmux to achieve this.

I created a very simple script to start both recordings at the same time and save them on a path specified via command line

#!/bin/bash

if [ "$1" = "" ]; then

	echo "you need to specify project name";
	exit 1;

else 

	mkdir ~/Videos/$1;
	if [ "$?" = "0" ]; then

		echo "created directory ~/Videos/${1}";

	else 

		echo "cannot create directory ~/Videos/${1}";
		exit;

	fi

fi

tmux new-session -d
tmux set-option remain-on-exit on
# make sure to change your driver/device paths and adjust crop/scale dimensions
tmux split-window "LIBVA_DRIVER_NAME=radeonsi ffmpeg -vaapi_device /dev/dri/renderD128 -device /dev/dri/card1 -framerate 60 -thread_queue_size 140048 -f kmsgrab -i - -vf 'hwmap=derive_device=vaapi,crop=3840:1600:0:1600,scale_vaapi=w=3840:h=1600:format=nv12' -c:v hevc_vaapi -sei hdr -qp:v 0 ~/Videos/${1}/screen.mp4"
# make sure to change your audio monitor device to match your setup
tmux split-window "ffmpeg -thread_queue_size 140048 -f pulse -ac 2 -i alsa_output.pci-0000_0a_00.3.iec958-stereo.monitor  ~/Videos/${1}/audio.opus"

# uncomment and edit this line if you want to also record from your camera
#tmux split-window "ffmpeg -f v4l2 -framerate 30 -video_size 1920x1080 -i /dev/video0 ~/Videos/${1}/cam.mkv"

If everything went as planned, you should be able to modify and execute the script above. You can then attach on the newly created tmux session and you will be able to stop the FFMPEG processes whenever you are done recording.

Combining Recordings

Now you should have 2 files generated under ~/Videos/<project name>/

For a very simple editing I use the most recent version of OpenShot. This way I am able to just drag and drop the files there and sync them out. I created the following video with the process described on this post.

4K Gameplay On Linux