##############################################
# $Id: 99_myUtils_camera.pm 00011 2020-12-24 11:30:00Z kst $
#
#************************************************************************
# 2020-12-19 - Datei erstellt
# 2020-12-20 - ffmpeg direkt zu starten, anstatt ueber script
# 2020-12-21 - ffmpeg wird gestartet, und die zugehoerige PID im reading angelegt
# - Funktion mit DOIF erfolgreich getestet
# 2020-12-22 - Funktion nur noch mit DOIF getestet
# - ffmpeg wird mit der entsprechenden PID gestoppt
# - wenn wiederholt geriggert wird, waehrend eine Aufnahme laeuft,
# wird die Aufnahme um den Wert der Dauer verlaengert
# 2020-12-23 - mit einer sub fuer alle Kameras geht nicht
# - fuer jede Kamera eine sub funktioniert
# 2020-12-24 - Funktion das die Aufnahmen nach 2 Tagen geloescht werden
# - Aufruf durch at
# -
# -
# -
# -
# -
#
#------------------------------------------------------------------------
package main;
use strict;
use warnings;
sub
myUtils_camera_Initialize($$)
{
my ($hash) = @_;
}
# Enter you functions below _this_ line.
#************************************************************************
# camera ffmpeg mq_dafang_01
#************************************************************************
sub camera_ffmpeg_dafang_01 {
# Pflicht-Uebernahmeparameter (Name des Geraetes von dem die sub aufgerufen wird), mit Ueberpruefung
my $kst_name_device = shift // return '!!! Error: minimum call {camera_ffmpeg_dafang_01(\"$SELF\", \'address stream\', \'camera name\', \'destination\', \'duration\')} !!!';
# Pflicht-Uebernahmeparameter (Adresse der Kamera unter welcher der stream aufgerufen werden kann), mit Ueberpruefung
# Beispiel: 'rtsp://192.168.78.86:8554/unicast'
# Beispiel: 'rtsp://{USERNAME}:{PASSWORD}\@192.168.78.86:8554/unicast'
my $kst_stream_camera = shift // return '!!! Error: minimum call {camera_ffmpeg_dafang_01(\"$SELF\", \'address stream\', \'camera name\', \'destination\', \'duration\')} !!!';
# Pflicht-Uebernahmeparameter (Name der Kamera (Device NAME) welche triggert), mit Ueberpruefung
# Beispiel: 'mq_dafang_01'
my $kst_name_camera = shift // return '!!! Error: minimum call {camera_ffmpeg_dafang_01(\"$SELF\", \'address stream\', \'camera name\', \'destination\', \'duration\')} !!!';
# Pflicht-Parameter (Zielverzeichnis in welchem die Ordner und Dateien angelegt werden), mit Ueberpruefung
# Beispiel: '/mnt/ipcam/dafang_01/movie'
my $kst_folder_path = shift // return '!!! Error: minimum call {camera_ffmpeg_dafang_01(\"$SELF\", \'address stream\', \'camera name\', \'destination\', \'duration\')} !!!';
# Pflicht-Parameter (Dauer der Aufnahme wenn nur einmal ausgeloest wird), mit Ueberpruefung
# Beispiel: '120' fuer zwei Minuten
my $kst_ffmpeg_duration = shift // return '!!! Error: minimum call {camera_ffmpeg_dafang_01(\"$SELF\", \'address stream\', \'camera name\', \'destination\', \'duration\')} !!!';
# Benoetigte Ordner und Dateinamen
my $kst_folder_sub1 = strftime("%Y-%m", localtime);
my $kst_folder_sub2 = strftime("%d", localtime);
my $kst_file_name = strftime("%Y_%m_%d__%H_%M_%S.mp4", localtime);
my $kst_folder_destination = "$kst_folder_path/$kst_folder_sub1/$kst_folder_sub2";
my $kst_file_destination = "$kst_folder_path/$kst_folder_sub1/$kst_folder_sub2/$kst_file_name";
my $kst_folder_log = "$kst_folder_path/log";
my $kst_file_log = "$kst_name_camera.log";
my $kst_log_destination = "$kst_folder_log/$kst_file_log";
# Meta Daten, die spaeter in der Aufnahme hinterlegt sind (koennen an eigene Beduerfnisse angepasst werden)
# Moechte man die Meta Daten nicht verwenden, muss der Aufruf von ffmpeg angepasst werden.
# Beispiel: Ohne Titel einfach "-metadata title=$kst_meta_title" entfernen
my $kst_meta_title = strftime("%Y_%m_%d__%H_%M_%S", localtime);
my $kst_meta_artist = 'kst';
my $kst_meta_comment = 'Livestream';
my $kst_meta_date = strftime("%Y", localtime);
my $kst_meta_copyright = "'(c) $kst_meta_date by kst'";
if (defined "$kst_name_device:007_ffmpeg_active" && ReadingsNum("$kst_name_device","007_ffmpeg_active",0)==1)
{
goto continue_rec;
}
else
{
fhem("setreading $kst_name_device 007_ffmpeg_active 0");
}
# Readings fuer eine Uebersicht im verwendeten Geraet
# Readings werden nur in einem DOIF geschrieben
fhem("setreading $kst_name_device 001_name_device $kst_name_device");
fhem("setreading $kst_name_device 002_name_camera $kst_name_camera");
fhem("setreading $kst_name_device 003_file_destination $kst_file_destination");
fhem("setreading $kst_name_device 004_log_destination $kst_log_destination");
# setreading 005_ffmpeg_pid weiter unten im code
fhem("setreading $kst_name_device 006_ffmpeg_duration $kst_ffmpeg_duration");
# setreading 007_ffmpeg_active oben und weiter unten im code
if (! -d "$kst_folder_log")
{ system("mkdir -p $kst_folder_log && wait \$!");
Log3 $kst_name_device, 3, "$kst_name_device: $kst_folder_log wurde erstellt";
}
if (! -e "$kst_log_destination")
{ system("touch $kst_log_destination && wait \$!");
Log3 $kst_name_device, 3, "$kst_name_device: $kst_log_destination wurde erstellt";
}
if (! -d "$kst_folder_destination")
{ system("mkdir -p $kst_folder_destination && wait \$!");
Log3 $kst_name_device, 3, "$kst_name_device: $kst_folder_destination wurde erstellt";
}
system("ffmpeg -loglevel quiet -rtsp_transport tcp -y -i $kst_stream_camera -vcodec copy -metadata title=$kst_meta_title -metadata comment=$kst_meta_comment -metadata artist=$kst_meta_artist -metadata copyright=$kst_meta_copyright -metadata date=$kst_meta_date $kst_file_destination&");
fhem("setreading $kst_name_device 007_ffmpeg_active 1");
system("wait \$! && ps -fC ffmpeg | awk '/ffmpeg/ {print \$2}' | tail -n 1 >$kst_log_destination && wait \$!");
continue_rec:
my ($error, @content) = FileRead({FileName => "$kst_log_destination", ForceType => "file"});
return $error if ($error);
my $kst_ffmpeg_pid = $content[0];
fhem ("sleep 0.5; setreading $kst_name_device 005_ffmpeg_pid $kst_ffmpeg_pid");
Log3 $kst_name_device, 3, "$kst_name_device:ffmpeg mit PID: $kst_ffmpeg_pid gestartet";
fhem ("sleep ".($kst_ffmpeg_duration)." ".($kst_name_camera)." quiet; {system('kill -15 \"$kst_ffmpeg_pid\"')}; {Log3 \"$kst_name_device\", 3, \"$kst_name_device:ffmpeg mit PID: $kst_ffmpeg_pid gestoppt\"}; setreading $kst_name_device 007_ffmpeg_active 0");
}
#************************************************************************
# camera ffmpeg mq_yi_home_01
#************************************************************************
sub camera_ffmpeg_yi_home_01 {
# Pflicht-Uebernahmeparameter (Name des Geraetes von dem die sub aufgerufen wird), mit Ueberpruefung
my $kst_name_device = shift // return '!!! Error: minimum call {camera_ffmpeg_yi_home_01(\"$SELF\", \'address stream\', \'camera name\', \'destination\', \'duration\')} !!!';
# Pflicht-Uebernahmeparameter (Adresse der Kamera unter welcher der stream aufgerufen werden kann), mit Ueberpruefung
# Beispiel: 'rtsp://192.168.78.86:8554/unicast'
# Beispiel: 'rtsp://{USERNAME}:{PASSWORD}\@192.168.78.86:8554/unicast'
my $kst_stream_camera = shift // return '!!! Error: minimum call {camera_ffmpeg_yi_home_01(\"$SELF\", \'address stream\', \'camera name\', \'destination\', \'duration\')} !!!';
# Pflicht-Uebernahmeparameter (Name der Kamera (Device NAME) welche triggert), mit Ueberpruefung
# Beispiel: 'mq_dafang_01'
my $kst_name_camera = shift // return '!!! Error: minimum call {camera_ffmpeg_yi_home_01(\"$SELF\", \'address stream\', \'camera name\', \'destination\', \'duration\')} !!!';
# Pflicht-Parameter (Zielverzeichnis in welchem die Ordner und Dateien angelegt werden), mit Ueberpruefung
# Beispiel: '/mnt/ipcam/dafang_01/movie'
my $kst_folder_path = shift // return '!!! Error: minimum call {camera_ffmpeg_yi_home_01(\"$SELF\", \'address stream\', \'camera name\', \'destination\', \'duration\')} !!!';
# Pflicht-Parameter (Dauer der Aufnahme wenn nur einmal ausgeloest wird), mit Ueberpruefung
# Beispiel: '120' fuer zwei Minuten
my $kst_ffmpeg_duration = shift // return '!!! Error: minimum call {camera_ffmpeg_yi_home_01(\"$SELF\", \'address stream\', \'camera name\', \'destination\', \'duration\')} !!!';
# Benoetigte Ordner und Dateinamen
my $kst_folder_sub1 = strftime("%Y-%m", localtime);
my $kst_folder_sub2 = strftime("%d", localtime);
my $kst_file_name = strftime("%Y_%m_%d__%H_%M_%S.mp4", localtime);
my $kst_folder_destination = "$kst_folder_path/$kst_folder_sub1/$kst_folder_sub2";
my $kst_file_destination = "$kst_folder_path/$kst_folder_sub1/$kst_folder_sub2/$kst_file_name";
my $kst_folder_log = "$kst_folder_path/log";
my $kst_file_log = "$kst_name_camera.log";
my $kst_log_destination = "$kst_folder_log/$kst_file_log";
# Meta Daten, die spaeter in der Aufnahme hinterlegt sind (koennen an eigene Beduerfnisse angepasst werden)
# Moechte man die Meta Daten nicht verwenden, muss der Aufruf von ffmpeg angepasst werden.
# Beispiel: Ohne Titel einfach "-metadata title=$kst_meta_title" entfernen
my $kst_meta_title = strftime("%Y_%m_%d__%H_%M_%S", localtime);
my $kst_meta_artist = 'kst';
my $kst_meta_comment = 'Livestream';
my $kst_meta_date = strftime("%Y", localtime);
my $kst_meta_copyright = "'(c) $kst_meta_date by kst'";
if (defined "$kst_name_device:007_ffmpeg_active" && ReadingsNum("$kst_name_device","007_ffmpeg_active",0)==1)
{
goto continue_rec;
}
else
{
fhem("setreading $kst_name_device 007_ffmpeg_active 0");
}
# Readings fuer eine Uebersicht im verwendeten Geraet
# Readings werden nur in einem DOIF geschrieben
fhem("setreading $kst_name_device 001_name_device $kst_name_device");
fhem("setreading $kst_name_device 002_name_camera $kst_name_camera");
fhem("setreading $kst_name_device 003_file_destination $kst_file_destination");
fhem("setreading $kst_name_device 004_log_destination $kst_log_destination");
# setreading 005_ffmpeg_pid weiter unten im code
fhem("setreading $kst_name_device 006_ffmpeg_duration $kst_ffmpeg_duration");
# setreading 007_ffmpeg_active oben und weiter unten im code
if (! -d "$kst_folder_log")
{ system("mkdir -p $kst_folder_log && wait \$!");
Log3 $kst_name_device, 3, "$kst_name_device: $kst_folder_log wurde erstellt";
}
if (! -e "$kst_log_destination")
{ system("touch $kst_log_destination && wait \$!");
Log3 $kst_name_device, 3, "$kst_name_device: $kst_log_destination wurde erstellt";
}
if (! -d "$kst_folder_destination")
{ system("mkdir -p $kst_folder_destination && wait \$!");
Log3 $kst_name_device, 3, "$kst_name_device: $kst_folder_destination wurde erstellt";
}
system("ffmpeg -loglevel quiet -rtsp_transport tcp -y -i $kst_stream_camera -vcodec copy -metadata title=$kst_meta_title -metadata comment=$kst_meta_comment -metadata artist=$kst_meta_artist -metadata copyright=$kst_meta_copyright -metadata date=$kst_meta_date $kst_file_destination&");
fhem("setreading $kst_name_device 007_ffmpeg_active 1");
system("wait \$! && ps -fC ffmpeg | awk '/ffmpeg/ {print \$2}' | tail -n 1 >$kst_log_destination && wait \$!");
continue_rec:
my ($error, @content) = FileRead({FileName => "$kst_log_destination", ForceType => "file"});
return $error if ($error);
my $kst_ffmpeg_pid = $content[0];
fhem ("sleep 0.5; setreading $kst_name_device 005_ffmpeg_pid $kst_ffmpeg_pid");
Log3 $kst_name_device, 3, "$kst_name_device:ffmpeg mit PID: $kst_ffmpeg_pid gestartet";
fhem ("sleep ".($kst_ffmpeg_duration)." ".($kst_name_camera)." quiet; {system('kill -15 \"$kst_ffmpeg_pid\"')}; {Log3 \"$kst_name_device\", 3, \"$kst_name_device:ffmpeg mit PID: $kst_ffmpeg_pid gestoppt\"}; setreading $kst_name_device 007_ffmpeg_active 0");
}
#************************************************************************
# camera ffmpeg files deleted after 2 days
#************************************************************************
sub camera_ffmpeg_file_delete {
system("find /mnt/ipcam/dafang_01/movie /mnt/ipcam/yi_01/movie -daystart -mtime +2 -delete && wait \$!");
system("find /mnt/ipcam/dafang_01/movie /mnt/ipcam/yi_01/movie -empty -delete &");
}
#************************************************************************
# Temporaer
#************************************************************************
#
#FFMPEG loggen muss folgende Zeile vor dem ffmpeg befehl stehen
#FFREPORT=file=\$kst_folder_log/ffreport.log:level=32
#Beispiel: system("FFREPORT=file=\$kst_folder_log/ffreport.log:level=32 ffmpeg -loglevel quiet ...")
#
#
#
1;