1

I am trying to do a share screen using python and pygame, and the screenshots I take with d3dshot. Does anyone have an idea How can I make it better and increase the frames per second?

This is my code: Server - share the screen with the client

""" Server """
from socket import socket
from threading import Thread
import pyautogui
import cv2
import numpy as np
import d3dshot
from lz4.frame import compress


WIDTH, HEIGHT = pyautogui.size()


def retreive_screenshot(conn):
    d = d3dshot.create(capture_output="numpy")

    while 'recording':
        img = d.screenshot()

        img = cv2.resize(img, (0, 0), fx=0.5, fy=0.5)

        img = compress(img, 10)


        # Send the size of the pixels length
        size = len(img)
        size_len = (size.bit_length() + 7) // 8
        conn.send(bytes([size_len]))

        # Send the actual pixels length
        size_bytes = size.to_bytes(size_len, 'big')
        conn.send(size_bytes)

         # Send pixels
        conn.sendall(img)


def main(host='0.0.0.0', port=5000):
    sock = socket()
    sock.bind((host, port))
    try:
        sock.listen(5)
        print('Server started.')

        while 'connected':
            conn, addr = sock.accept()
            print('Client connected IP:', addr)
            thread = Thread(target=retreive_screenshot, args=(conn,))
            thread.start()
    finally:
        sock.close()


if __name__ == '__main__':
    main()

Client - get the screen from the server and show the server screen

""" Client """
from socket import socket
from lz4.frame import decompress
import numpy as np
import pygame
import cv2

WIDTH = 1600
HEIGHT = 900

def recvall(conn, length):
    """ Retreive all pixels. """

    buf = b''
    while len(buf) < length:
        data = conn.recv(length - len(buf))
        if not data:
            return data
        buf += data
    return buf


def main(host='127.0.0.1', port=5000):
    pygame.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    watching = True

    sock = socket()
    sock.connect((host, port))
    try:
        while watching:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    watching = False
                    break

            # Retreive the size of the pixels length, the pixels length and pixels
            size_len = int.from_bytes(sock.recv(1), byteorder='big')
            size = int.from_bytes(sock.recv(size_len), byteorder='big')
            img = decompress(recvall(sock, size))

            img = np.frombuffer(img, np.uint8)
            img = img.reshape((int(HEIGHT * 0.5), -1, 3))
            img = cv2.resize(img, (0, 0), fx=2, fy=2).tobytes()

            # Create the Surface from raw pixels
            img = pygame.image.fromstring(img, (WIDTH, HEIGHT), 'RGB')

            # Display the picture
            screen.blit(img, (0, 0))
            pygame.display.flip()
    finally:
        sock.close()


if __name__ == '__main__':
    main()
Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
User11
  • 11
  • 1
  • 1
    if you use `cv2` / `numpy` in server to get screen then maybe you should also use `cv2` / `numpy` in client to display it (instead of using `pygame`) – furas Mar 01 '21 at 20:06
  • 1
    maybe you should compress it as `JPG` - maybe it will be smaller and it will have to send more data - so will have more time to get more frames. Some tools to share screen make even more complex method - they send only this part of screen which was changed. – furas Mar 01 '21 at 20:11

0 Answers0