I am trying to show live webcam video stream on webpage and I have a working draft. However, I am not satisfied with the performance and looking for a better way to do the job.
I have a webcam connected to Raspberry PI and a web server which is a simple python-Flask server. Webcam images are captured by using OpenCV and formatted as JPEG. Later, those JPEGs are sent to one of the server's UDP ports. What I did up to this point is something like a homemade MJPEG(motion-jpeg) streaming.
At the server-side I have a simple python script that continuously reads UDP port and put JPEG image in the HTML5 canvas. That is fast enough to create a perception of a live stream.
Problems:
This compress the video very little. Actually it does not compress the video. It only decreases the size of a frame by formatting as JPEG.
FPS is low and also quality of the stream is not that good.
It is not a major point for now but UDP is not a secure way to stream video.
Server is busy with image picking from UDP. Needs threaded server design.
Alternatives:
Is this applicable on Raspberry PI ?
Is there any Media Player to embed on HTML/Javascript to handle network stream like the VLC does ?
Does these apply for this case ? If it does,how should I use them ?
Is there any other way to show live stream on webpage ?
What is the best practice for transport layer protocol in video streaming ?
I will try to answer as many of your listed "Problems" as I can:
FPS is low and also quality of the stream is not that good.
Since you are using Flask, you can use the immensely powerful url_for
keyword to display your streamed frames directly into an img tag. Here is how you can achieve this:
On the webpage, add <img src="{{url_for('video_feed')}}"
where you want your feed to be streamed.
At the backend, do the following:
def gen(camera):
frame = camera.read()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
@app.route('/video_feed')
def video_feed():
return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame')
Now, the img tag will display the image present on the endpoint video_feed
which is of type multipart. Hence, it will keep asking for newer parts (newer frames) in your case.
I have found this approach to be quite fast!
Credits: Miguel Grinberg's blog post
It is not a major point for now but UDP is not a secure way to stream video.
Most video streaming devices don’t encrypt the video they stream, because doing so is computationally expensive. So while you might connect to an embedded web server on the device via HTTPS, and you probably have to log into the device to control it, all that security is limited to the “control plane.” The video itself will almost certainly be transmitted unencrypted. If it complies with an open standard, it is probably being sent over RTP/RTSP or over HTTP Live Streaming (HLS).
Source: Thoughts on Streaming Videos Securely
Server is busy with image picking from UDP. Needs threaded server design.
Using the above approach, I was able to interact with the server even while streaming the video. With the Flask development web server, you can add threaded=True
to your app.run()
call, or --with-threads
if you use the Flask CLI.
You can also use Gunicorn in combination with gevent or eventlet to have further control over your threads.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With