Last active
October 4, 2022 18:05
-
-
Save paius1/f758e33183616c03d6bd66b4b89ae2a1 to your computer and use it in GitHub Desktop.
Script to view and Monitor rtsp:// stream from a security camera
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# | |
# Simple script to monitor a ipcam stream running on mpv | |
# using the ipc-server | |
# requires mpv, socat, and jq written for bash 4 | |
# xwinwrap to run on the Desktop | |
# by gmail plgroves 2019 | |
# | |
# script creates a kill script in same path as this script | |
# named This_script-kill | |
# if path is not writable it is in $HOME | |
# | |
# it also creates a .desktop file so it shows up in the | |
# menu under the Video/Multimedia Category | |
# | |
userName="username" | |
passWord="password" # We shouldn't put plaintext passwords in files | |
HOST="127.0.0.1" | |
PORT="554" | |
pATH="/path/to/stream" | |
# Run as desktop background | |
deskTop=false | |
# You may have to play with SLEEP stay in the middle loop | |
SLEEP=2 | |
# audioDevice=(--no-audio) | |
# or mpv --audio-device=help | grep pulse or alsa | |
# audioDevice=(--audio-device=pulse/alsa_output.1.analog-stereo) | |
# Here you can add your own arguments to mpv | |
# addArguments+=() | |
addArguments+=(--window-scale=.5) | |
[[ $deskTop == "true" ]] && { addArguments+=(--no-osc); } | |
#----------------------------------------------------- | |
me=$0 && fileName=$(basename ${me}) | |
hostName=$(nmap -sL $HOST | grep report | cut -d' ' -f5) | |
socket="/tmp/mpvsocket-${fileName} " # yes there is a space here | |
logFile=/tmp/mpvlog.file | |
# ---------------------------------------------------- | |
# exit from an infinite loop cleanly | |
trap ctrl_c INT | |
echo Double Ctrl-C to exit | |
function ctrl_c { | |
echo -en "\n## Caught SIGINT; Clean up and Exit \n" | |
$killScript | |
exit $? | |
} | |
# Check for required programs | |
# mpv | |
[[ $(command -v mpv) ]] || { echo "\n mpv not found\n Can't continue\n"; ctrl_c; } | |
# socat | |
[[ $(command -v socat) ]] || { echo "\n socat not found\n Can't communicate with mpv\n"; ctrl_c; } | |
# jq | |
[[ $(command -v jq) ]] || { echo -e "\n jq not found\n can't keep track of stream position \n"; ctrl_c; } | |
# xwinwrap to run mpv on the Desktop | |
[[ ${deskTop} == "true" && $(command -v xwinwrap) ]] || { deskTop=false; echo -e "\n\tWon't run on the Desktop\n"; } | |
# Changes to $command to run as the Desktop Background | |
[[ ${deskTop} == "true" ]] && { winDesktop=( -wid WID --window-scale=1); runDesktop=(xwinwrap -g $(xdpyinfo | grep 'dimensions:'|awk '{print $2}') -ov --); addArguments=($(echo ${addArguments[@]//--window-scale*/})); } | |
# Create .desktop file for this script - you can edit for future use | |
scriptDesktop=$HOME/.local/share/applications/${hostName}.$(echo $HOST | cut -d'.' -f4).desktop | |
if [ ! -f "${scriptDesktop}" ]; then | |
# Create entry in the Application/Video Menu | |
cat <<-EOF >$scriptDesktop | |
[Desktop Entry] | |
Type=Application | |
StartupNotify=true | |
Name=IP Camera @ $hostName | |
Icon=mpv | |
Exec=$me | |
Categories=GTK;GNOME;Video;AudioVideo | |
EOF | |
fi | |
# Create kill script for infinite 'while' loop | |
# and add to Application/Video Menu | |
killScript=$me-kill | |
scriptDesktop=$HOME/.local/share/applications/${fileName}-kill.desktop | |
touch $killScript &>> /dev/null || killScript=$HOME/$fileName-kill | |
echo -e "Kill with\n $killScript" | |
cat <<-EOF > $killScript | |
#!/bin/sh | |
echo '{ "command": ["quit"] }' | socat - $socket > /dev/null 2>&1 | |
rm -f $socket $scriptDesktop $killScript | |
echo -e "\n`date "+%F %l:%M:%S %p"` Stopped server for $hostName cleanly" | tee -a $logFile | |
ps -ef | egrep -wi --color '${socket}|${fileName}' | grep -v grep | awk '{print \$2}' | xargs kill -9 > /dev/null 2>&1 | |
EOF | |
chmod u+x $killScript | |
# Create .desktop | |
cat <<-EOF >$scriptDesktop | |
[Desktop Entry] | |
Type=Application | |
Name=IP Camera @ $hostName STOP | |
Icon=gtk-delete | |
Exec=$killScript | |
Categories=GTK;GNOME;Video;AudioVideo; | |
EOF | |
# Functions | |
# create stream url | |
function streamUrl () { | |
stream="rtsp://$userName:$passWord@$HOST:$PORT$pATH" | |
} | |
# start server | |
function start_Server () { | |
command="${runDesktop[*]} mpv ${winDesktop[*]} --input-ipc-server=${socket} --idle --keep-open=always ${audioDevice[*]} ${addArguments[*]} --title $hostName --x11-name $hostName --no-cache --untimed --no-demuxer-thread --video-sync=audio --vd-lavc-threads=1 --log-file=/tmp/camera.log > /tmp/cameraOutput.log" | |
$command &>> /dev/null 2>&1 & | |
} | |
# send video file to mpv | |
function open_Stream () { | |
stream=$1 | |
#sleep $SLEEP | |
response=$(echo "{ \"command\": [\"loadfile\", \"${stream}\"] }" | socat - $socket) || return 255 | |
return 0 | |
} | |
# Monitor stream position | |
function streamPosition () { | |
POSITION=$(echo '{ "command": ["get_property_string", "time-pos"] }' | socat - $socket | jq .data | tr '"' ' ' | cut -d'.' -f 1 | xargs -i echo "({}/1)" | bc ) | |
} | |
# End Functions | |
# Starting Server | |
echo -e "\n`date "+%F %l:%M:%S %p"` Starting Server for $hostName" | tee -a $logFile | |
start_Server | |
# Wait for camera to become reachable | |
while true; do printf '%s\r' "`date "+%F %l:%M:%S %p"` ping $hostName" | tee -a $logFile; ping -c 1 $HOST > /dev/null && break; sleep 2; done | |
sleep $SLEEP | |
streamUrl | |
open_Stream $stream | |
echo -e "`date "+%F %l:%M:%S %p"` Opened $stream" | tee -a $logFile | |
# Waiting for stream to stream. | |
while [[ $POSITION -lt 1 ]]; do | |
streamPosition | |
printf '%s\r' "`date "+%F %l:%M:%S %p"` waiting for $hostName $stream" | tee -a $logFile | |
done; | |
sleep $SLEEP | |
echo | tee -a $logFile | |
# Starting endless Loop | |
while true; do | |
positionCheck=0 | |
# This Loop monitors "the postion in the stream" | |
while true; do | |
streamPosition | |
printf '%s %s\r' "previous $positionCheck" "current $POSITION $hostName" | tee -a /tmp/debug.log | |
if [ -z $POSITION ]; then break; fi | |
# Not moving forward then let's break and restart | |
[[ "$positionCheck" -ge "$POSITION" ]] && { echo -e "\n${hostName} ${stream} not moving forward \nprevious position $positionCheck current $POSITION" | tee -a $logfile; break; } | |
# print "the postion in the stream" | |
printf ' %d:%02d:%02d %s \r' $(($POSITION/3600)) $(($POSITION%3600/60)) $(($POSITION%60)) $stream | tee -a $logFile | |
positionCheck=$POSITION | |
sleep $SLEEP | |
done | |
# if we break out of the previous loop something is amiss | |
echo -e "\n`date "+%F %l:%M:%S %p"` $hostName $stream stalled" | tee -a $logFile | |
echo '{ "command": ["get_property", "mpv-version"] }' | socat - /tmp/mpvsocket-ipcam1-mpv.sh &> /dev/null || { echo -e "`date "+%F %l:%M:%S %p"` Restarting Server for $hostName" | tee -a $logFile; rm $socket; start_Server; sleep $SLEEP; } | |
# Server started/still running | |
echo -e "`date "+%F %l:%M:%S %p"` Trying to restart $hostName $stream" | tee -a $logFile | |
# Wait for camera to become reachable | |
while true; do printf '%s\r' "`date "+%F %l:%M:%S %p"` ping $hostName" | tee -a $logFile; ping -c 1 $HOST > /dev/null && break; sleep 2; done | |
echo -e "\n$nullStream" '=>' "$socket" #debug | |
open_Stream $nullStream | |
echo -e "response-NULL $response return-NULL $retUrn" # debug | |
for n in {1..5}; do sleep 1; done | |
streamUrl | |
echo -e "\n$stream" '=>' "$socket" # debug | |
open_Stream $stream | |
echo -e "respone-STREAM $response return-STREAM $retUrn" # debug | |
response=$(echo $response | cut -d '"' -f6) | |
[[ "$response" = "success" ]] && { while [[ $POSITION -lt 1 ]]; do streamPosition; done; } || ps -ef | egrep -wi --color ${socket} | grep -v grep | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1 | |
sleep $SLEEP | |
echo -e "\n`date "+%F %l:%M:%S %p"` Retry complete on $hostName" | tee -a $logFile | |
done | |
# End of 'infinite' loop | |
echo "`date "+%F %l:%M:%S %p"` Something went Horribly wrong on $hostName" | tee -a $logFile | |
ctrl_c | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment