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.