0

I am trying to stream and save video from Raspberry Pi Camera. I found code which provide streaming to HTML page but when I write output stream to a file I am getting MJPEG file which size is increasing by the time but when I watch it, I can see same image from camera for the whole time. I guess it captures just first image and then it is stuck or replicated through the whole video. I tried to write bytes when write method is called or when whole frame is complete but it resolves in same problem.

Here is the code. The part inside StreamingOutput -> self.file.write(self.frame) is added by me and all things about file. (EDIT) I will be glad for any working solution not just Python.

Thank you.

# Web streaming example
# Source code from the official PiCamera package
# http://picamera.readthedocs.io/en/latest/recipes2.html#web-streaming

import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server

PAGE="""\
<html>
<head>
<title>Raspberry Pi - Surveillance Camera</title>
</head>
<body>
<center><h1>Raspberry Pi - Surveillance Camera</h1></center>
<center><img src="stream.mjpg" width="90%" height=90%"></center>
</body>
</html>
"""

class StreamingOutput(object):
    def __init__(self):
        self.frame = None
        self.buffer = io.BytesIO()
        self.condition = Condition()
        self.file = None

    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # New frame, copy the existing buffer's content and notify all
            # clients it's available
            self.buffer.truncate()
            with self.condition:
                self.frame = self.buffer.getvalue()
                self.file.write(self.frame)
                self.condition.notify_all()
            self.buffer.seek(0)
        #self.file.write(buf)
        return self.buffer.write(buf)

class StreamingHandler(server.BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(301)
            self.send_header('Location', '/index.html')
            self.end_headers()
        elif self.path == '/index.html':
            content = PAGE.encode('utf-8')
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.send_header('Content-Length', len(content))
            self.end_headers()
            self.wfile.write(content)
        elif self.path == '/stream.mjpg':
            self.send_response(200)
            self.send_header('Age', 0)
            self.send_header('Cache-Control', 'no-cache, private')
            self.send_header('Pragma', 'no-cache')
            self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
            self.end_headers()
            try:
                while True:
                    with output.condition:
                        output.condition.wait()
                        frame = output.frame
                    self.wfile.write(b'--FRAME\r\n')
                    self.send_header('Content-Type', 'image/jpeg')
                    self.send_header('Content-Length', len(frame))
                    self.end_headers()
                    self.wfile.write(frame)
                    self.wfile.write(b'\r\n')
            except Exception as e:
                logging.warning(
                    'Removed streaming client %s: %s',
                    self.client_address, str(e))
        else:
            self.send_error(404)
            self.end_headers()

class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
    allow_reuse_address = True
    daemon_threads = True

with picamera.PiCamera(resolution='1920x1080', framerate=30) as camera:
    
    try:        
        with open("/home/pi/stream.mjpeg", "wb") as outFile:
            output = StreamingOutput()
            output.file = outFile
            camera.rotation = 180
            camera.start_recording(output, format='mjpeg')
            try:
                address = ('', 8000)
                server = StreamingServer(address, StreamingHandler)
                server.serve_forever()
            finally:
                camera.stop_recording()
    finally:
        outFile.close()

2
  • why are you limiting your chance of getting a good answer by posting here? ... the question is not about the Raspberry Pi
    – jsotola
    Mar 20, 2021 at 17:34
  • I am also open for other options. For example I tried even raspivid -o - | tee file so it divide output to file and stdout. But tee makes video broken. Video is much short. I watch it and it is played x-times faster. I admit question is asked wrong way and thank you I also raise another in general Stack.
    – cherioss
    Mar 21, 2021 at 7:01

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.