I want to make a python code that browsers can connect to get a video stream.
Problem is that my python code handles only one time use, meaning if you open the browser it will connect to that websocket correctly, but if you refresh the page, or another client want to access a stream from in parallel it doesn't work My code:
import asyncio
import websockets
import cv2
import os
import signal
async def time1(websocket, path):
while True:
vid = cv2.VideoCapture('V_DRONE_097.mp4')
vid.set(cv2.CAP_PROP_FPS,24)
try:
#v = VideoStreamWidget()
#v.ops()
while(vid.isOpened()):
img, frame = vid.read()
#frame = cv2.resize(frame, (640, 480))
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 65]
man = cv2.imencode('.jpg', frame, encode_param)[1]
#sender(man)
#print(len(man.tobytes()))
#cv2.imshow('img',man)
await websocket.send(man.tobytes())
except :
pass
async def main():
loop = asyncio.get_running_loop()
stop = loop.create_future()
#loop.add_signal_handler(signal.SIGTERM, stop.set_result, None)
port = int(os.environ.get("PORT", "8585"))
global stop1
async with websockets.serve(time1, "", port):
await stop
stop1 = False
'''
async def main():
async with websockets.serve(time1, "localhost", 8585):
await asyncio.Future() # run forever
asyncio.run(main())
'''
if __name__ == "__main__":
while True:
asyncio.run(main())
I want the server to keep working even if the client (browser) refreshes the page or close it and comeback later.
This is the code of javascript running in the browser if that will help:
openSocket = () => {
socket = new WebSocket("ws://127.0.0.1:8585/");
let msg = document.getElementById("msg");
socket.addEventListener('open', (e) => {
document.getElementById("status").innerHTML = "Opened";
});
socket.addEventListener('message', (e) => {
let ctx = msg.getContext("2d");
let image = new Image();
image.src = URL.createObjectURL(e.data);
image.addEventListener("load", (e) => {
ctx.drawImage(image, 0, 0, msg.width, msg.height);
});
});
}
and this is the HTML code:
<!DOCTYPE html>
<html>
<head>
<title>Python_Websocket_Live_Streaming</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script type="text/javascript" src="script.js" ></script>
</head>
<body onl oad="openSocket()">
<div id="status">
Connection failed. Somebody may be using the socket.
</div>
<div style="text-align: center">
<canvas id="msg" width="960" height="720" style="display:inline-block" />
</div>
</body>
</html>
I've searched and tried many solutions but non worked. My final goal is to integrate this with flask API
Update 1: yes it is stuck in the time1 function I've known from wrapping the "send" function in a try catch:
try:
await websocket.send(man.tobytes())
except websockets.exceptions.ConnectionClosedError:
print("clean up")
break
when the browser closes/refresh the page, clean up is printed infinitely
Edit 2 It was stuck in the outer loop, that while true loop. Solved now Thanks
CodePudding user response:
There are a few culprits, but ultimately I think that while(vid.isOpened())
prevents the async from ever being free
edit
or stuck in the outer while loop