Created
June 29, 2021 16:13
-
-
Save alexer/36c7f4e399a04f2f253f4667bdcc99af to your computer and use it in GitHub Desktop.
Like import from ImageMagick, but for video. Because someone wondered if this exists - I don't know if it did, but now it does. No options. Requires ffmpeg and python-xlib.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Xlib.display | |
from Xlib import X, Xcursorfont | |
def XSelectWindow(dpy): | |
screen = dpy.screen() | |
root = screen.root | |
gc = root.create_gc(background=screen.black_pixel, foreground=screen.white_pixel, function=X.GXinvert, subwindow_mode=X.IncludeInferiors) | |
font = dpy.open_font('cursor') | |
cursor = font.create_glyph_cursor(font, Xcursorfont.crosshair, Xcursorfont.crosshair+1, (65535, 65535, 65535), (0, 0, 0)) | |
try: | |
root.grab_pointer(0, X.ButtonPressMask|X.ButtonReleaseMask|X.ButtonMotionMask, X.GrabModeSync, X.GrabModeAsync, root, cursor, X.CurrentTime) | |
try: | |
dpy.grab_server() | |
start = None | |
w = h = 0 | |
pressed = 0 | |
while start is None or pressed: | |
rect = w*w + h*h > 9 | |
# Draw rectangle | |
if rect: | |
root.rectangle(gc, x, y, w, h) | |
dpy.allow_events(X.SyncPointer, X.CurrentTime) | |
# Fetch a button press/release or the most recent MotionNotify | |
ev = dpy.next_event() | |
for i in range(dpy.pending_events()): | |
if ev.type in (X.ButtonPress, X.ButtonRelease): | |
break | |
# I'm not sure if we can receive any other events, but it doesn't hurt to be safe | |
ev_ = dpy.next_event() | |
if ev_.type in (X.ButtonPress, X.ButtonRelease, X.MotionNotify): | |
ev = ev_ | |
# Clear rectangle | |
if rect: | |
root.rectangle(gc, x, y, w, h) | |
if ev.type == X.ButtonPress: | |
start = x, y = ev.event_x, ev.event_y | |
pressed += 1 | |
elif ev.type == X.ButtonRelease: | |
pressed -= 1 | |
elif ev.type == X.MotionNotify: | |
(x, w), (y, h) = sorted((start[0], ev.event_x)), sorted((start[1], ev.event_y)) | |
w -= x | |
h -= y | |
# Make sure rectangle clear goes through (not quite sure why the rectangle persists [at least for me] without this. python-xlib doesn't flush on quit?) | |
dpy.flush() | |
finally: | |
dpy.ungrab_server() | |
finally: | |
dpy.ungrab_pointer(X.CurrentTime) | |
return x, y, w+1, h+1 | |
if __name__ == '__main__': | |
import sys, os | |
if len(sys.argv) != 2: | |
print('usage: %s FILE' % sys.argv[0], file=sys.stderr) | |
sys.exit(-1) | |
dpy = Xlib.display.Display() | |
x, y, w, h = XSelectWindow(dpy) | |
display = dpy.get_display_name() | |
fname = sys.argv[1] | |
os.execvp('ffmpeg', ['ffmpeg', '-video_size', '%dx%d' % (w, h), '-framerate', '25', '-f', 'x11grab', '-i', '%s+%d,%d' % (display, x, y), fname]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment