I'm trying to make FastAPI server which streams MJPEG from Raspberry Pi via picamera2 library. It works, but when I reload browser on /mjpeg multiple times, it will stuck. But with this example it works perfectly - you can reload browsers as many times as you want. Can you spot the problem?
For server I'm using uvicorn with default settings.
Thanks!
import io
import os
from threading import Condition
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from picamera2 import Picamera2
from picamera2.encoders import JpegEncoder
from picamera2.outputs import FileOutput
from fastapi.responses import HTMLResponse, StreamingResponse
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins="http://localhost:8000",
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class StreamingOutput(io.BufferedIOBase):
def __init__(self):
self.frame = None
self.condition = Condition()
def write(self, buf):
with self.condition:
self.frame = buf
self.condition.notify_all()
picam2 = Picamera2()
picam2.configure(picam2.create_video_configuration(main={"size": (640, 480)}))
output = StreamingOutput()
picam2.start_recording(JpegEncoder(), FileOutput(output))
def get_frame():
try:
while True:
with output.condition:
output.condition.wait()
frame = output.frame
yield (
b"--frame\r\n" b"Content-Type: image/jpeg\r\n\r\n" + frame + b"\r\n"
)
except Exception as e:
print("Error! Frames")
@app.get("/mjpeg", response_class=StreamingResponse)
def mjpeg(request: Request):
try:
frames = get_frame()
response = StreamingResponse(
frames,
headers={
"Cache-Control": "no-cache, private",
"Pragma": "no-cache",
},
media_type="multipart/x-mixed-replace; boundary=frame",
)
return response
except Exception as e:
print("Error! Route")