Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Live Video Encoding and Streaming on a Webpage

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:

  • I have used FFMPEG before to convert video formats and also stream pre-recorded video. I guess, it is possible to encode(let say H.264) and stream WebCam live video using ffmpeg or avconv. (Encoding)

Is this applicable on Raspberry PI ?

  • VLC is able to play live videos streamed on network. (Stream)

Is there any Media Player to embed on HTML/Javascript to handle network stream like the VLC does ?

  • I have read about HLS (HTTP Live Stream) and MPEG-DASH.

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 ?

  • RTSP is a secure protocol.

What is the best practice for transport layer protocol in video streaming ?

like image 522
Ockhius Avatar asked Mar 08 '16 23:03

Ockhius


1 Answers

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.

like image 161
PANKAJ BARANWAL Avatar answered Sep 22 '22 03:09

PANKAJ BARANWAL