Contents

monitor screen remotely

1. Server

to be installed on the Windows machine which screen will be seen remotely

Notice the file must be named as ‘xxx.pyw’ because we need to use pythonw.exe to run this app. With pythonw, the terminal windows will not pop up.

To enable the app autostarting when the host Windows started, run these steps:

  1. Win+R to open the Run window
  2. Input command ‘shell:autostart’
  3. copy this file xxx.pyw into the Startup folder

Reference: https://support.microsoft.com/en-us/windows/add-an-app-to-run-automatically-at-startup-in-windows-10-150da165-dcd9-7230-517b-cf3c295d89dd

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# pip install numpy pillow
import numpy as np
import socket
import pickle,struct

from PIL import ImageGrab, Image

def main():
    server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    port = 9999
    socket_address = ('0.0.0.0', port)
    server_socket.bind(socket_address)
    basewidth = 1024
    while True:
        server_socket.listen(5)
        client_socket, addr = server_socket.accept()
        try:
            if client_socket:
                while True:
                    image = ImageGrab.grab()
                    wpercent = (basewidth/float(image.size[0]))
                    hsize = int((float(image.size[1])*float(wpercent)))
                    resized = image.resize((basewidth,hsize), Image.Resampling.LANCZOS)
                    frame = np.array(resized)
                    data = pickle.dumps(frame)
                    message = struct.pack("Q",len(data))+data
                    client_socket.sendall(message)
        except Exception as e:
            pass
            #print(e)
        finally:
            client_socket.close()
            #server_socket.close()

if __name__ == '__main__':
    main()

2. Client

Run this app on another machine B to monitor the machine A after machine A has been started

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# pip install opencv-python

import socket
import pickle
import struct

import cv2

IP_ADDRESSES = {
    0: ['10.0.0.19', 'user1'],
    1: ['10.0.0.10', 'user2']
}

def main(index=0):
    """primary client
    """
    # create socket
    client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    host_ip = IP_ADDRESSES[index][0] # ip address
    the_user = IP_ADDRESSES[index][1]  # the user
    port = 9999
    client_socket.connect((host_ip, port)) # a tuple
    data = b""
    payload_size = struct.calcsize("Q")
    while True:
        while len(data) < payload_size:
            packet = client_socket.recv(4*1024) # 4K
            if not packet:
                break
            data+=packet
        packed_msg_size = data[:payload_size]
        data = data[payload_size:]
        msg_size = struct.unpack("Q",packed_msg_size)[0]

        while len(data) < msg_size:
            data += client_socket.recv(4*1024)
        frame_data = data[:msg_size]
        data  = data[msg_size:]
        frame = pickle.loads(frame_data)
        cv2.imshow(f'{the_user}', frame)
        # quit when key 'q' is pressed
        #if cv2.waitKey(1) & 0xFF == ord('q'):
        # quit when key 'ESC' is pressed
        if cv2.waitKey(1) & 0xFF == 27:
            break
    client_socket.close()

if __name__ == '__main__':
    main(index=1)

3. broadcast to http directly. Client is not needed

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from flask import Flask, Response

import numpy as np
from PIL import ImageGrab
import cv2

app = Flask(__name__)

# Define a class for capturing screen and serving the video
class ScreenCapture:
    def __init__(self):
        self.is_capturing = False

    def start_capture(self):
        while True:
            #im = ImageGrab.grab().convert("RGB") 
            #img_byte_arr = io.BytesIO()
            #im.save(img_byte_arr, format='PNG')
            #frame = img_byte_arr.getvalue()
            frame = np.array(ImageGrab.grab())
            frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
            ret, buffer = cv2.imencode('.jpg', frame)
            frame = buffer.tobytes()
            yield (b'--frame\r\n'
                    b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

# Initialize the screen capture object
screen_capture = ScreenCapture()

# Define FastAPI endpoints
@app.route('/')
def get_video_feed():
    headers = {'Content-Type': 'multipart/x-mixed-replace; boundary=frame'}
    return Response(screen_capture.start_capture(), headers=headers)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8000, debug=True)