@@ -397,6 +397,12 @@ def main() -> None:
397397 metavar = "LEFT,TOP,RIGHT,BOTTOM" ,
398398 help = "region to capture as comma-separated coordinates" ,
399399 )
400+ parser .add_argument (
401+ "-2" ,
402+ "--region-crop-to-multiple-of-two" ,
403+ action = argparse .BooleanOptionalAction ,
404+ help = "crop the capture region to a multiple of two, as required by some codecs (default: only for libx264 and libx265)" ,
405+ )
400406 parser .add_argument (
401407 "-c" ,
402408 "--codec" ,
@@ -426,6 +432,7 @@ def main() -> None:
426432 codec = args .codec
427433 filename = args .output
428434 duration_secs = args .duration_secs
435+ region_crop_to_multiple_of_two = args .region_crop_to_multiple_of_two
429436
430437 with mss .mss () as sct :
431438 if args .region :
@@ -439,6 +446,17 @@ def main() -> None:
439446 else :
440447 monitor = sct .monitors [args .monitor ]
441448
449+ # Some codecs, such as libx264, require the region to be a multiple of 2, to get the chroma subsampling right.
450+ # Others, such as h264_nvenc, do not; they'll pad to get the subsampling region, and add flags to the stream
451+ # to tell the viewer to crop accordingly.
452+ if region_crop_to_multiple_of_two is None :
453+ # The user didn't specify; choose the default. We haven't tested many codecs, but we know these require
454+ # it (at least, when using 4:2:0 subsampling).
455+ region_crop_to_multiple_of_two = codec in {"libx264" , "libx265" }
456+ if region_crop_to_multiple_of_two :
457+ monitor ["width" ] = (monitor ["width" ] // 2 ) * 2
458+ monitor ["height" ] = (monitor ["height" ] // 2 ) * 2
459+
442460 # We don't pass the container format to av.open here, so it will choose it based on the extension: .mp4, .mkv,
443461 # etc.
444462 with av .open (filename , "w" ) as avmux :
0 commit comments