A Raspberry Pi camera system with a live video feed, motion detection system, H.264 mp4 recording capabilities and a storage management system with support for remote storage. The recorder supports pre-motion frame recording and no internet environments (e.g. Wildlife cameras).
NOTE: This entire project is for the legacy pi cameras
NOTE: Legacy versions of this project are moved to the ‘legacy’ directory (These are the legacy versions of THIS project, not to be confused with the legacy versions of the pi camera)
A Raspberry Pi camera system with a live video feed, motion detection system, H.264 mp4 recording capabilities and a storage management system with support for remote storage.
The recorder supports pre-motion frame recording and no internet environments (e.g. Wildlife cameras).
Confirmed working on Raspberry Pi 3b, 3b+, 4. Other versions will probably work, but they haven’t been tested.
Feature | |
---|---|
- Live low-bandwidth H.264 Streaming to a local web page. | |
- Advanced motion detection system that records H.264 .mp4 videos when motion is detected. | |
- Even frames from before the motion triggering event are recorded, so everything will be on video. | |
- Detection sensitivity, recording length, and much more is all easily user configurable. | |
- Storage management system that automatically removes the oldest recordings when the storage is almost full. | |
- Recordings can be sent to a separate storage device on the network. | |
- As long as local storage is used, the camera doesn’t require an internet connection. So it can be used as a wildlife camera. | |
- Support for multiple cameras. | |
- The recordings and the live stream can be viewed from a Django web page. |
sudo raspi-config
menu.sudo apt update
sudo apt install python3-opencv
python3 -c "import cv2; print(cv2.__version__)"
3.0.0
you are good to go.sudo apt install git
):
cd ~
git clone https://github.com/Ruud14/SecurityCamera.git
python3 main.py
. But first make sure all necessary packages are installed: pip3 install -r requirements.txt
(python 3.11+ might additionally require this).http://<local_pi_ip>:8000/index.html
as long as streamer_active
is set to true
in the configuration file. Don’t forget to replace <local_pi_ip>
with the local IP address of your Raspberry Pi.storage_option
is set to local
(default), the recordings will be stored in the local_recordings_output_path
directory (assuming recorder_active
is set to true
).storage_option
is set to be the IP address of another storage device on the network, you should follow the Remote storage receiver guide below the Configuration guide.convert_h264_to_mp4
is set to true
).convert_h264_to_mp4
is set to true
).main.py
at startup can be achieved with i.a chronjobs.The configuration of the camera can be changed in the config.json
file, which looks like this by default:
{
"streamer_active": true,
"recorder_active": true,
"camera_resolution": "1600x1200",
"camera_fps": 15,
"camera_vFlip": false,
"camera_hFlip": false,
"camera_denoise": true,
"annotate_time": true,
"stream_resolution": "1120x840",
"detection_resolution": "64x48",
"detector_motion_threshold": 20,
"record_seconds_before_motion": 5,
"record_seconds_after_motion": 12,
"max_recording_seconds": 600,
"temporary_local_recordings_output_path": "./temp_recordings/",
"convert_h264_to_mp4": true,
"ffmpeg_path": "/usr/local/bin/ffmpeg",
"storage_option": "local",
"local_recordings_output_path": "./recordings/",
"max_local_storage_capacity": 25
}
Name | Description | Type | Required | Default value |
---|---|---|---|---|
streamer_active |
Determines if the camera can be looked at via http://<local_pi_ip>:8000/index.html . |
Boolean | Yes | true |
recorder_active |
Determines if the camera will start recording when there is motion. | Boolean | Yes | true |
camera_resolution |
The resolution of the camera. This resolution can not be lower than stream_resolution and/or detection_resolution . Supported resolution and frame rate combinations can be found here. |
String | Yes | "1600x1200" |
camera_fps |
The frame rate of the camera. Supported resolution and frame rate combinations can be found here. | Integer | Yes | 15 |
camera_vFlip |
Determines if the camera is flipped vertically. | Boolean | Yes | false |
camera_hFlip |
Determines if the camera is flipped horizontally. | Boolean | Yes | false |
camera_denoise |
Determines if noise reduction is active. | Boolean | Yes | true |
annotate_time |
Determines if the current date and time will be shown in the video. | Boolean | Yes | true |
stream_resolution |
The resolution of the live stream. This resolution can not be higher than camera_resolution . Try to use the same aspect ratio as camera_resolution e.g. 16:9 or 4:3. |
String | Only if streamer_active is set to true . |
"1120x840" |
detection_resolution |
The resolution at which motion detection is happening. This should be a really low resolution to make it less CPU intensive. Try to use the same aspect ratio as camera_resolution e.g. 16:9 or 4:3. |
String | Only if recorder_active is set to true . |
"64x48" |
detector_motion_threshold |
Threshold for detecting motion. The higher this number, the less motion is detected. | Integer | Only if recorder_active is set to true . |
20 |
record_seconds_before_motion |
The amount of seconds that will be recorded before motion is detected. | Integer | Only if recorder_active is set to true . |
5 |
record_seconds_after_motion |
The amount of seconds that will be recorded after motion. If there is more motion detected within record_seconds_after_motion seconds after the first motion is detected, it will continue recording until no more motion is detected or max_recording_seconds is exceeded. |
Integer | Only if recorder_active is set to true . |
12 |
max_recording_seconds |
The maximum duration of a recording in seconds. | Integer | Only if recorder_active is set to true . |
600 |
temporary_local_recordings_output_path |
The directory where parts of recordings will be temporarily stored. | String | Only if recorder_active is set to true . |
./temp_recordings/ |
convert_h264_to_mp4 |
Determines whether or not the .h264 recordings will be converted to .mp4. | Boolean | Only if recorder_active is set to true . |
true |
ffmpeg_path |
Path to the the ffmpeg executable. The default value will most likely be the right path. If not, you can find the correct path using the whereis ffmpeg command. |
String | Only if convert_h264_to_mp4 is set to true . |
/usr/local/bin/ffmpeg |
storage_option |
Determines how your recordings will be stored. Use the local IP address of a local storage device on which file_receiver.py is running for remote storage e.g. 192.168.x.x . Use local to store all recordings locally in the local_recordings_output_path directory. |
String | Only if recorder_active is set to true . |
local |
local_recordings_output_path |
The directory where recordings will be stored. | String | Only if storage_option is set to local . |
./recordings/ |
max_local_storage_capacity |
The maximum storage capacity that the recordings can occupy in Gigabytes. If this value is about to be exceeded, the oldest recordings will be removed. | Integer | Only if storage_option is set to local . |
25 |
This part is only necessary for users that want to use remote storage!
If you want your recordings to be stored on another storage device on the network, you should do the following:
On the Raspberry Pi Camera:
config.json
:
storage_option
to the local IP address of the storage device e.g. 192.168.x.x.
On the Storage device:
recordings_receiver
directory.python3 recordings_receiver.py
.config.json
which looks something like this:{
"recordings_output_path": "./recordings/",
"max_storage_capacity": 25
}
The values can be changed according to the table below:
Name | Description | Type | Required | Default value |
---|---|---|---|---|
recordings_output_path |
The directory where recordings will be stored. | String | Yes | ./recordings/ |
max_storage_capacity |
The maximum storage capacity that the recordings can occupy in Gigabytes. If this value is about to be exceeded, the oldest recordings will be removed. | Integer | Yes | 25 |
recordings_receiver.py
at startup can be achieved with i.a chronjobs.If you are having trouble installing or configuring, feel free to e-mail me!
If you come across any bugs or want to see a new feature, please let me know here.