0

I wrote the following script to capture both the screen and the audio from the microphone, both lossless from my laptop:

#!/bin/bash

d=$(date +"%Y%m%d_%-H%M")
dimensions=$(xdpyinfo |grep dimensions| awk '{print $2}';)

ffmpeg -f x11grab -r 25 -s "${dimensions}" -i "${DISPLAY}" -f alsa -ac 2 -i default -c:v libx264rgb -crf 0 -color_range 2 -preset ultrafast -c:a pcm_s16le -strict -2 "${d}.mkv"

The sound becomes very intermittent when setting to a very low number of frames per second (the sound practically disappears when r is set to 7) and it improves substantially to an acceptable quality with -r set to 50 or higher. This behaviour is also present with lossy capturing of the screen and audio as with ffmpeg -f alsa -ac 2 -i default -f x11grab -s "${dimensions}" -r 7 -i "${DISPLAY}" "${d}.mkv"
Why does the -r parameter influence the quality of the sound? Is the syntax of my script incorrect? When I record the audio without screencasting, either ffmpeg -f alsa -ac 2 -i default "${d}.mp4" or ffmpeg -f alsa -ac 2 -i default "${d}.wav" works fine giving me satisfying quality of the audio. The output from recording with ffmpeg -f x11grab -r 25 -s "${dimensions}" -i "${DISPLAY}" -f alsa -ac 2 -i default -c:v libx264rgb -crf 0 -color_range 2 -preset ultrafast -c:a pcm_s16le -strict -2 "${d}.mkv" is:

ffmpeg version 5.1.4-0+deb12u1 Copyright (c) 2000-2023 the FFmpeg developers
  built with gcc 12 (Debian 12.2.0-14)
  configuration: --prefix=/usr --extra-version=0+deb12u1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libglslang --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librist --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --disable-sndio --enable-libjxl --enable-pocketsphinx --enable-librsvg --enable-libmfx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-libplacebo --enable-librav1e --enable-shared
  libavutil      57. 28.100 / 57. 28.100
  libavcodec     59. 37.100 / 59. 37.100
  libavformat    59. 27.100 / 59. 27.100
  libavdevice    59.  7.100 / 59.  7.100
  libavfilter     8. 44.100 /  8. 44.100
  libswscale      6.  7.100 /  6.  7.100
  libswresample   4.  7.100 /  4.  7.100
  libpostproc    56.  6.100 / 56.  6.100
[x11grab @ 0x55d20fe24040] Stream #0: not enough frames to estimate rate; consider increasing probesize
Input #0, x11grab, from ':0':
  Duration: N/A, start: 1707046868.487852, bitrate: 1658880 kb/s
  Stream #0:0: Video: rawvideo (BGR[0] / 0x524742), bgr0, 1920x1080, 1658880 kb/s, 25 fps, 1000k tbr, 1000k tbn
Guessed Channel Layout for Input Stream #1.0 : stereo
Input #1, alsa, from 'default':
  Duration: N/A, start: 1707046868.768038, bitrate: 1536 kb/s
  Stream #1:0: Audio: pcm_s16le, 48000 Hz, stereo, s16, 1536 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264rgb))
  Stream #1:0 -> #0:1 (pcm_s16le (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
[libx264rgb @ 0x55d20fe7e9c0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264rgb @ 0x55d20fe7e9c0] profile High 4:4:4 Predictive, level 4.0, 4:4:4, 8-bit
[libx264rgb @ 0x55d20fe7e9c0] 264 - core 164 r3095 baee400 - H.264/MPEG-4 AVC codec - Copyleft 2003-2022 - http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=0:0:0 analyse=0:0 me=dia subme=0 psy=0 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=0 chroma_qp_offset=0 threads=24 lookahead_threads=4 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=250 keyint_min=25 scenecut=0 intra_refresh=0 rc=cqp mbtree=0 qp=0
Output #0, matroska, to '20240204_1241-loseless.mkv':
  Metadata:
    encoder         : Lavf59.27.100
  Stream #0:0: Video: h264 (H264 / 0x34363248), bgr0(pc, progressive), 1920x1080, q=2-31, 25 fps, 1k tbn
    Metadata:
      encoder         : Lavc59.37.100 libx264rgb
    Side data:
      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A
  Stream #0:1: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, stereo, s16, 1536 kb/s
    Metadata:
      encoder         : Lavc59.37.100 pcm_s16le
