Skip to content

Commit 51b2bfc

Browse files
authored
fix(demo): crop to a multiple of two. (#474)
To accommodate 4:2:0 subsampling, libx264 and libx265 require the video size to be a multiple of two. Add that behavior, with a flag to adjust it in the full demo.
1 parent 0c73441 commit 51b2bfc

2 files changed

Lines changed: 23 additions & 0 deletions

File tree

demos/video-capture-simple.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ def main() -> None:
7171
with mss.mss() as sct:
7272
monitor = sct.monitors[1]
7373

74+
# Because of how H.264 video stores color information, libx264 requires the video size to be a multiple of
75+
# two.
76+
monitor["width"] = (monitor["width"] // 2) * 2
77+
monitor["height"] = (monitor["height"] // 2) * 2
78+
7479
with av.open(FILENAME, "w") as avmux:
7580
# The "avmux" object we get back from "av.open" represents the MP4 file. That's a container that holds
7681
# the video, as well as possibly audio and more. These are each called "streams". We only create one

demos/video-capture.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)