Skip to content

Instantly share code, notes, and snippets.

@alexer
Created June 29, 2021 16:13
Show Gist options
  • Save alexer/36c7f4e399a04f2f253f4667bdcc99af to your computer and use it in GitHub Desktop.
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.
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