Facebook
From joku, 3 Years ago, written in Python.
Embed
Download Paste or View Raw
Hits: 116
  1. import io
  2. import picamera
  3. import logging
  4. import socketserver
  5. from threading import Condition
  6. from http import server
  7.  
  8. PAGE="""\
  9. <html>
  10. <head>
  11. <title>picamera MJPEG streaming demo</title>
  12. </head>
  13. <body>
  14. <h1>PiCamera MJPEG Streaming Demo</h1>
  15. <img src="stream.mjpg" width="640" height="480" />
  16. </body>
  17. </html>
  18. """
  19.  
  20. class StreamingOutput(object):
  21.     def __init__(self):
  22.         self.frame = None
  23.         self.buffer = io.BytesIO()
  24.         self.condition = Condition()
  25.  
  26.     def write(self, buf):
  27.         if buf.startswith(b'\xff\xd8'):
  28.             # New frame, copy the existing buffer's content and notify all
  29.             # clients it's available
  30.             self.buffer.truncate()
  31.             with self.condition:
  32.                 self.frame = self.buffer.getvalue()
  33.                 self.condition.notify_all()
  34.             self.buffer.seek(0)
  35.         return self.buffer.write(buf)
  36.  
  37. class StreamingHandler(server.BaseHTTPRequestHandler):
  38.     def do_GET(self):
  39.         if self.path == '/':
  40.             self.send_response(301)
  41.             self.send_header('Location', '/index.html')
  42.             self.end_headers()
  43.         elif self.path == '/index.html':
  44.             content = PAGE.encode('utf-8')
  45.             self.send_response(200)
  46.             self.send_header('Content-Type', 'text/html')
  47.             self.send_header('Content-Length', len(content))
  48.             self.end_headers()
  49.             self.wfile.write(content)
  50.         elif self.path == '/stream.mjpg':
  51.             self.send_response(200)
  52.             self.send_header('Age', 0)
  53.             self.send_header('Cache-Control', 'no-cache, private')
  54.             self.send_header('Pragma', 'no-cache')
  55.             self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
  56.             self.end_headers()
  57.             try:
  58.                 while True:
  59.                     with output.condition:
  60.                         output.condition.wait()
  61.                         frame = output.frame
  62.                     self.wfile.write(b'--FRAME\r\n')
  63.                     self.send_header('Content-Type', 'image/jpeg')
  64.                     self.send_header('Content-Length', len(frame))
  65.                     self.end_headers()
  66.                     self.wfile.write(frame)
  67.                     self.wfile.write(b'\r\n')
  68.             except Exception as e:
  69.                 logging.warning(
  70.                     'Removed streaming client %s: %s',
  71.                     self.client_address, str(e))
  72.         else:
  73.             self.send_error(404)
  74.             self.end_headers()
  75.  
  76. class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
  77.     allow_reuse_address = True
  78.     daemon_threads = True
  79.  
  80. with picamera.PiCamera(resolution='640x480', framerate=24) as camera:
  81.     output = StreamingOutput()
  82.     camera.start_recording(output, format='mjpeg')
  83.     try:
  84.         address = ('', 8000)
  85.         server = StreamingServer(address, StreamingHandler)
  86.         server.serve_forever()
  87.     finally:
  88.         camera.stop_recording()
  89.