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