frame=    1 fps=0.0 q=0.0 size=       1kB time=00:00:00.02 bitrate= 286.5kbits/sframe=   21 fps=0.0 q=0.0 size=       1kB time=00:00:00.02 bitrate= 286.5kbits/s[alsa @ 0x55d20fe30440] Thread message queue blocking; consider raising the thread_queue_size option (current value: 8)
[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=   33 fps= 32 q=0.0 size=       1kB time=00:00:00.81 bitrate=   7.3kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=   46 fps= 30 q=0.0 size=       1kB time=00:00:00.82 bitrate=   7.3kbits/sframe=   58 fps= 28 q=0.0 size=       1kB time=00:00:01.58 bitrate=   3.8kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=   71 fps= 28 q=0.0 size=       1kB time=00:00:02.34 bitrate=   2.6kbits/sframe=   84 fps= 28 q=0.0 size=    5376kB time=00:00:02.34 bitrate=18780.5kbits/[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=   96 fps= 27 q=0.0 size=    5376kB time=00:00:03.14 bitrate=14003.2kbits/[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  109 fps= 27 q=0.0 size=    5376kB time=00:00:03.93 bitrate=11186.2kbits/frame=  122 fps= 27 q=0.0 size=    5376kB time=00:00:03.93 bitrate=11186.2kbits/[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  134 fps= 26 q=0.0 size=    5376kB time=00:00:04.70 bitrate=9358.3kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  147 fps= 26 q=0.0 size=    5376kB time=00:00:04.88 bitrate=9020.9kbits/sframe=  160 fps= 26 q=0.0 size=    5376kB time=00:00:05.49 bitrate=8010.2kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  173 fps= 26 q=0.0 size=    5376kB time=00:00:06.25 bitrate=7039.7kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  185 fps= 26 q=0.0 size=    5376kB time=00:00:06.39 bitrate=6889.9kbits/sframe=  198 fps= 26 q=0.0 size=    5376kB time=00:00:07.02 bitrate=6268.2kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
[matroska @ 0x55d20fe7d800] Non-monotonous DTS in output stream 0:1; previous: 7108, current: 7104; changing to 7108. This may result in incorrect timestamps in the output file.
[matroska @ 0x55d20fe7d800] Non-monotonous DTS in output stream 0:1; previous: 7173, current: 7170; changing to 7173. This may result in incorrect timestamps in the output file.
frame=  211 fps= 26 q=0.0 size=    7424kB time=00:00:07.82 bitrate=7776.2kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  223 fps= 26 q=0.0 size=    7424kB time=00:00:07.97 bitrate=7626.0kbits/sframe=  236 fps= 26 q=0.0 size=    7424kB time=00:00:08.58 bitrate=7088.3kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  248 fps= 26 q=0.0 size=    7424kB time=00:00:09.34 bitrate=6510.1kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  261 fps= 26 q=0.0 size=    7424kB time=00:00:09.40 bitrate=6469.2kbits/sframe=  273 fps= 26 q=0.0 size=    7424kB time=00:00:10.14 bitrate=5996.0kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  286 fps= 26 q=0.0 size=    8960kB time=00:00:10.93 bitrate=6711.2kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  299 fps= 26 q=0.0 size=    8960kB time=00:00:10.94 bitrate=6703.8kbits/sframe=  312 fps= 26 q=0.0 size=    8960kB time=00:00:11.69 bitrate=6276.2kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  324 fps= 26 q=0.0 size=    8960kB time=00:00:12.46 bitrate=5888.5kbits/sframe=  337 fps= 26 q=0.0 size=    8960kB time=00:00:12.46 bitrate=5888.5kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  349 fps= 26 q=0.0 size=    8960kB time=00:00:13.26 bitrate=5533.0kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  362 fps= 26 q=0.0 size=    8960kB time=00:00:13.47 bitrate=5445.9kbits/s[matroska @ 0x55d20fe7d800] Non-monotonous DTS in output stream 0:1; previous: 13457, current: 13451; changing to 13457. This may result in incorrect timestamps in the output file.
[matroska @ 0x55d20fe7d800] Non-monotonous DTS in output stream 0:1; previous: 13457, current: 13453; changing to 13457. This may result in incorrect timestamps in the output file.
frame=  374 fps= 25 q=0.0 size=    8960kB time=00:00:14.05 bitrate=5220.9kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  387 fps= 25 q=0.0 size=    8960kB time=00:00:14.82 bitrate=4952.8kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  400 fps= 25 q=0.0 size=    8960kB time=00:00:15.04 bitrate=4878.7kbits/sframe=  413 fps= 25 q=0.0 size=   11776kB time=00:00:15.57 bitrate=6193.0kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  425 fps= 25 q=0.0 size=   11776kB time=00:00:16.33 bitrate=5905.7kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.
frame=  438 fps= 25 q=0.0 size=   11776kB time=00:00:16.48 bitrate=5853.3kbits/sframe=  451 fps= 25 q=0.0 size=   17408kB time=00:00:17.09 bitrate=8340.0kbits/s[alsa @ 0x55d20fe30440] ALSA buffer xrun.


[q] command received. Exiting.

frame=  455 fps= 25 q=-1.0 Lsize=   21617kB time=00:00:18.16 bitrate=9750.7kbits/s speed=1.01x    
video:20715kB audio:896kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.025721%
[libx264rgb @ 0x55d20fe7e9c0] frame I:2     Avg QP: 0.00  size:950424
[libx264rgb @ 0x55d20fe7e9c0] frame P:453   Avg QP: 0.00  size: 42629
[libx264rgb @ 0x55d20fe7e9c0] mb I  I16..4: 100.0%  0.0%  0.0%
[libx264rgb @ 0x55d20fe7e9c0] mb P  I16..4: 56.4%  0.0%  0.0%  P16..4:  0.1%  0.0%  0.0%  0.0%  0.0%    skip:43.5%
[libx264rgb @ 0x55d20fe7e9c0] coded y,u,v intra: 1.8% 1.8% 2.0% inter: 0.1% 0.1% 0.1%
[libx264rgb @ 0x55d20fe7e9c0] i16 v,h,dc,p: 98%  2%  0%  0%
[libx264rgb @ 0x55d20fe7e9c0] kb/s:9323.81

The laptop (Debian based system, utilizing X11 for the window manager, 16GB of RAM, Intel i7-10870H CPU 2.20GHz - 16 cores, NVIDIA Corporation GA106M [GeForce RTX 3060 Mobile / Max-Q]) does not lack compute, the loading averages when not recording are: 0.16, 0.14, 0.38.

1 Answer 1

1

For x11grab you should be using -framerate and not -r.

Here is what you should use:

ffmpeg -f x11grab -framerate 25 -s ${dimensions} -i ${DISPLAY} -f alsa -ac 2 -i default -c:v libx264rgb -crf 0 -color_range 2 -vf mpdecimate=0:1:1:1 -preset superfast -c:a flac ${d}.mkv

I also changed the preset to superfast to enable CABAC coding which improves compression ratio significantly and in my experience will never be a bottleneck for screen recording.

I also added a video filter which will deduplicate frames that are 100% identical and create a VFR video (very very useful when screen recording and lets you increase the framerate a lot without increasing system load or video bitrate much). It's still lossless and has identical output to a CFR video with duplicated frames.

Finally I changed the audio codec to flac. It is lossless and it's much better to use flac than raw pcm.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.