Search code examples
pythonpynput

Speeding up Screen Captures in While Loops


I'm new to python and I'm trying to make a bot to play FNF. Obviously this means I need a bot that's fast, but my code runs really slow. I know this is because the processes I'm doing are quite heavy, but I don't know how to speed it up.

from pynput.keyboard import Key, Controller
import PIL.ImageGrab
import time

keyPresser = Controller()

while True:

    pic = PIL.ImageGrab.grab((2000, 400, 2001, 401))
    pic2 = pic.convert("RGB") 
    rgbPixelValue = pic2.getpixel((0, 0))
    if rgbPixelValue != (134, 163, 173):
        keyPresser.press(Key.left)
    
    print(rgbPixelValue)

Solution

  • Your problem seems to be that you are calling .press(). However, I think you actually want to press and release the key. This can be done by calling keyPresser.release(Key.left) directly after calling .press() or by just calling keyPresser.tap(Key.left). The current speed at which it is repeating is probably just the repeat limit define by your OS.

    Edit: Turns out ImageGrab is just too slow (it uses a system command and the filesystem). You could use it with some form of multithreading (like concurrent.futures), but you should probably use something designed for fast capture. A quick google search turns up mss which is much faster:

    from pynput.keyboard import Key, Controller
    from mss import mss
    from PIL import Image
    
    keyPresser = Controller()
    
    with mss() as sct:
        for i in range(100):
            pic = sct.grab((200, 400, 201, 401))
            pic2 = Image.frombytes("RGB", pic.size, pic.bgra, "raw", "BGRX")
            rgbPixelValue = pic2.getpixel((0, 0))
            if rgbPixelValue != (134, 163, 173):
                keyPresser.tap(Key.left)
            
            print(rgbPixelValue)
    

    This (appears to) achieves about 100 iterations per second on my computer.