🎙️ Next talk at #EmbeddedRecipes2026!
Stefan Klug takes the stage with a very practical session: "Inspect your camera using camshark".
#EmbeddedRecipes2026 #EmbeddedLinux #Camera #libcamera #Debugging #EmbeddedDev #OpenSource
@Oleksii @robot Video calls using @dino has been working even on #postmarketOS stable since last year at least. I tested it successfully on a #Librem5 with pmOS 26.06 and 25.12 during each's testing phase.
🎙️ Next talk at #EmbeddedRecipes2026!
Stefan Klug takes the stage with a very practical session: "Inspect your camera using camshark".
#EmbeddedRecipes2026 #EmbeddedLinux #Camera #libcamera #Debugging #EmbeddedDev #OpenSource
🎙️ Next talk at #EmbeddedRecipes2026!
Laurent Pinchart takes the stage with a panoramic talk: "Linux and cameras: past, present and future".
#EmbeddedRecipes2026 #EmbeddedLinux #Camera #ISP #LibCamera #V4L2 #OpenSource #EmbeddedSystems
@[email protected]
I'm not really sure what changed. I get the same image from qcam. Cheese knows the camera but shows nothing from it. Likewise the gstreamer command line fails to show image and firefox seems to show no image.
Chromium gives an image but of lower quality than even that of qcam (that is grained).
gst-launch-1.0 pipewiresrc ! autovideosink .flatpak permission-remove devices cameramedia.webrtc.camera.allow-pipewire (and restart firefox). Otherwise I saw a long list of "ipu6" devices (all the /dev/videoN files?) instead of a single camera named "Built-in Front Camera".TL;DR
I wanted to revive my old Raspberry Pi Zero W camera and stream it to Home Assistant.
I made it work via libcamera2 (mjpeg stream). If I compare it with ESP32 Cam, it’s resolution and fps is better, but it’s more complex to set it up.
Long story
RBPi camera used to work when I bought it (2018) – stream using uv4l, but now (in 2026) and with new version of Raspbian OS, it doesn’t.
Which streaming tools I’ve tried and didn’t manage to get them work:
Libcamera2 and Python MJPEG streaming server
Lastly I’ve found libcamera2 python code2 (mjpeg_server2.py3)and it works. I can stream MJPEG stream to Home Assistant. The code:
#!/usr/bin/python3
# This is the same as mjpeg_server.py, but uses the h/w MJPEG encoder.
import io
import logging
import socketserver
from http import server
from threading import Condition
from picamera2 import Picamera2
from picamera2.encoders import MJPEGEncoder
from picamera2.outputs import FileOutput
PAGE = """\
<html>
<head>
<title>picamera2 MJPEG streaming demo</title>
</head>
<body>
<h1>Picamera2 MJPEG Streaming Demo</h1>
<img src="stream.mjpg" width="640" height="480" />
</body>
</html>
"""
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()
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
picam2 = Picamera2()
picam2.video_configuration.controls.FrameRate = 5.0
picam2.configure(picam2.create_video_configuration(main={"size": (800, 600)}))
output = StreamingOutput()
picam2.start_recording(MJPEGEncoder(), FileOutput(output))
try:
address = ('', 8000)
server = StreamingServer(address, StreamingHandler)
server.serve_forever()
finally:
picam2.stop_recording()Starting the program above with:
python mystreamer.py
Now I can finally see what is happening in my aquarium:
It works ok, but when my ssh connection closes, the python program terminates and it doesn’t stream anymore.
So I made it as a systemd service:
nano /etc/systemd/system/mystreamer.service
mystreamer.service looks like:
[Unit]
# Human readable name of the unit
Description=Python MJPEG web streamer
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=tomi
WorkingDirectory=/home/tomi/mymjpeg
ExecStart=/usr/bin/python /home/tomi/mymjpeg/mystreamer.py
Restart=on-failure
RestartSec=10
StartLimitIntervalSec=60
StartLimitBurst=3
Environment=PYTHONUNBUFFERED=1
StandardOutput=journal
StandardError=journal
CPUQuota=70%
MemoryMax=300M
Nice=10
[Install]
WantedBy=multi-user.target
Start the service:
sudo systemctl start mystreamer.serviceStatus?
sudo systemctl status mystreamer.serviceSee logs:
sudo journalctl -u mystreamer.service -fEnable it (autostart at boot):
sudo systemctl enable mystreamer.serviceCheck if enabled:
systemctl is-enabled mystreamer.serviceAnd finally, reboot and see if it starts:
sudo systemctl reboot
Then I modified .py code and made a mistake. Pi booted, but the service restarted every few seconds. I couldn’t even ssh to Pi.
What now?
I took SD card out of PI, put it in my computer, edited faulty .py code, put it back to RBPi, booted and I could SSH again.
Bottomline: streaming now works, but the poor PI’s CPU is at 100% (60% python streaming server, 30% glances). I found out I can set my python streamer service to CPUQuota=50% and still works ok.
Streaming H.264?
Raspberry Pi camera can also stream H.264 video, but I didn’t know how to integrate it in Home Assistant. It looks like the Camera integration doesn’t support it (it supports RTSP stream).
The command is:
libcamera-vid -t 0 --inline --listen -o tcp://0.0.0.0:8888
If anyone knows how to put this stream to HA, please let me know.
Footnotes