MJPEG Server for Webcam in Python with OpenCV

Features of the mjpeg Server:

  • Can show html files from the local directory
  • Can show jpeg images from the local directory
  • Can serve multiple client simultaniously with a mjpeg stream ( multithreaded )
  • Image Quality of the stream can be set by the client.

The Stream can be watched in a Browser or by e.g. VLC-player by opening the url: http://localhost:8080/something.mjpeg
In order to get the Streamquality adjusting interface open in a browser with: http://localhost:8080/index.html (index.html must exist in the directory where the server is executed. The content of index.html is shown below)
Dependencies:

  • Python with OpenCV and webcam

The Webserver .py file:

#edited by Norbert (mjpeg part) from a file from Copyright Jon Berg , turtlemeat.com,
#MJPEG Server for the webcam
import string,cgi,time
from os import curdir, sep
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from SocketServer import ThreadingMixIn
import cv
import re
capture = cv.CaptureFromCAM(-1)
img = cv.QueryFrame(capture)
cameraQuality=75
class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        global cameraQuality
        try:
            self.path=re.sub('[^.a-zA-Z0-9]', "",str(self.path))
            if self.path=="" or self.path==None or self.path[:1]==".":
                return
            if self.path.endswith(".html"):
                f = open(curdir + sep + self.path)
                self.send_response(200)
                self.send_header('Content-type',	'text/html')
                self.end_headers()
                self.wfile.write(f.read())
                f.close()
                return
            if self.path.endswith(".mjpeg"):
                self.send_response(200)
                self.wfile.write("Content-Type: multipart/x-mixed-replace; boundary=--aaboundary")
                self.wfile.write("\r\n\r\n")
                while 1:
                    img = cv.QueryFrame(capture)
                    cv2mat=cv.EncodeImage(".jpeg",img,(cv.CV_IMWRITE_JPEG_QUALITY,cameraQuality))
                    JpegData=cv2mat.tostring()
                    self.wfile.write("--aaboundary\r\n")
                    self.wfile.write("Content-Type: image/jpeg\r\n")
                    self.wfile.write("Content-length: "+str(len(JpegData))+"\r\n\r\n" )
                    self.wfile.write(JpegData)
                    self.wfile.write("\r\n\r\n\r\n")
                    time.sleep(0.05)
                return
            if self.path.endswith(".jpeg"):
                f = open(curdir + sep + self.path)
                self.send_response(200)
                self.send_header('Content-type','image/jpeg')
                self.end_headers()
                self.wfile.write(f.read())
                f.close()
                return
            return
        except IOError:
            self.send_error(404,'File Not Found: %s' % self.path)
    def do_POST(self):
        global rootnode, cameraQuality
        try:
            ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
            if ctype == 'multipart/form-data':
                query=cgi.parse_multipart(self.rfile, pdict)
            self.send_response(301)

            self.end_headers()
            upfilecontent = query.get('upfile')
            print "filecontent", upfilecontent[0]
            value=int(upfilecontent[0])
            cameraQuality=max(2, min(99, value))
            self.wfile.write("<HTML>POST OK. Camera Set to<BR><BR>");
            self.wfile.write(str(cameraQuality));

        except :
            pass

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
#class ThreadedHTTPServer(HTTPServer):
    """Handle requests in a separate thread."""

def main():
    try:
        server = ThreadedHTTPServer(('localhost', 8080), MyHandler)
        print 'started httpserver...'
        server.serve_forever()
    except KeyboardInterrupt:
        print '^C received, shutting down server'
        server.socket.close()

if __name__ == '__main__':
    main()

The index.html file:

<HTML>
<BODY>

<div id="hiddenDiv" style="display:none;visible:hidden;">
  < iframe src="hidden.html" height="1" width="1" border="0" scrolling="no" name="hiddenFrame" id="hiddenFrame" >< / iframe>
</div>

<img src="camera.mjpeg" alt="Smiley face" height="480" width="640">

<form target="hiddenFrame" method='POST' enctype='multipart/form-data'>

    <div align="center">
        Set Quality:
        <select name="upfile" width="50">
            <option value="2"> 2 </option>
            <option value="5"> 5 </option>
             <option value="10"> 10 </option>
            <option value="20"> 20 </option>
             <option value="30"> 30 </option>
            <option value="50"> 50 </option>
            <option value="75"> 75 </option>
            <option value="80"> 80 </option>
            <option value="90"> 90 </option>
            <option value="96"> 96 </option>
             </select>
        <input type=submit value=Set>
     </div>
</form>

</BODY>
</HTML>

 

About these ads

Posted on April 11, 2013, in MJPEG Server in Python and tagged . Bookmark the permalink. 1 Comment.

  1. Interesint entry. But I have a question… if I try two connections from two different tabs it seems like I just can get one access at a time

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: