Photo by Bernadette Wurzinger
minigugl
is a little video streaming client to read an MJPEG video stream and store it in chunks (segments) locally as H.264-encoded video files. It's highly configurable and the perfect little helper to continuously record videos to file (e.g., for dashcams or security cameras).
This project uses poetry
for Python dependency management and requires Python 3.6.1+
, but no newer than Python 3.7.x
due to its dependencies. pyenv
is a great tool to manage different Python versions.
It furthermore requires FFmpeg
for video encoding/decoding.
minigugl
uses the fantastic Python video processing framework called vidgear
to read an MJPEG stream with VideoGear
and process it through FFmpeg with WriteGear
.
Video frames are augmented with text using OpenCV. This includes timestamps using arrow
and optionally GPS coordinates using gpsd
, e.g., using a Globalsat BU-353S4 GPS USB Receiver.
- Clone the GitHub repo:
git clone git@github.com:FraBle/minigugl.git
- Inside
minigugl
directory, runpoetry install --no-root
to install dependencies.- Use
poetry install --no-root --extras gps
to install it with GPS tooling.
- Use
minigugl
uses pydantic's settings management
and provides defaults for all parameters except OUTPUT_DIR
and VIDEO_SOURCE
.
The following parameters can be passed in as environment variables. Alternatively, you can use a .env
file as well.
Environment Variable | Type | Required | Default |
---|---|---|---|
OUTPUT_DIR |
str |
Yes | |
VIDEO_SOURCE |
str |
Yes | |
DEBUG |
bool |
No | False |
LOG_FORMAT |
str |
No | provided |
LOG_LEVEL |
str |
No | "info" |
ENABLE_GPS |
bool |
No | False |
GPS_INTERVAL_SEC |
float or int |
No | 0.1 |
ANNOTATION_FONT_HEIGHT |
int |
No | 15 |
ANNOTATION_MARGIN |
int |
No | 5 |
ANNOTATION_PADDING |
int |
No | 5 |
VIDEO_CODEC |
str |
No | "libx264" |
VIDEO_FRAMERATE |
int |
No | 24 |
VIDEO_HEIGHT |
int |
No | 480 |
VIDEO_SEGMENT_LENGTH_SEC |
int |
No | 60 |
VIDEO_WIDTH |
int |
No | 640 |
With all required environment variables set, execute the following code inside the repo directory to start the video streaming client:
poetry run python -m minigugl.client
Based on
These steps have been verified with a Raspberry Pi 3B+ running DietPi with the following DietPi-optimised software installed:
[ ] 0 OpenSSH Client: Feature-rich SSH, SFTP and SCP client
[ ] 16 Build-Essentials: common packages for compiling
[ ] 17 Git Client: Clone and manage Git repositories locally
[ ] 103 DietPi-RAMlog: minimal, optimised logging
[ ] 104 Dropbear: Lightweight SSH server
Changes applied to dietpi.txt
for easier, headless setup:
AUTO_SETUP_ACCEPT_LICENSE=1
AUTO_SETUP_LOCALE=en_US.UTF-8
AUTO_SETUP_KEYBOARD_LAYOUT=us
AUTO_SETUP_TIMEZONE=America/Los_Angeles
AUTO_SETUP_NET_WIFI_ENABLED=1
AUTO_SETUP_NET_WIFI_COUNTRY_CODE=US
AUTO_SETUP_NET_HOSTNAME=<custom hostname>
AUTO_SETUP_HEADLESS=1
AUTO_SETUP_AUTOSTART_TARGET_INDEX=7
AUTO_SETUP_AUTOMATED=1
AUTO_SETUP_GLOBAL_PASSWORD=<custom password>
AUTO_SETUP_INSTALL_SOFTWARE_ID=0 #OpenSSH Client
AUTO_SETUP_INSTALL_SOFTWARE_ID=16 #Build-Essentials
AUTO_SETUP_INSTALL_SOFTWARE_ID=17 #Git
AUTO_SETUP_INSTALL_SOFTWARE_ID=103 #DietPi-RAMlog
AUTO_SETUP_INSTALL_SOFTWARE_ID=104 #Dropbear
CONFIG_BOOT_WAIT_FOR_NETWORK=2
Changes applied to config.txt
for camera setup:
#-------RPi camera module-------
start_x=1
#disable_camera_led=1
#-------GPU memory splits-------
gpu_mem_256=128
gpu_mem_512=128
gpu_mem_1024=128
Don't forget to set aWIFI_SSID[0]
and aWIFI_KEY[0]
in dietpi-wifi.txt
.
Once the Raspberry Pi comes up and is connected to the WiFi, follow these steps:
-
Install
v4l2rtspserver
sudo apt install -y cmake liblog4cpp5-dev libv4l-dev cd /tmp git clone https://github.com/mpromonet/v4l2rtspserver.git cd /tmp/v4l2rtspserver cmake . make sudo make install
-
Install
v4l-utils
for debugging & control commandssudo apt install v4l-utils
Example "rotatation of camera":
v4l2-ctl --set-ctrl=rotate=90
-
Add
v4l2-ctl
command to system boot viaudev
subsystemsudo nano /etc/udev/rules.d/99-local-webcam.rules
:SUBSYSTEM=="video4linux", PROGRAM="/usr/bin/v4l2-ctl --set-ctrl=rotate=90"
-
Add
bcm2835-v4l2
to/etc/modules
(kernel modules to load at boot time)sudo nano /etc/modules
:# Add to the end of the file bcm2835-v4l2
-
Set parameters for
bcm2835-v4l2
by creating a config file:sudo nano /etc/modprobe.d/bcm2835-v4l2.conf
:options bcm2835-v4l2 max_video_width=640 options bcm2835-v4l2 max_video_height=480
-
Reboot Raspberry Pi with
reboot
and test the setup by startingv4l2rtspserver
with open source V4L2 driverbcm2835-v4l2
v4l2-ctl --all # should print driver and device info with set resolution v4l2rtspserver -W640 -H480 -F30 -P8555 /dev/video0 # start RTSP server manually
-
Testing H264 RTSP video stream, e.g. with VLC from a MacBook
vlc rtsp://<rpi-ip>:8555/unicast
-
Add
v4l2rtspserver
start-up scriptCreate start-up script
sudo nano /usr/local/bin/start-rtsp-server
:#!/bin/bash v4l2rtspserver -W640 -H480 -F30 -P8555 /dev/video0
Add execution rights with
sudo chmod +x /usr/local/bin/start-rtsp-server
. -
Add
v4l2rtspserver
to systemdCreate systemd entry
sudo nano /lib/systemd/system/v4l2rtspserver.service
:[Unit] Description=V4L2 RTSP server After=network.target [Service] Type=simple ExecStart=/usr/local/bin/start-rtsp-server Restart=always RestartSec=1 StartLimitIntervalSec=0 [Install] WantedBy=multi-user.target
Enable
v4l2rtspserver.service
sudo systemctl daemon-reload sudo systemctl enable v4l2rtspserver.service sudo systemctl start v4l2rtspserver.service
-
Reboot Raspberry Pi with
reboot
and confirm everything starts automaticallyOpen H264 RTSP video stream, e.g. with VLC from a MacBook:
vlc rtsp://<rpi-ip>:8555/unicast
If you encounter an error such as
root@guglhupf-agent-2:~# /usr/local/bin/start-rtsp-server
2021-04-24 16:24:49,091 [NOTICE] - /tmp/v4l2rtspserver/main.cpp:294
Version: 0.2.3-26-gd0da079 live555 version:2021.04.06
2021-04-24 16:24:49,092 [NOTICE] - /tmp/v4l2rtspserver/src/V4l2RTSPServer.cpp:36
Create V4L2 Source.../dev/video0
2021-04-24 16:24:49,092 [NOTICE] - /tmp/v4l2rtspserver/v4l2wrapper/src/V4l2MmapDevice.cpp:49
Device /dev/video0
VIDIOC_REQBUFS: Inappropriate ioctl for device
2021-04-24 16:24:49,092 [NOTICE] - /tmp/v4l2rtspserver/v4l2wrapper/src/V4l2MmapDevice.cpp:141
Device /dev/video0
VIDIOC_STREAMOFF: Inappropriate ioctl for device
VIDIOC_REQBUFS: Inappropriate ioctl for device
...restart the picamera, e.g. using dietpi-config
(under 1 : Display Options
).
-
Install
gpsd
packagesapt install gpsd gpsd-clients
-
Edit gpsd config (setting
DEVICES
,GPSD_OPTIONS
, andGPSD_SOCKET
)nano /etc/default/gpsd
/etc/default/gpsd
for reference:# Default settings for the gpsd init script and the hotplug wrapper. # Start the gpsd daemon automatically at boot time START_DAEMON="true" # Use USB hotplugging to add new USB devices automatically to the daemon USBAUTO="true" # Devices gpsd should collect to at boot time. # They need to be read/writeable, either by user gpsd or the group dialout. DEVICES="/dev/ttyUSB0" # Other options you want to pass to gpsd # "-n: Don't wait for a client to connect before polling whatever GPS is associated with it." GPSD_OPTIONS="-n" GPSD_SOCKET="/var/run/gpsd.sock"
-
Enable the gpsd service
systemctl enable gpsd.socket systemctl start gpsd.socket
-
Verify GPS connection by running
gpsmon
and/orcgps