feat:
--Layer 4 tcp only --Later webRTC
This commit is contained in:
commit
6907288be7
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
venv/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Ignore VSCode settings (optional)
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
9
readme.txt
Normal file
9
readme.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
screenReciever.py
|
||||||
|
this is used to capture images from screen and send using udp
|
||||||
|
ip address must be mentioned
|
||||||
|
only on local area network
|
||||||
|
|
||||||
|
screenSender.py
|
||||||
|
this will recieve the data from the reviever
|
||||||
|
|
||||||
|
uses opencv
|
||||||
91
screenCapt.py
Normal file
91
screenCapt.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import signal
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
from mss import mss
|
||||||
|
|
||||||
|
|
||||||
|
OUTPUT_FILE = Path("screen_recording.avi")
|
||||||
|
FPS = 20
|
||||||
|
MONITOR_NUMBER = 1
|
||||||
|
|
||||||
|
recording = True
|
||||||
|
|
||||||
|
|
||||||
|
def stop_recording(signum=None, frame=None):
|
||||||
|
global recording
|
||||||
|
recording = False
|
||||||
|
print("\nStopping recording safely...")
|
||||||
|
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, stop_recording)
|
||||||
|
signal.signal(signal.SIGTERM, stop_recording)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global recording
|
||||||
|
|
||||||
|
with mss() as sct:
|
||||||
|
monitor = sct.monitors[MONITOR_NUMBER]
|
||||||
|
|
||||||
|
width = monitor["width"]
|
||||||
|
height = monitor["height"]
|
||||||
|
|
||||||
|
# Video codecs generally prefer even dimensions.
|
||||||
|
width -= width % 2
|
||||||
|
height -= height % 2
|
||||||
|
|
||||||
|
# MJPG inside AVI is more resistant to corruption than MP4.
|
||||||
|
fourcc = cv2.VideoWriter_fourcc(*"MJPG")
|
||||||
|
|
||||||
|
writer = cv2.VideoWriter(
|
||||||
|
str(OUTPUT_FILE),
|
||||||
|
fourcc,
|
||||||
|
FPS,
|
||||||
|
(width, height),
|
||||||
|
)
|
||||||
|
|
||||||
|
if not writer.isOpened():
|
||||||
|
raise RuntimeError("Could not open VideoWriter")
|
||||||
|
|
||||||
|
print(f"Recording {width}x{height} at {FPS} FPS")
|
||||||
|
print("Press Ctrl+C once to stop safely.")
|
||||||
|
|
||||||
|
frame_interval = 1.0 / FPS
|
||||||
|
next_frame_time = time.perf_counter()
|
||||||
|
|
||||||
|
try:
|
||||||
|
while recording:
|
||||||
|
screenshot = sct.grab(
|
||||||
|
{
|
||||||
|
"left": monitor["left"],
|
||||||
|
"top": monitor["top"],
|
||||||
|
"width": width,
|
||||||
|
"height": height,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
frame = np.asarray(screenshot)
|
||||||
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2BGR)
|
||||||
|
|
||||||
|
writer.write(frame)
|
||||||
|
|
||||||
|
next_frame_time += frame_interval
|
||||||
|
sleep_time = next_frame_time - time.perf_counter()
|
||||||
|
|
||||||
|
if sleep_time > 0:
|
||||||
|
time.sleep(sleep_time)
|
||||||
|
else:
|
||||||
|
next_frame_time = time.perf_counter()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
writer.release()
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
|
||||||
|
print(f"Recording saved safely: {OUTPUT_FILE.resolve()}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
102
screenReciever.py
Normal file
102
screenReciever.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
LISTEN_IP = "0.0.0.0"
|
||||||
|
LISTEN_PORT = 5000
|
||||||
|
|
||||||
|
HEADER_SIZE = 4
|
||||||
|
MAX_FRAME_SIZE = 20 * 1024 * 1024 # 20 MB safety limit
|
||||||
|
|
||||||
|
|
||||||
|
def receive_exact(sock, size):
|
||||||
|
"""
|
||||||
|
Receive exactly 'size' bytes.
|
||||||
|
|
||||||
|
TCP recv() may return fewer bytes than requested,
|
||||||
|
so we keep receiving until the full frame arrives.
|
||||||
|
"""
|
||||||
|
data = bytearray()
|
||||||
|
|
||||||
|
while len(data) < size:
|
||||||
|
packet = sock.recv(size - len(data))
|
||||||
|
|
||||||
|
if not packet:
|
||||||
|
return None
|
||||||
|
|
||||||
|
data.extend(packet)
|
||||||
|
|
||||||
|
return bytes(data)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
|
||||||
|
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
server.bind((LISTEN_IP, LISTEN_PORT))
|
||||||
|
server.listen(1)
|
||||||
|
|
||||||
|
print(f"Waiting for sender on TCP port {LISTEN_PORT}...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
connection, address = server.accept()
|
||||||
|
|
||||||
|
with connection:
|
||||||
|
connection.setsockopt(
|
||||||
|
socket.IPPROTO_TCP,
|
||||||
|
socket.TCP_NODELAY,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"Sender connected from {address[0]}:{address[1]}")
|
||||||
|
print("Press Q in the video window to stop.")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
header = receive_exact(connection, HEADER_SIZE)
|
||||||
|
|
||||||
|
if header is None:
|
||||||
|
print("Sender disconnected.")
|
||||||
|
break
|
||||||
|
|
||||||
|
frame_size = struct.unpack("!I", header)[0]
|
||||||
|
|
||||||
|
if frame_size <= 0 or frame_size > MAX_FRAME_SIZE:
|
||||||
|
print(f"Invalid frame size: {frame_size}")
|
||||||
|
break
|
||||||
|
|
||||||
|
frame_data = receive_exact(connection, frame_size)
|
||||||
|
|
||||||
|
if frame_data is None:
|
||||||
|
print("Connection closed during frame reception.")
|
||||||
|
break
|
||||||
|
|
||||||
|
compressed_array = np.frombuffer(
|
||||||
|
frame_data,
|
||||||
|
dtype=np.uint8,
|
||||||
|
)
|
||||||
|
|
||||||
|
frame = cv2.imdecode(
|
||||||
|
compressed_array,
|
||||||
|
cv2.IMREAD_COLOR,
|
||||||
|
)
|
||||||
|
|
||||||
|
if frame is None:
|
||||||
|
print("Failed to decode frame.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
cv2.imshow("Remote Screen - Press Q to exit", frame)
|
||||||
|
|
||||||
|
if cv2.waitKey(1) & 0xFF == ord("q"):
|
||||||
|
break
|
||||||
|
|
||||||
|
finally:
|
||||||
|
server.close()
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
print("Receiver stopped.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
116
screenSender.py
Normal file
116
screenSender.py
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import signal
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import time
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
from mss import mss
|
||||||
|
|
||||||
|
|
||||||
|
RECEIVER_IP = "172.16.11.81" # Your friend's computer IP
|
||||||
|
RECEIVER_PORT = 5000
|
||||||
|
|
||||||
|
FPS = 15
|
||||||
|
JPEG_QUALITY = 55
|
||||||
|
MONITOR_NUMBER = 1
|
||||||
|
|
||||||
|
running = True
|
||||||
|
|
||||||
|
|
||||||
|
def stop_stream(signum=None, frame=None):
|
||||||
|
global running
|
||||||
|
running = False
|
||||||
|
print("\nStopping screen stream safely...")
|
||||||
|
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, stop_stream)
|
||||||
|
signal.signal(signal.SIGTERM, stop_stream)
|
||||||
|
|
||||||
|
|
||||||
|
def send_all(sock, data):
|
||||||
|
"""Send the complete byte sequence."""
|
||||||
|
view = memoryview(data)
|
||||||
|
|
||||||
|
while view and running:
|
||||||
|
bytes_sent = sock.send(view)
|
||||||
|
|
||||||
|
if bytes_sent == 0:
|
||||||
|
raise ConnectionError("TCP connection closed")
|
||||||
|
|
||||||
|
view = view[bytes_sent:]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print(f"Connecting to {RECEIVER_IP}:{RECEIVER_PORT}...")
|
||||||
|
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||||
|
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||||
|
sock.connect((RECEIVER_IP, RECEIVER_PORT))
|
||||||
|
|
||||||
|
print("Connected.")
|
||||||
|
print("Press Ctrl+C once to stop.")
|
||||||
|
|
||||||
|
with mss() as sct:
|
||||||
|
monitor = sct.monitors[MONITOR_NUMBER]
|
||||||
|
|
||||||
|
frame_interval = 1.0 / FPS
|
||||||
|
next_frame_time = time.perf_counter()
|
||||||
|
|
||||||
|
while running:
|
||||||
|
screenshot = sct.grab(monitor)
|
||||||
|
|
||||||
|
frame = np.asarray(screenshot)
|
||||||
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2BGR)
|
||||||
|
|
||||||
|
# Reduce resolution to lower bandwidth.
|
||||||
|
frame = cv2.resize(
|
||||||
|
frame,
|
||||||
|
None,
|
||||||
|
fx=0.6,
|
||||||
|
fy=0.6,
|
||||||
|
interpolation=cv2.INTER_AREA,
|
||||||
|
)
|
||||||
|
|
||||||
|
success, encoded_frame = cv2.imencode(
|
||||||
|
".jpg",
|
||||||
|
frame,
|
||||||
|
[cv2.IMWRITE_JPEG_QUALITY, JPEG_QUALITY],
|
||||||
|
)
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
continue
|
||||||
|
|
||||||
|
frame_data = encoded_frame.tobytes()
|
||||||
|
frame_size = len(frame_data)
|
||||||
|
|
||||||
|
# Network byte order, unsigned 4-byte integer.
|
||||||
|
header = struct.pack("!I", frame_size)
|
||||||
|
|
||||||
|
send_all(sock, header)
|
||||||
|
send_all(sock, frame_data)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"\rSent: {frame_size / 1024:.1f} KB",
|
||||||
|
end="",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
next_frame_time += frame_interval
|
||||||
|
sleep_time = next_frame_time - time.perf_counter()
|
||||||
|
|
||||||
|
if sleep_time > 0:
|
||||||
|
time.sleep(sleep_time)
|
||||||
|
else:
|
||||||
|
next_frame_time = time.perf_counter()
|
||||||
|
|
||||||
|
print("\nScreen streaming stopped.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
except ConnectionRefusedError:
|
||||||
|
print("Connection refused. Start the receiver first.")
|
||||||
|
except (ConnectionError, BrokenPipeError) as error:
|
||||||
|
print(f"\nConnection lost: {error}")
|
||||||
29
server.py
Normal file
29
server.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||||
|
import sys
|
||||||
|
|
||||||
|
server_name = sys.argv[1]
|
||||||
|
port = int(sys.argv[2])
|
||||||
|
|
||||||
|
|
||||||
|
class Handler(BaseHTTPRequestHandler):
|
||||||
|
def do_GET(self):
|
||||||
|
body = f"""
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>{server_name}</h1>
|
||||||
|
<p>Request path: {port}</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
""".encode()
|
||||||
|
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-Type", "text/html")
|
||||||
|
self.send_header("Content-Length", str(len(body)))
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(body)
|
||||||
|
|
||||||
|
def log_message(self, format, *args):
|
||||||
|
print(f"[{server_name}] {self.client_address[0]} - {format % args}")
|
||||||
|
|
||||||
|
|
||||||
|
HTTPServer(("127.0.0.1", port), Handler).serve_forever()
|
||||||
22783
server1.log
Normal file
22783
server1.log
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user