| #!/usr/bin/python | |
| ''' | |
| Author: Igor Maculan - n3wtron@gmail.com | |
| A Simple mjpg stream http server | |
| ''' | |
| import cv2 | |
| import Image | |
| import threading | |
| from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer | |
| from SocketServer import ThreadingMixIn | |
| import StringIO | |
| import time | |
| capture=None | |
| class CamHandler(BaseHTTPRequestHandler): | |
| def do_GET(self): | |
| if self.path.endswith('.mjpg'): | |
| self.send_response(200) | |
| self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary') | |
| self.end_headers() | |
| while True: | |
| try: | |
| rc,img = capture.read() | |
| if not rc: | |
| continue | |
| imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB) | |
| jpg = Image.fromarray(imgRGB) | |
| tmpFile = StringIO.StringIO() | |
| jpg.save(tmpFile,'JPEG') | |
| self.wfile.write("--jpgboundary") | |
| self.send_header('Content-type','image/jpeg') | |
| self.send_header('Content-length',str(tmpFile.len)) | |
| self.end_headers() | |
| jpg.save(self.wfile,'JPEG') | |
| time.sleep(0.05) | |
| except KeyboardInterrupt: | |
| break | |
| return | |
| if self.path.endswith('.html'): | |
| self.send_response(200) | |
| self.send_header('Content-type','text/html') | |
| self.end_headers() | |
| self.wfile.write('<html><head></head><body>') | |
| self.wfile.write('<img src="http://127.0.0.1:8080/cam.mjpg"/>') | |
| self.wfile.write('</body></html>') | |
| return | |
| class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): | |
| """Handle requests in a separate thread.""" | |
| def main(): | |
| global capture | |
| capture = cv2.VideoCapture(0) | |
| capture.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 320); | |
| capture.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 240); | |
| capture.set(cv2.cv.CV_CAP_PROP_SATURATION,0.2); | |
| global img | |
| try: | |
| server = ThreadedHTTPServer(('localhost', 8080), CamHandler) | |
| print "server started" | |
| server.serve_forever() | |
| except KeyboardInterrupt: | |
| capture.release() | |
| server.socket.close() | |
| if __name__ == '__main__': | |
| main() | |
|
Great work, Igor! Wolfgang, the program uses pipes (http://www.python-course.eu/pipes.php) to communicate the output to the server. When you disconnect from the port, it breaks the existing pipe, and when you reconnect, it breaks the previous pipe and starts a new one. If you were running the script locally and the opencv output was displayed in a window, you could use the 'Keyboard Interrupt' to break the loop without any errors. That doesn't work in the browser because you've already used a pipe to get there. tl;dr : that error is nothing to worry about, you'll pretty much see it every time you disconnect or reconnect. |
|
Nice man!! exactly I was looking for on web. Saved my time |
|
hi, when connecting a flash mjepg netstream reader I got |
|
Hi bluelemonade, |
|
Hello Igor, I have adapted your code for a project of mine. Thanks for sharing this! I noticed you did not include a license with this, and I want to be respectful of your ownership of this code. Am I free to use my modified version of this gist in my project under any license? Thanks! |
|
hello ...people...I used this code ...it works for me ...like it doesn't give any error...but I cannot see the web cam stream in browser for some reason ??.....help is much appreciated. Thanks |
|
Hi @njlochner you are free to use it and modify it (GPLv3 License) when I've shared this code I forgot to add the licence, I'm sorry. |
Thanks! |
|
Hi |
|
@Asymptote, in order to do this you need to adapt this into a threaded HTTP server. I have done so in my code. See the accepted answer from this thread: http://stackoverflow.com/questions/14088294/multithreaded-web-server-in-python |
|
@Asymptote thanks to @njlochner I've adjust it for multi thread. |
|
Hi ! I wanted to see what we can do with this. It seems to work fine, because i don't get any error and the infinite loop is running, but when i want to access at "localhost:8080" with my browser, i receive an error : "Message corrupt". Any idea about it ? For those who get the error "Cannot import Image", you should replace Anyway, thank you for sharing this =) |
|
Hey!
The problem seems to be this line: Any idea? Best, |
|
i fixed the error above by uninstalling pil and pillow (seem to cause conflicts if both are installed). Then I reinstalled only pillow. Now I get a popup window "python.exe has stopped working.." when accessing the mjpg via browser caused by this line: Any ideas? Best, Hanna |
|
Nice, worked like a charm.... Thank you! |
|
Hello Igor, this looks very promising . I have a couple questions maybe someone could help with. Please forgive me I'm a bit of a noob at this. I'm presently using SimpleCV, which includes an mjpeg streaming server that seems to work in a similar way to this code, however with that server I often have to re-load the page a few times to get the image feed to appear, and sometimes it disappears after it's been streaming for a while. I thought maybe it would be more reliable if I were to somehow get the stream to write to a location and then use Apache to actually serve it up. There is a post here about streaming OpenCV images via Apache. I discovered your code above when starting to work through that tutorial. I don't understand how to write the code to get the components to talk to eachother. Would you mind giving a bit more detail and example of how to actually use the above code? I assume I would kick it off in a terminal and let it run, at which time I could access the stream via a browser, but I'm not sure how to actually save images from OpenCV/SimpleCV to the server. And a followup, is there a reason you're not just using Apache? I'm sure there was a good reason, it just seems it's already installed with most Linux distros so I'm not sure why one would write another server. Thanks so much! |
|
Hi @plumgeek, I hope that I have been useful to you |
|
I have the same issue that @Kiolali |
|
Hi @andresR8, |
|
I am having issue when multiple clients connect to the server. When first client connects, streaming works perfectly. As soon as I second client connects, get following dump many times and server crashes: [mpjpeg @ 0x560aa30ffae0] Expected boundary '--' not found, instead found a line of 127 bytes Any idea how to fix multi client access issue? Thanks |
|
I have the same issue as @wpoet ("broken pipe") accessing the mjpeg stream via browser works - but if I use a test client like "insomnia" (GET url_mjpeg_stream) I don't get any response.. |
Igor, this is a terrific example! Wonderful work!!!!
When I run it on my Ubuntu 15.10 system, it works, but initially I get this error message:
server started
127.0.0.1 - - [09/Jan/2016 16:54:47] "GET /cam.mjpg HTTP/1.1" 200 -
Exception happened during processing of request from ('127.0.0.1', 42188)
Traceback (most recent call last):
File "/usr/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 321, in process_request
self.finish_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python2.7/SocketServer.py", line 657, in init
self.finish()
File "/usr/lib/python2.7/SocketServer.py", line 716, in finish
self.wfile.close()
File "/usr/lib/python2.7/socket.py", line 283, in close
self.flush()
File "/usr/lib/python2.7/socket.py", line 307, in flush
self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
The program still serves the mjpeg stream, but this message comes on every re/connect. Do you have an idea why this happens?
br Wolfgang