What ffmpeg settings to get the best possible video resolution/framerate that my webcam is capable of?

I want to record the best possible video file (in terms of resolution/framerate/colors) from my webcam.
Right now I am using this command:

ffmpeg -f v4l2 -framerate 25 -video_size 640x480 -i /dev/video0 output.mkv

My webcam seems to support this:

$ ffmpeg -f v4l2 -list_formats all -i /dev/video0
…
[video4linux2,v4l2 @ 0xf07d80] Raw       : yuyv422 : YUV 4:2:2 (YUYV) : 640x480 160x120 176x144 320x176 320x240 352x288 432x240 544x288 640x360
[video4linux2,v4l2 @ 0xf07d80] Compressed:   mjpeg :            MJPEG : 640x480 160x120 176x144 320x176 320x240 352x288 432x240 544x288 640x360

I guess I got the resolution part, but how can I improve my command line to:

  • Use no compression (I suspect the current .mkv output is compressed)
  • Use the best framerate that the camera&computer is capable of, without duplicating frames either (no point saving the file at 100 fps if the webcam is not capable of capturing frames at that rate)
  • All ideas to further improve the video quality are welcome

Do you really want no compression? Uncompressed video would be very large. Or do you want no transcoding? Or lossless?

No compression can be achieved as mentioned at https://superuser.com/a/1302502/128124

First determine your available formats with:

v4l2-ctl --list-formats-ext

as mentioned at: How can I list the available video modes for a USB webcam in Linux?

The highest ones for me are:

        [0]: 'YUYV' (YUYV 4:2:2)
                Size: Discrete 1280x720
                        Interval: Discrete 0.100s (10.000 fps)
        [1]: 'MJPG' (Motion-JPEG, compressed)
                Size: Discrete 1280x720
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)

You can then also check:

ffmpeg -f v4l2 -list_formats all -i /dev/video0

which contains for my device:

video4linux2,v4l2 @ 0x5579b13df240] Raw       :     yuyv422 :           YUYV 4:2:2 : 640x480 320x180 320x240 352x288 424x240 640x360 848x480 960x540 1280x720
[video4linux2,v4l2 @ 0x5579b13df240] Compressed:       mjpeg :          Motion-JPEG : 640x480 320x180 320x240 352x288 424x240 640x360 848x480 960x540 1280x720

Then, If I record two 3.5 second very similar video of my making faces on the setup described at https://askubuntu.com/questions/348838/how-to-check-available-webcams-from-the-command-line/848390#848390 rev 18 with:

ffmpeg -y -f v4l2 -framerate 30 -video_size 1280x720 -input_format mjpeg -i /dev/video0 -c copy out.mjpeg.mkv
ffmpeg -y -f v4l2 -framerate 30 -video_size 1280x720 -input_format yuyv422 -i /dev/video0 -c copy out.yuyv422.mkv

the sizes are about:

  • 15MB
  • 60MB

and ffprobe confirms respectively:

    Stream #0:0: Video: mjpeg (Baseline), yuvj422p(pc, bt470bg/unknown/unknown), 1280x720, 30 fps, 30 tbr, 1k tbn, 1k tbc (default)
    Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 1280x720, 10 fps, 10 tbr, 1k tbn, 1k tbc (default)

Lossless is discussed at:

  • Lossless universal video format
  • https://stackoverflow.com/questions/11713882/lossless-ffmpeg-conversion-encoding
  • https://video.stackexchange.com/questions/7903/how-to-losslessly-encode-a-jpg-image-sequence-to-a-video-in-ffmpeg

Tested on Ubuntu 20.04, Lenovo ThinkPad P51.