通过MJPEG让树莓派摄像头做网页直播

本篇笔记是无意中翻阅“PiCamera”的技术文档发现的。文档链接:https://picamera.readthedocs.io/en/release-1.13/recipes2.html#web-streaming

文档翻译:

通过网络流式传输视频非常复杂。 在撰写本文时,所有平台上的所有Web浏览器仍然没有普遍支持的视频标准。 此外,HTTP最初被设计为一种用于服务网页的一次性协议。 自发明以来,为了满足其不断增长的用例(文件下载,恢复,流式传输等),已经增加了各种附加功能,但事实仍然是,目前还没有“简单”的视频流传输解决方案。

如果您想播放流“真实”视频格式(特别是MPEG1)的播放,则可能需要看一下pistreaming演示。 但是,出于本食谱的目的,我们将使用更简单的格式:MJPEG。 以下脚本使用Python的内置http.server模块制作了一个简单的视频流服务器:

源代码:

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

运行上述代码后,我们就可以通过访问“http://树莓派IP:8000”观看树莓派直播啦!效果如下:

通过MJPEG让树莓派摄像头做网页直播

你想把广告放到这里吗?

发表评论

您必须 登录 才能发表留言!