This project creates a simple flask + openCV server for streaming video and accessing camera frames of standard V4l2 protocol usb cameras and luxionus depthai cameras on a rasberry pi (or linux/debian system).
Supports live MJPEG video streaming, lossless PNG snapshots, and raw NumPy frame data for scientific/computer-vision clients.
- RTSP serving
- Computer vision outputs(Particularly from DepthAI cameras)
- Stream live video feed over HTTP (
/video_feed) - Get lossless PNG-encoded snapshots (
/lossless_frame) - Get raw NumPy frame data (
/raw_frame) - Query and change camera configuration (
/current_config,/configure) - List available devices, codecs, resolutions, and FPS (
/devices) - Graceful shutdown (releases camera device when service stops)
- Create custom pipelines for depthai cameras
- Works with browsers, Python clients, or custom UIs
- Python 3.9+
- OpenCV (
cv2) - NumPy
- Flask
- Gunicorn (for production with systemd)
sudo apt update
sudo apt install python3-opencv python3-numpy python3-flask python3-pip v4l-utils guinicorn- Raspberry pi auto hotspot script (Useful for connecting pi to network)
cd
curl "https://www.raspberryconnect.com/images/scripts/AccessPopup.tar.gz" -o AccessPopup.tar.gz
tar -xvf ./AccessPopup.tar.gz
cd AccessPopup
sudo ./installconfig.sh
# Follow installer script promptsgit clone https://github.com/mohas95/pi_cam_server.git
cd pi_cam_server
python3 app.pygit clone https://github.com/mohas95/pi_cam_server.git
cd pi_cam_server
gunicorn --workers 1 --threads 4 --timeout 120 --bind 0.0.0.0:5000 app:appSave as /etc/systemd/system/campi.service:
[Unit]
Description=Campi Server using Flask and Gunicorn
After=network.target
[Service]
User=pi
WorkingDirectory=/home/pi/pi_cam_server
ExecStart=/usr/bin/gunicorn --workers 1 --threads 4 --timeout 120 --bind 0.0.0.0:5000 app:app
Restart=always
[Install]
WantedBy=multi-user.targetEnable and start:
sudo systemctl daemon-reload
sudo systemctl enable campi.service
sudo systemctl start campi.serviceGET /video_feedGET /lossless_frame- Returns a single lossless PNG-encoded frame
- Content-Type: image/png
- Good for one-off snapshots or analysis
GET /raw_frame- Returns raw BGR bytes (application/octet-stream)
- Metadata in response headers:
- X-Height → image height
- X-Width → image width
- X-Channels → number of channels (3 for BGR)
- X-Dtype → NumPy dtype (e.g., uint8)
Client can reconstruct with:
frame = np.frombuffer(resp.content, dtype=np.uint8).reshape(height, width, channels)GET /current_config- returns
{
"device_id": "/dev/video0",
"codec": "MJPG",
"width": 1280,
"height": 720,
"fps": 30
}GET /devices- Returns all available devices, codecs, resolutions, and FPS.
- Example response:
{
"/dev/video0": {
"device": "C922_Pro_Stream_Webcam",
"formats": [
{
"codec": "MJPG",
"desc": "Motion-JPEG",
"resolutions": [
{"resolution": "1920x1080", "fps": [30.0]},
{"resolution": "1280x720", "fps": [30.0]}
]
}
]
}
}POST /configure- Re-initializes the camera with new settings
- Content-Type: application/json
- example of configuration to send:
{
"device_id": "/dev/video0",
"codec": "MJPG",
"resolution": "1280x720",
"fps": 30
}- Returns { "status": "ok" } if successful
- start integration with depthai cameras
- access control to prevent pipeline breaking or conflicting stream access
- fixes to initialization protocol
- custom pipeline builder integrations for depthai cameras
- change device identifier to device_id rather than device