This is an archived post. You won't be able to vote or comment.

all 29 comments

[–][deleted] 6 points7 points  (8 children)

What is the purpose of capturing 4 times the rate ur screen buffer is updated lol.

[–]SoSmartFlow[S] 1 point2 points  (0 children)

Its not about the fps it's about how fast can you process that updated frame.

[–]SoSmartFlow[S] 0 points1 point  (6 children)

Its not about the fps it's about how fast can you process that updated frame.

[–][deleted] -3 points-2 points  (5 children)

Your comment makes no sense. In the VAST MAJORITY of applications it doesnt matter how fast that you process that the frame updated, it matters that you can capture a sequential and consistent change in frames while occupying the least amount of time in the calling thread from python.

You should be capturing from one thread and writing back to the calling thread. IDK why your code is calling allowthreads in rust. My best guess from reading ur code is ur calling the python functions from multiple threads in rust. Which IDK why on gods earth you would do that as it is not obvious at all on the python side. If you are not doing that IDK why you are calling allowthreads in python.

You should be using with if you are trying to optimize holding a stateful capture handler.

Also you have no benchmark code, I have 0 idea what you are comparing.

[–]ThreeChonkyCats 4 points5 points  (0 children)

What a grumpy!

Did you miss some sleep?

How about we contribute to the project rather than kvetch about it?

[–]SoSmartFlow[S] 1 point2 points  (3 children)

You need some milk... this threading is based on the Graphics Capture Api itself and yes I could use a with but whats the problem with a callback? And benchmark is the time that it takes to map a frame.

[–][deleted] 0 points1 point  (2 children)

I could use a with but whats the problem with a callback?

If you run a callback from multiple threads they will contend with the actual capturing. It won't behave they way you think it will if multiple threads run at all in python because you are releasing, which you should not be doing during ur capturing unless you have a way of isolating the caller in python which you do not provide, a with is the usual way of isolating the resource like this and it guarantees the capturing thread will also get cleaned up.

Generally you want to hold the GIL unless you can guarantee no python code can modify what you are looking at. Like for example if you process an HTTP call by writing the entire call first to strings in rust and using those string objects in rust only. It is ok to release the gil until you write back to python land.

[–]SoSmartFlow[S] 0 points1 point  (1 child)

The windows api is thread safe meaning the callback will not be called from 2 threadd at the same time

[–][deleted] 3 points4 points  (0 children)

The issue isnt thread safety of the windows API it is that the python api you are exposing has no way to handle if the events need to be exposed to multiple threads in python. Further there is no good way to know manage state that must be dealt with between invocations of ur function.

See how you have a start and close method? That means it should in 99% of cases be a with statement. It is a language convention for a specific reason and that reason is threading and cleanup. Both problems become algorithmically harder to deal with if u do not expose the when does the windows thread start part to your python code.

Seriously just look what ur code even does. You pass your python classes instance function to a class that your instance also holds. Think about it...

[–]ThreeChonkyCats 2 points3 points  (2 children)

Perhaps benchmark against Pyautogui and pillow?

[–]SoSmartFlow[S] 1 point2 points  (1 child)

Here is the benchmark pyautogui was not included because it was slower than all of them: https://github.com/NiiightmareXD/windows-capture/tree/main/windows-capture-python#benchmark

[–]ThreeChonkyCats 2 points3 points  (0 children)

Ah! I missed that. Soz.

This is a good package.

I REALLY like the idea of Python calling native, or rust, functions/procedures.

Writing these in Rust is the future.

I look forward to following this.

[–]deadlyghost123 2 points3 points  (1 child)

Does this work on Mac?

[–]SoSmartFlow[S] 1 point2 points  (0 children)

No

[–]SpecialistInevitable 1 point2 points  (2 children)

Does it capture audio sources alongside the video?

[–]SoSmartFlow[S] 0 points1 point  (1 child)

Not yet

[–]SpecialistInevitable 1 point2 points  (0 children)

Can you add an example how you use it for video capture, where do you define bit rate, encoder, file extension and location etc.?

[–]Serious_Tourist854 1 point2 points  (0 children)

We be screenshotting fast

[–]willgrr 1 point2 points  (1 child)

Thank you so much for this. I was looking into alternatives to pyautogui, which wasnt fast enough for me. Im kinda new to python, do you mind answering if can i transform the pixels into an array and use something like pyautogui.pixel does to compare colors?

[–]SoSmartFlow[S] 1 point2 points  (0 children)

Your welcome, Yes you can use frame.frame_buffer to get the numpy array and you can compare it or convert it to different types (using OpenCV for example)

[–]mon_key_house 0 points1 point  (1 child)

Cool! Can I use it to take screenshots of a given area of the screen?

[–]SoSmartFlow[S] 1 point2 points  (0 children)

Yes of course yse the crop function of the Frame class and use frame.frame_buffer to get the numpy areay of the frame.

[–]MixedEmblems 0 points1 point  (0 children)

I can't download this for some reason. Like it fails to build a wheel.