Browser-based studio control for Canon EOS cameras, optimized for:
- Raspberry Pi (e.g. Pi 4 / Pi 5)
- Rockchip SBCs (e.g. Rock 5B)
It can run:
- as a bare-metal Flask app on a single board,
- as a Docker container, or
- as a K3s microservice in a cluster,
and can work in both:
- Local mode – camera physically attached to the same board
- Distributed mode – camera attached to a small helper board via USB/IP, with the main server running on a more powerful node (even inside K3s).
-
Live View / “Mirror” mode
Live preview in the browser on any device on your LAN (HDMI monitor, tablet, phone, laptop). -
Capture & mini gallery
- One-click capture from the web UI
- Images organised into dated folders
- 3×3 mini gallery on the main page
- Full gallery page for browsing sessions
-
Quick settings & presets
- Change supported camera settings via the UI (as exposed by
gphoto2) - Save and load presets (e.g. “studio key light”, “window light”, “night”).
- Change supported camera settings via the UI (as exposed by
-
Intervalometer
- Start/stop time-lapse from the UI
- Configurable interval and shot count.
-
Import-from-camera with cancel
- Bulk import all images from the camera (via
gphoto2) - Runs as a background worker
- Shows progress and allows cancelling mid-way.
- Bulk import all images from the camera (via
-
GPS / EXIF tagging
- Set GPS coordinates in the UI (or fetch from another sensor/service)
- Write coordinates and other EXIF metadata into images.
-
Histogram & info panel
- Generate histogram / summary for recent captures
- Quick exposure check without opening a full editor.
-
Session / folder switching
- Quickly change the active photo folder / session
- Useful for events, multiple shoots, or separating “family” vs “work” sessions.
-
Optional face-recognition integration
- On capture, the server can notify an external face-recognition service
- Sends file path + metadata over HTTP for face tagging / notifications
- Designed to work nicely with an AuraFace/RKNN-style pipeline running on an RK3588 board (not part of this repository).
- Camera’s USB cable is plugged directly into:
- a Raspberry Pi, or
- a Rockchip board (e.g. Rock 5B).
- Flask app (or Docker/K3s pod) runs on that same board.
This is the simplest and is ideal for a single studio/location.
For more flexible setups:
-
Camera node
- Small board physically connected to the Canon via USB.
- Runs a small
usbipexporter. - Makes the Canon USB device available over the network.
-
Main server node
- More powerful board (e.g. Pi 5 / Rockchip SBC with NVMe).
- Attaches the remote USB device via
usbip. - Runs the Flask app bare-metal, in Docker, or as a K3s service.
This is useful if your “brains + storage” live in one place, and the camera is physically located somewhere else.
Main components:
-
Flask backend (
server.py)- HTTP API and HTML pages (
index.html,gallery.html,field.html). - Orchestrates capture, intervalometer, import, EXIF, GPS, presets, histogram, etc.
- HTTP API and HTML pages (
-
Camera control via
gphoto2- Capture, listing, import, live view, and settings executed via
gphoto2CLI commands.
- Capture, listing, import, live view, and settings executed via
-
Image and EXIF helpers
- EXIF/GPS tagging using
exiftool(or similar). - Thumbnail and histogram generation (e.g. with
Pillow,ffmpeg).
- EXIF/GPS tagging using
-
Optional integration with a face pipeline
- Configurable URL to call after each capture.
- Sends image path, timestamp, and optionally GPS data.
- External service performs detection/recognition and returns results or triggers notifications.
A typical layout looks like:
canon-eos-studio-remote/
server.py # Flask backend and application logic
README.md
requirements.txt # Python dependencies (if provided)
photos/ # Captured photos (organised per date/session)
tmp/ # Temporary files (live view frames, working data)
www/
index.html # Main UI (live view, quick controls, mini gallery)
gallery.html # Gallery view
field.html # Alternate / simplified layout
You can adapt the exact structure to your needs; the code expects a www/ directory with HTML templates and some writable directories for photos and temporary files.
Main server:
- Raspberry Pi (e.g. Pi 4 or Pi 5), or
- Rockchip SBC (e.g. Rock 5B)
Optional camera node (for USB/IP mode):
- Any Pi or SBC that supports
usbipandgphoto2.
Camera:
- Canon EOS camera.
- The project has been tested with models such as the Canon 5D Mark II; other
gphoto2-supported EOS cameras may work.
Network:
- All boards on the same network (wired or Wi-Fi).
On Raspberry Pi OS / other Debian-like systems:
sudo apt update
sudo apt install -y gphoto2 libgphoto2-6 libgphoto2-dev exiftool ffmpeg python3-venv python3-pip usbipOn Rockchip boards, install the equivalent packages from your distribution’s repositories.
Install in a virtual environment:
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtA typical requirements.txt might include:
Flask
Werkzeug
Pillow
numpy
(Plus any other libraries referenced in server.py.)
git clone https://github.com/Mojo24x7/canon-eos-studio-remote.git
cd canon-eos-studio-remote(Or use the SSH URL if you’ve set up SSH keys.)
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtgphoto2 --auto-detect
gphoto2 --summaryYou should see your Canon EOS camera listed.
source venv/bin/activate
python3 server.pyThen open in your browser:
http://<board-ip>:8090 ,
For a fun photobooth
http://<board-ip>:8090/field
You should see:
- live view / mirror area
- capture button and quick controls
- mini gallery
- GPS controls
- import start/stop buttons
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "server.py"]docker build -t canon-eos-studio-remote:latest .You need to pass through USB and a folder for photos:
docker run -d --name canon-eos-studio-remote --restart unless-stopped --net host --device /dev/bus/usb:/dev/bus/usb -v /path/to/photos:/photos canon-eos-studio-remote:latestAdjust /path/to/photos and the internal path so they match what server.py expects for the photos directory.
The app can be deployed as a pod in a K3s cluster, typically pinned to the node that has the camera attached.
apiVersion: apps/v1
kind: Deployment
metadata:
name: canon-eos-studio-remote
spec:
replicas: 1
selector:
matchLabels:
app: canon-eos-studio-remote
template:
metadata:
labels:
app: canon-eos-studio-remote
spec:
hostNetwork: true
containers:
- name: app
image: canon-eos-studio-remote:latest
securityContext:
privileged: true # for USB pass-through
volumeMounts:
- name: photos
mountPath: /photos
volumes:
- name: photos
hostPath:
path: /path/on/node/for/photos
type: DirectoryOrCreate
nodeSelector:
camera-node: "true" # label the node with the cameraYou can then expose it with a Service and your preferred ingress setup (NGINX, Apache reverse proxy, etc.).
This repository does not ship a full USB/IP script, but the idea is:
On the camera node:
- Load the
usbip_hostmodule. - Export the Canon USB device with
usbip.
On the main server node (where this app runs):
- Attach the remote USB device using
usbip. gphoto2will then see the camera as if it were local.
The application code does not need to change; it just talks to gphoto2 as usual.
The server can be configured to call an external HTTP endpoint after each capture, for example:
- A local face-recognition service running on another board.
- A service that uses AuraFace-based embeddings and a local face database.
Typical flow:
- Canon EOS Studio Remote captures an image.
- It sends a POST request with JSON such as:
- image path or URL
- timestamp
- optional GPS/EXIF data
- The face service:
- detects faces
- matches them to known identities
- updates a database or sends notifications.
The exact payload, URL, and behaviour are configurable in the application code.
This project is licensed under the Apache License 2.0 – see the LICENSE file for details.
This project builds on:
- gphoto2 / libgphoto2 – Canon EOS camera control
- exiftool – EXIF and GPS tagging
- ffmpeg – video and frame processing
- Flask and related Python libraries – web backend
Face-recognition services are not part of this repository; if you integrate an external face pipeline, follow the licenses and documentation of those separate projects.