moonfire-nvr is fire
parent
60c011278f
commit
5aad9c980d
|
|
@ -0,0 +1 @@
|
|||
https://github.com/scottlamb/moonfire-nvr/blob/master/guide/install.md
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
|
||||
read -p "going to: https://github.com/scottlamb/moonfire-nvr/blob/master/guide/install.md as /etc/moonfire-nvr.toml"
|
||||
echo '
|
||||
[[binds]]
|
||||
ipv4 = "0.0.0.0:29898"
|
||||
allowUnauthenticatedPermissions = { viewVideo = true }
|
||||
|
||||
[[binds]]
|
||||
unix = "/var/lib/moonfire-nvr/sock"
|
||||
ownUidIsPrivileged = true
|
||||
' | sudo tee /etc/moonfire-nvr.toml
|
||||
|
||||
sudo mkdir -p /var/lib/moonfire-nvr
|
||||
sudo chmod -R 777 /var/lib/moonfire-nvr
|
||||
|
||||
moonfire-nvr init
|
||||
|
||||
read -p "1. create a SAMPLE DIR first,"
|
||||
read -p "2. use like rtsp://192.168.0.83:8554/unicast with RECORD and DIR for MAIN and SUB"
|
||||
read -p "3. modify SAMPLE DIR to retain N Mbps_/_8_*_120s disk (wyze at home is 5Mbps, so 75MB per 2min file (54GB per day) if noisy?)"
|
||||
moonfire-nvr config
|
||||
|
||||
open http://localhost:29898
|
||||
read -p "moonfire-nvr run"
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#! /bin/bash
|
||||
disabled="false"
|
||||
threshold="0.040"
|
||||
vdir=/tmp/tmpfs
|
||||
exec > >(tee "$vdir/backup.log") 2>&1
|
||||
if ! [ -d "$vdir" ]; then
|
||||
echo $vdir does not exist >&2
|
||||
exit 1
|
||||
fi
|
||||
if ps aux | \
|
||||
grep -v grep | \
|
||||
grep -E 'services.backups.rclone|local.ffprobe'; then
|
||||
echo skipping colliding run >&2
|
||||
exit 0
|
||||
fi
|
||||
echo ok at 1
|
||||
files=($(find $vdir -type f -name "*.m*"))
|
||||
if [ "${#files[@]}" == "0" ]; then
|
||||
echo no files found >&2
|
||||
exit 0
|
||||
fi
|
||||
echo files=${files[@]}
|
||||
includes=()
|
||||
printf "reviewing"; printf " %s\n" "${files[@]}"
|
||||
echo ok at 2
|
||||
for file in "${files[@]}"; do
|
||||
frames="$(
|
||||
nice -n 19 /var/services/homes/squeaky2x3/ffmpeg-local/ffprobe \
|
||||
-threads 1 -loglevel error -hide_banner -show_frames -of compact=p=0 \
|
||||
-f lavfi "movie=$file,select=gt(scene\\,$threshold)" 2> /dev/null \
|
||||
)"
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ] && [ $(printf "%s\n" "$frames" | wc -l) -lt 2 ]; then
|
||||
echo file has no movement $file >&2
|
||||
rm -f "$file"
|
||||
elif [ $ret -ne 0 ]; then
|
||||
echo failed scanning $file >&2
|
||||
files=("${files[@]/"$file"}")
|
||||
else
|
||||
echo file has movement $file
|
||||
includes+=("$(basename "$file")")
|
||||
fi
|
||||
done
|
||||
echo "pushing files ${includes[@]}"
|
||||
if [ "${#includes[@]}" -gt 0 ]; then
|
||||
if [ "$disabled" == "true" ] || \
|
||||
/volume1/homes/squeaky2x3/services/backups/rclone \
|
||||
--config /volume1/homes/squeaky2x3/services/backups/rclone.conf \
|
||||
copy \
|
||||
$vdir/ \
|
||||
blapointe-drive:/projects/cctv/ut/ \
|
||||
$(printf " --include %s" "${includes[@]}") ; then
|
||||
rm -f "${files[@]}"
|
||||
fi
|
||||
fi
|
||||
echo donezo
|
||||
echo why
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
#! /bin/bash
|
||||
|
||||
SEG="${SEG:-300}"
|
||||
|
||||
function main() {
|
||||
if [ "$#" -eq 0 ]; then
|
||||
log "USAGE: $0 ip ip ip..." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
function clean() {
|
||||
kill -9 $(jobs -p)
|
||||
}
|
||||
if [ "$(hostname)" == "Scratch" ]; then
|
||||
trap clean EXIT ERR
|
||||
fi
|
||||
watchman "$@" &
|
||||
for ip in "$@"; do
|
||||
log recording from $ip...
|
||||
record "$ip" &
|
||||
done
|
||||
|
||||
for i in "$@"; do
|
||||
if ! wait -n 1; then
|
||||
log "Something died: $?"
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
done
|
||||
}
|
||||
|
||||
function log() {
|
||||
echo "$(date): $@" >&2
|
||||
}
|
||||
|
||||
function mkdirs() {
|
||||
mkdir -p "${OUT_DIR:-/tmp/ffmpeg_cap}/$(date +%Y)/$(date +%m)/$(date +%d)"
|
||||
}
|
||||
|
||||
function watchman() {
|
||||
log watchman starting on $@
|
||||
local max_last=$SEG
|
||||
max_last=$((max_last*3))
|
||||
function finder() {
|
||||
local suffix="${1:-"*"}"
|
||||
find "${OUT_DIR:-/tmp/ffmpeg_cap}" -type f -name "*_${suffix}.m*"
|
||||
}
|
||||
function mark_last_file() {
|
||||
local now="$(date +%s)"
|
||||
local suffix="$1"
|
||||
local min=$((max_last-1))
|
||||
for f in $(finder "$suffix"); do
|
||||
local ts="$(stat -c '%X' "$f")"
|
||||
if ((now-ts<min)); then
|
||||
min=$((now-ts))
|
||||
fi
|
||||
done
|
||||
echo $min
|
||||
}
|
||||
function check_disk() {
|
||||
if du -s "${OUT_DIR:-/tmp/ffmpeg_cap}" | grep -E '^[6-9][0-9]{5}'; then
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
while sleep 10; do
|
||||
mkdirs
|
||||
for suffix in "$@"; do
|
||||
local seconds=$(mark_last_file "$suffix")
|
||||
log "$suffix: $seconds s"
|
||||
if ((seconds>max_last)); then
|
||||
log "no new videos in $seconds seconds for $suffix, panicking"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
until check_disk; do
|
||||
local f="$(finder | sort | head -n 1)"
|
||||
log "high disk usage, pruning $f"
|
||||
rm -f "$f"
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
function record() {
|
||||
log "starting record for $@"
|
||||
_record "$@"
|
||||
tail -n 50 /tmp/ffmpegs.log
|
||||
}
|
||||
|
||||
function _record() {
|
||||
local out="${OUT_DIR:-/tmp/ffmpeg_cap}/%Y/%m/%d/%H-%M-%S_${1}.mp4"
|
||||
mkdirs
|
||||
ffmpeg \
|
||||
-threads 0 \
|
||||
-nostdin \
|
||||
-nostats \
|
||||
-loglevel error \
|
||||
-i rtsp://192.168.0.$1:8554/unicast \
|
||||
-an \
|
||||
-map 0 \
|
||||
-force_key_frames "expr:gte(t,n_forced*9)" \
|
||||
-f segment \
|
||||
-segment_time $SEG \
|
||||
-segment_format mp4 \
|
||||
-strftime 1 \
|
||||
-minrate .05k \
|
||||
-vcodec copy \
|
||||
"$out" \
|
||||
-vf "select=gt(scene\,0.003),setpts=N/(15*TB)" \
|
||||
< /dev/null \
|
||||
>> /tmp/ffmpegs.log \
|
||||
2>&1
|
||||
}
|
||||
|
||||
if [ "$0" == "$BASH_SOURCE" ]; then
|
||||
main "$@"
|
||||
fi
|
||||
|
||||
Loading…
Reference in New Issue