I would like to take this opportunity to special thank the original author for this selfless sharing. Due to my usecase is to use Pi5 along with 2 Pi CSI Camera at the same time, therefore I need an option to define which the camera to be in use with. That's why I fork this project to make relevant modifications as needed. Free free to use it if you found this useful for you. Thanks!!!
Please note that this project is in a very early stage. Use at your own risk. Think about contributing to the project if you find that something is not working, and you are able to fix it. Every contribution is appreciated.
A simple mjpeg server for Picamera2.
With Spyglass you are able to stream videos from a camera that is supported by libcamera like the Raspberry Pi Camera Module 3.
Current version: 0.14.0
- Raspberry Pi OS Bullseye
- Picamera2 - Already installed on Raspberry Pi OS Bullseye
- Python 3.8+
- A camera supported by libcamera and connected to the Raspberry Pi
The server can be started with
./run.py
This will start the server with the following default configuration:
- Address the server binds to: 0.0.0.0
- Port: 8080
- Resolution: 640x480
- Framerate: 15fps
- Stream URL: /stream
- Snapshot URL: /snapshot
On startup the following arguments are supported:
Argument | Description | Default |
---|---|---|
-n , --csi_port_no |
CSI port number, additional port in Raspberry Pi 5 is 1, default is 0 if not specify | 0 |
-b , --bindaddress |
Address where the server will listen for new incoming connections. | 0.0.0.0 |
-p , --port |
Port where the server will listen for new incoming connections. | 8080 |
-r , --resolution |
Resolution of the captured frames. This argument expects the format <width>x<height> | 640x480 |
-f , --fps |
Framerate in frames per second (fps). | 15 |
-st , --stream_url |
Sets the URL for the mjpeg stream. | /stream |
-sn , --snapshot_url |
Sets the URL for snapshots (single frame of stream). | /snapshot |
-af , --autofocus |
Autofocus mode. Supported modes: manual , continuous . |
continuous |
-l , --lensposition |
Set focal distance. 0 for infinite focus, 0.5 for approximate 50cm. Only used with Autofocus manual. | 0.0 |
-s , --autofocusspeed |
Autofocus speed. Supported values: normal , fast . Only used with Autofocus continuous |
normal |
-ud , --upsidedown |
Rotate the image by 180° (see below) | |
-fh , --flip_horizontal |
Mirror the image horizontally (see below) | |
-fv , --flip_vertical |
Mirror the image vertically (see below) | |
-or , --orientation_exif |
Set the image orientation using an EXIF header (see below) | |
-c , --controls |
Define camera controls to start spyglass with. Can be used multiple times. This argument expects the format <control>=<value>. | |
--list-controls |
List all available libcamera controls onto the console. Those can be used with --controls |
|
-tf , --tuning_filter |
Set a tuning filter file name. | |
-tfd , --tuning_filter_dir |
Set the directory to look for tuning filters. |
Starting the server without any argument is the same as
./run.py -n 0 -b 0.0.0.0 -p 8080 -r 640x480 -f 15 -st '/stream' -sn '/snapshot' -af continuous -l 0.0 -s normal
The stream can then be accessed at http://<IP of the server>:8080/stream
Please note that the maximum recommended resolution is 1920x1080 (16:9).
The absolute maximum resolution is 1920x1920. If you choose a higher resolution spyglass may crash.
There are two ways to change the image orientation.
To use the ability of picamera2 to transform the image you can use the following options when starting spyglass:
-ud
or--upsidedown
- Rotate the image by 180°-fh
or--flip_horizontal
- Mirror the image horizontally-fv
or--flip_vertical
- Mirror the image vertically
Alternatively you can create an EXIF header to modify the image orientation. Most modern browsers should respect the this header.
Use the -or
or --orientation_exif
option and choose from one of the following orientations
h
- Horizontal (normal)mh
- Mirror horizontalr180
- Rotate 180mv
- Mirror verticalmhr270
- Mirror horizontal and rotate 270 CWr90
- Rotate 90 CWmhr90
- Mirror horizontal and rotate 90 CWr270
- Rotate 270 CW
For example to rotate the image 90 degree clockwise you would start spyglass the following way:
./run.py -or r90
Tuning filters are used to normalize or modify the camera image output, for example, using an NoIR camera can lead to a pink color, whether applying a filter to it you could remove its tone pink. More information here: https://github.com/raspberrypi/picamera2/blob/main/examples/tuning_file.py
Predefined filters can be found at one of the picamera2 directories:
- ~/libcamera/src/ipa/rpi/vc4/data
- /usr/local/share/libcamera/ipa/rpi/vc4
- /usr/share/libcamera/ipa/rpi/vc4
- /usr/share/libcamera/ipa/raspberrypi
You can also define your own directory of filter by using parameter tuning_filter_dir
.
list the files present there and you can use it in our config. eg.: ov5647_noir.json
If you want to use Spyglass as a webcam source for Mainsail add a webcam with the following configuration:
- URL Stream:
/webcam/stream
- URL Snapshot:
/webcam/snapshot
- Service:
V4L-MJPEG
If you want to install Spyglass globally on your machine you can use python -m pip install .
to do so.
Quite simple:
cd ~
git clone https://github.com/roamingthings/spyglass
cd ~/spyglass
make install
This will ask you for your sudo
password.
After install is done, please reboot to ensure service starts properly
To uninstall the service simply use
cd ~/spyglass
make uninstall
To be able to use Moonraker update manager, add the following lines to moonraker.conf:
[update_manager spyglass]
type: git_repo
channel: beta
path: ~/spyglass
origin: https://github.com/roamingthings/spyglass.git
managed_services: spyglass
Make sure moonraker.asvc contains
spyglass
in the list:cat ~/printer_data/moonraker.asvc | grep spyglass
.If not there execute:
make upgrade-moonraker
You should find a configuration file in ~/printer_data/config/spyglass.conf
.
Please see spyglass.conf for an example
To restart the service use systemctl
:
sudo systemctl restart spyglass
If you want to setup your environment for development perform the following steps:
Setup your Python virtual environment:
python -m venv .venv # Create a new virtual environment
. .venv/bin/activate # Activate virtual environment
python -m pip install --upgrade pip # Upgrade PIP to the current version
pip install -r requirements.txt # Install application dependencies
pip install -r requirements-test.txt # Install test dependencies
pip install -r requirements-dev.txt # Install development dependencies
The project uses commitizen to check commit messages to comply with Conventional Commits. When installing the development dependencies git-hooks will be set up to check commit messages pre commit.
You may get the following error message when you try to push to your branch:
fatal: ambiguous argument 'origin/HEAD..HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
This error occurs when your HEAD branch is not properly set (Stack Overflow) To fix this run the following command:
git remote set-head origin -a