Added ENV variables for all config, Fixed error in cleaner script
Update cleaner.py, docker-compose.yml, and 2 more files...
This commit is contained in:
parent
6b3ef62c4b
commit
d7538b950e
12
cleaner.py
12
cleaner.py
@ -3,8 +3,14 @@ import signal
|
||||
import sys
|
||||
import time
|
||||
|
||||
# Keep files for 73 hours (3 days + 1 hours)
|
||||
MAX_FILE_AGE_SECONDS = (72 + 1) * 60 * 60
|
||||
# Keep files for 72 hours (3 days)
|
||||
try:
|
||||
MAX_FILE_AGE_SECONDS = int(os.environ.get('NP_MAX_FILE_AGE_HOURS', "72")) * 60 * 60
|
||||
except err:
|
||||
print("Error: ")
|
||||
print(err)
|
||||
print("Using 72 hours instead !")
|
||||
MAX_FILE_AGE_SECONDS = 72 * 60 * 60
|
||||
|
||||
# Once done cleaning, sleep for 5 minutes
|
||||
SLEEP_TIME_SECONDS = 5 * 60
|
||||
@ -37,7 +43,7 @@ start_time = time.time()
|
||||
file_deleted_count = 0
|
||||
|
||||
for item in os.listdir("/data/"):
|
||||
item_path = os.path.join(folder_path, item)
|
||||
item_path = os.path.join("/data/", item)
|
||||
|
||||
if os.path.isdir(item_path):
|
||||
file_deleted_count = file_deleted_count + delete_old_files(item_path, start_time)
|
||||
|
@ -32,6 +32,7 @@ services:
|
||||
dockerfile: Dockerfile_cleaner
|
||||
environment:
|
||||
- TZ=Europe/Brussels
|
||||
- "NP_MAX_FILE_AGE_HOURS=72"
|
||||
volumes:
|
||||
- ./recordings:/data
|
||||
- ./cleaner.py:/app/app.py:ro
|
||||
@ -43,6 +44,10 @@ services:
|
||||
ports:
|
||||
- 26880:80
|
||||
environment:
|
||||
- "NP_CAM_cam1=Camera #1"
|
||||
- "NP_CAM_cam2=Camera #2"
|
||||
- "NP_TITLE=NibblePoker's Mini CCTV NVR"
|
||||
- "NP_FOOTER=Made by <i>BOZET Herwin</i>"
|
||||
- TZ=Europe/Brussels
|
||||
volumes:
|
||||
- ./htdocs:/var/www/html # Cannot be "ro" since the recordings are mounted into it.
|
||||
|
@ -1,10 +1,17 @@
|
||||
<?php
|
||||
// List of all available cameras
|
||||
$camsInfo = [
|
||||
# Format: [camId, camName]
|
||||
["cam1", "Cam #1"],
|
||||
["cam2", "Cam #2"]
|
||||
];
|
||||
// Grabbing the camera's info
|
||||
|
||||
$camsInfo = []; // Format: [[camId, camName], ...]
|
||||
|
||||
foreach ($_ENV as $envKey => $envValue) {
|
||||
if (strpos($envKey, 'NP_CAM_') === 0) {
|
||||
array_push($camsInfo, [substr($envKey, strlen('NP_CAM_')), $envValue]);
|
||||
}
|
||||
}
|
||||
|
||||
// Grabbing the other env variables.
|
||||
$pageTitle = $_ENV['NP_TITLE'] ?? 'NibblePoker\'s Mini CCTV NVR';
|
||||
$pageFooter = $_ENV['NP_FOOTER'] ?? 'Made by <a href="https://github.com/aziascreations">BOZET Herwin</a> on <a href="https://github.com/aziascreations/Docker-Mini-CCTV-NVR">Github</a>';
|
||||
|
||||
// Root location of all recordings. (Not used yet)
|
||||
$rootLocation = "./data/";
|
||||
@ -102,7 +109,7 @@ function sizeFormat($bytes) {
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>NibblePoker's Mini CCTV NVR</title>
|
||||
<title><?php echo($pageTitle); ?></title>
|
||||
<link rel="stylesheet" href="/css/simplette.all.min.css">
|
||||
<style>
|
||||
#video-selector {
|
||||
@ -139,13 +146,13 @@ function sizeFormat($bytes) {
|
||||
?>
|
||||
</ul>
|
||||
</nav>
|
||||
<header><h1><b>NibblePoker's Mini CCTV NVR</b></h1></header>
|
||||
<header><h1><b><?php echo($pageTitle); ?></b></h1></header>
|
||||
<hr><hr>
|
||||
<div class="margin-container auto-paragraph-margin">
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td>
|
||||
<h3 style="width: 100%;">Caméra: <i><?php echo($camName); ?></i></h3>
|
||||
<h3 style="width: 100%;">Camera: <i><?php echo($camName); ?></i></h3>
|
||||
</td>
|
||||
<td>
|
||||
<span style="float: right;"><?php
|
||||
@ -201,8 +208,7 @@ function sizeFormat($bytes) {
|
||||
</div>
|
||||
<hr><hr>
|
||||
<footer>
|
||||
<!-- Feel free to change this to something less invasive, or simply stats. Your imagination is the limit :) -->
|
||||
<p>Made by <a href="https://github.com/aziascreations">BOZET Herwin</a> on <a href="https://github.com/aziascreations/Docker-Mini-CCTV-NVR">Github</a></p>
|
||||
<p><?php echo($pageFooter); ?></p>
|
||||
</footer>
|
||||
<script>
|
||||
<?php
|
||||
|
101
readme.md
101
readme.md
@ -2,16 +2,19 @@
|
||||
A mini docker stack that allows you to easily record, clean and serve CCTV recordings made over RSTP while using a
|
||||
minimal amount of system resources.
|
||||
|
||||
## Preamble
|
||||
This stack records the camera's streams as-is and doens't re-encode or compress it which can cause it to use more disk space.<br>
|
||||
The highest I've got on my side is around 70 GiB per day for a 4K-ish cam with AAC audio.
|
||||
This stack is mainly intended to be used as a backup when other and more complete solutions crash or need to be shutdown.
|
||||
|
||||
It is highly recommended to put the web page behind a secure reverse-proxy that requires authentication for aditional security.
|
||||
## Preamble
|
||||
This stack records the camera's streams as-is and doens't re-encode or compress it which uses more disk space.<br>
|
||||
See "[Usage statistics example](#usage-statistics-example)" for an example.
|
||||
|
||||
If served out of your LAN, the web server should be behind a secure reverse-proxy that requires authentication.
|
||||
|
||||
## Setup
|
||||
Since the stack is a bit rough around the edges for simplicity''s sake you **will** need to setup a couple of things beforehand.
|
||||
All of the setup is done through environment variables in the [docker-compose.yml](docker-compose.yml) file.
|
||||
|
||||
It should only take 2-3 minutes if you already have the RTSP URL on hand however.
|
||||
It should only take 2-3 minutes if you already have the RTSP URL on hand.<br>
|
||||
If you don't have them, you should see your camera's user manual and test the URLs with [VLC](https://www.videolan.org/vlc/).
|
||||
|
||||
### Cameras
|
||||
Each recording container needs to be given a RSTP stream URL and a unique folder into which the recordings will go.
|
||||
@ -19,7 +22,7 @@ Each recording container needs to be given a RSTP stream URL and a unique folder
|
||||
The URL must be given via the `NP_CCTV_URL` environment variable, and the output folder via a mounted volume that is
|
||||
mounted as `/data` in the container.
|
||||
|
||||
Here is a simple example:
|
||||
#### Example:
|
||||
```yaml
|
||||
cctv_recorder_cam1:
|
||||
container_name: cctv-recorder-cam1
|
||||
@ -37,26 +40,61 @@ Here is a simple example:
|
||||
This example will use the `rtsp://user:password@address:554/sub-path` URL and will put its recordings in `./recordings/cam1`.
|
||||
|
||||
### Cleaner
|
||||
The cleaner script named [cleaner.py](cleaner.py) only requires you to change 1 variable located near the top of the file.
|
||||
The cleaner script named [cleaner.py](cleaner.py) only requires you to set 1 environment variable named `NP_MAX_FILE_AGE_HOURS`
|
||||
to the max amount of hours any recording should be kept.
|
||||
|
||||
The variable named `MAX_FILE_AGE_SECONDS` is used to indicate how long recordings should be kept for and is set to
|
||||
73 hours by default.
|
||||
If not set, the script will simply clean any recordings older than 72 hours.
|
||||
|
||||
It can also be changed as you wish without recreating the stack since the script is "reloaded" on each run.
|
||||
|
||||
### Web interface
|
||||
The web interface only requires you to give it the list of all cams' IDs and a friendly name in the `$camsInfo` variable.
|
||||
|
||||
This variable is located at the top of the [htdocs/index.php](htdocs/index.php) file and should look like this:
|
||||
```php
|
||||
$camsInfo = [
|
||||
# Format: [camId, camName]
|
||||
["cam1", "Cam #1"],
|
||||
["cam2", "Cam #2"]
|
||||
];
|
||||
#### Example
|
||||
```yaml
|
||||
cctv_cleaner:
|
||||
container_name: cctv-cleaner
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile_cleaner
|
||||
environment:
|
||||
- TZ=Europe/Brussels
|
||||
- "NP_MAX_FILE_AGE_HOURS=72"
|
||||
volumes:
|
||||
- ./recordings:/data
|
||||
- ./cleaner.py:/app/app.py:ro
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
The cam's ID refers to a subfolder of `./recordings` into which this cam's recordings are found as `.mp4` or `.mkv` files.
|
||||
### Web interface
|
||||
The web interface provides more customization options, but at its core, it only requires the camera's environment variables to be set.
|
||||
|
||||
Each camera requires one of the following environment variable:<br>
|
||||
`NP_CAM_<camId> = <Camera's name>`
|
||||
|
||||
Here is an example for `cam1` if named as `Camera #1`:<br>
|
||||
`NP_CAM_cam1 = Camera #1`
|
||||
|
||||
#### Other variables
|
||||
| Variable | Description |
|
||||
| ----------- | -------------------------- |
|
||||
| `NP_TITLE` | Page's title |
|
||||
| `NP_FOOTER` | Page's footer HTML content |
|
||||
|
||||
#### Example:
|
||||
```yaml
|
||||
cctv_web:
|
||||
container_name: cctv-web
|
||||
image: php:apache
|
||||
ports:
|
||||
- 26880:80
|
||||
environment:
|
||||
- TZ=Europe/Brussels
|
||||
- "NP_CAM_cam1=Camera #1"
|
||||
- "NP_CAM_cam2=Camera #2"
|
||||
- "NP_TITLE=NibblePoker's Mini CCTV NVR"
|
||||
- "NP_FOOTER=Made by <i>BOZET Herwin</i>"
|
||||
volumes:
|
||||
- ./htdocs:/var/www/html # Cannot be ":ro" since the recordings are mounted into it.
|
||||
- ./apache2.conf:/etc/apache2/apache2.conf:ro
|
||||
- ./recordings:/var/www/html/data:ro
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
## Startup
|
||||
Once you have finished setting up the stack, you can simply run the following command:
|
||||
@ -65,12 +103,23 @@ docker-compose up --build -d
|
||||
```
|
||||
|
||||
## Screenshots
|
||||
### Home page
|
||||
![alt text](screenshots/home.png)
|
||||
|
||||
### Camera's page with blurred preview
|
||||
![alt text](screenshots/cam.png)
|
||||
|
||||
## Usage statistics example
|
||||
* NanoPi R4S 4GB
|
||||
* Uses 0.008 kWh / 8 Watts with other containers and USB HDD & USB SSD
|
||||
* 4 IP Cameras
|
||||
* All H.256 4k RTSP TCP streams
|
||||
* Around 220 GB of data per day
|
||||
* Around 20.4 Mbit/s or 2.6 MB/s
|
||||
* Less than 200MB of RAM usage
|
||||
* ~32 MB per recorder
|
||||
* 4 MB for cleaner
|
||||
* 4 MB for web server
|
||||
* Uses ~10% of CPU on average over 6 cores
|
||||
* Average of 15% per recorder
|
||||
* Average of 1-5% on cleaner and web server
|
||||
|
||||
## License
|
||||
This software, as well as the [Simplette CSS Stylesheet](https://github.com/aziascreations/Simplette-CSS-Stylesheet)
|
||||
|
Loading…
Reference in New Issue
Block a user