Projekt: Video Organisation und Aufbereitung für das Web von diversen Webcams (Version 2.1) vom 20.04.2015

Wieso "Video Aufbereitung" und "Organisation" ? Was soll das ?

Hintergrund : Man hat eine tolle Netzwerk Kamera oder RTSP Streaming Kamera, die bei "Alarm" oder Bewegungserkennung alles aufzeichnet und Bilder sichert. Entweder auf einem FTP Server oder auf einer internen Speicher oder MicroSD Card (je nach Modell). Bei Sicherung der Bilder auf einer SD Karte ist meist die Gefahr das jemand die Kamera findet und die Speicherkarte entfernt - so hat man keine Aufnahmen. Oder die Aufnahmen werden auf einem FTP Server gesichert, aber da fallen mitunter ganz schöne Datenmengen an - wo soll man das alles Speichern - und wann soll wer was löschen ?

Die Lösung:

Ein Raspberry Pi mit einer großen Speicherkarte wo ein FTP Server drauf läuft. Die Netzwerk Kamera(s) übermittelt die Bilder und Videos per FTP auf die Speicherkarte des Raspberry Pis, der irgendwo im Netzwerk hängt, nicht unbedingt dort wo auch die Kamera ist. Alternativ kann auch der Raspberry selber einen RTSP Stream abgreifen und direkt aufzeichnen. Aber auch hier fallen mitunter ziemliche Datenmengen an, das muss also organisiert werden. Ein Cronjob auf dem Raspberry Pi ruft alle z.b. 10 Minuten ein PHP Script auf, welches die Bilder und Videos in passende Datumsordner weg sortiert. Es rechnet die Bilder für die Webvorschau klein, erstellt ein Vorschaubild des Videos und bereitet so den Weg für eine sehr schnelle sortierte Webvorschau. Weiterhin lässt sich die Archivdauer einstellen, so kann man sagen das nach z.b. 14 Tagen die ältesten Aufnahmen automatisch gelöscht werden - so läuft das ganze ziemlich autark und rund ohne das man sich darum kümmern muss.

Das PHP Script kann auch direkt im Browser aufgerufen werden und zeigt einem "schön" einfach alle Aufnahmen des Tages an, und bietet die möglichkeit das Bilder und Video Archiv zu durchforsten.

Dieses ist Version 2.0 des Scriptes. Da ich mittlerweile eine zweite Webcam bekommen habe, musste das Script erweitert / Neu Programmiert werden. Mittlerweile kann das Script beliebig viele Webcams verwalten und ist einfach ausbaufähig, egal wie die Daten auf den Raspberry Pi kommen.

Wie sieht es in etwa aus ?

Die Startseite ist "Simpel" gehalten, so das die jeder gestalten kann wie er will. Es werden die Kamera Ordner aufgelistet, die beschreibung und die Archivdauer angezeigt. Mit einem Klick auf die Kamera kommt man direkt zur passenden Kamera.

 

 

Am linken Rand sind sämtliche "Tage" aufgelistet in denen noch Aufnahmen Schlummern.

In der Oberen Leiste steht drin welches Archiv man sich gerade anguckt, wieviele Bilder es sind, wieviel Platz sie einnehmen, und wie lange die Archivzeit ist.

Weiterhin kann man hier den noch verbleibenen Speicherplatz des Systems ablesen.

In der unteren großen Box sind die Bilder und Videos in einer kleinen Vorshau sortiert nach Uhrzeit zu sehen und können auch direkt angeklickt werden - die öffnen dann im Original in einem neuem Fenster.

 

Das ist alles. Der Rest läuft im Hintergrund ab und sorgt dafür das der Speicherplatz niemals knapp wird.

Was ist nötig ?

Man braucht den Video Konverter "avconv", den Installiert man mittels:

 

sudo apt-get install avconv

 

und dann noch

 

sudo apt-get install libav-tools

 

Weiterhin sollte man eine recht große SD Karte wählen, oder einen passenden USB Stick einbinden. Ich verwende hier eine 128 GB SD Karte die immer noch Ausfallfrei läuft. An Datenmengen fallen hier ca 1 GB Video/Foto Daten am Tag an (Full HD).

Die Netzwerk Kameras sollte die Bilder und Videos im folgenden Format in dem FTP-Ordner "RaspberryPI-IP"/ftp/Kameras/Kamera_x/INPUT" speichern. Die Filenamen sind an sich ziemlich egal. Unterstützt werden die Formate "mov", "mp4" und "jpg". Alles in kleinschreibung - ich habe mich nicht damit befasst was passiert wenn die Endungen groß geschrieben werden.

Hier das PHP Script was alles erledigt, es liegt direkt in dem "Kamera" Ordner wo die ganze Organisation stattfindet:

Das PHP Script: index.php, durch einen direkten Aufruf ohne Parameter bekommt man die Webanzeige der passenden Webcamera.

Durch Aufruf mittels "index.php?tag=2015-04-07" wird direkt das passende Datum in der Webanzeige aufgerufen.

Mit "index.php?action=organize" sortiert und konvertiert das Script die Bilder on der Webcam in die passenen Ordner und löscht evtl Aufnahmen wenn die Älter sind als in der Datei "Archivierungsdauer.txt" hinterlegt ist.

Wer mag kann den Kameras direkte einfach beschreibene Namen geben, das geht in der Datei "Kameraname.txt".

Nun aber zum eigentlichen PHP Script:

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Video Organizer (C) 2015 A.Teichmann@gmx.net</title>
<?php //Dateien Organisieren ?
$action= $_GET['action'];
if ($action=="organize") {


//Dieses Script wandelt JPG, MP4 und MOV in eine Webvorschau und verschiebt die Dateien entsprechend.

//Wie Lange die Aufnahmen aufheben ? Anzahl der Tage steht in der Datei "Archivierungsdauer.txt"
$Archivierungdauer="Archivierungsdauer.txt";
if (file_exists($Archivierungdauer)) {$buffer = implode('', file($Archivierungdauer));}
$Aufhebedauer=preg_replace("/[^0-9]/","",$buffer)+0;
if ($Aufhebedauer<1) { echo "Fehler: Archivierungsdauer ist SEHR SEHR KLEIN"; exit; }

$input="INPUT"; // Ordner wo die Kamera die Videos/ Fotos hochlädt, nach erfolgreichen übertragen werden die Bilder verschoben.
$ordner="OUTPUT"; // Ordner wo die bereits fertig übertragenden Fotos/ Videos der Kamera abgelegt werden
$tmpordner="WEB"; // Ordner für die Webvorschau Bilder
$original="ORIGINAL"; // Ordner wo die Originaldateien nach dem einsortieren Archiviert werden.

date_default_timezone_set('Europe/Berlin');setlocale(LC_TIME, "de_DE");ini_set('max_execution_time', 500);

//Aufhebedauer Quercheck...
if ($Aufhebedauer>=1) {$Aufhebedauer=$Aufhebedauer-1;} if ($Aufhebedauer<0) {$Aufhebedauer=0;}

//Aktuelles Datum
$datum_heute=date("Y-m-d"); $datum_aktsec=strtotime(date($datum_heute));

//Datum Entsprechend der Aufhebedauer zuvor berechnen
list($jahr,$monat,$tag)=explode('-',$datum_heute);
$timestamp = mktime(0,0,0,$monat,$tag-$Aufhebedauer,$jahr);
$datum_Loeschen=date('Y-m-d',$timestamp); $datum_presec=strtotime(date($datum_Loeschen));

//Dateien aus dem Kamera Ordner einlesen

$alledateien = scandir($ordner); //Ordner "files" auslesen
foreach ($alledateien as $datei) {

if (is_dir($datei)==false) { //Wenn kein ordner dann einlesen

//Datum des jeweiligen Files feststellen
$filedatum=date("Y-m-d", filemtime($ordner."/".$datei));

//Ordner im Original Archiv erzeugen wenn er nicht existiert
if (!file_exists($original."/".$filedatum)) { shell_exec("mkdir ".$original."/".$filedatum); } //Ordner erstellen
if (!file_exists($tmpordner."/".$filedatum)) { shell_exec("mkdir ".$tmpordner."/".$filedatum); } //Ordner erstellen

//File in Ordner bewegen
if (file_exists($original."/".$filedatum)) { //Existiert der Ordner ?
if (is_dir($original."/".$datei)==false) { //Ist die Datei ein Ordner ? dann nicht verschieben
shell_exec("mv ".$ordner."/".$datei." ".$original."/".$filedatum."/".$datei);

//Bilder kleinrechnen JPG
$isteinbild=0;
if($datei!=str_replace(".jpg","",$datei)) { $isteinbild=1; }
if($datei!=str_replace(".Jpg","",$datei)) { $isteinbild=1; }
if($datei!=str_replace(".JPG","",$datei)) { $isteinbild=1; }
if($datei!=str_replace(".jepg","",$datei)) { $isteinbild=1; }
if($isteinbild==1) {

$bild=$original."/".$filedatum."/".$datei;
$bildklein=$tmpordner."/".$filedatum."/".$datei;
$fileuhrzeit=date("H:i:s", filemtime($bild))." Uhr";
if (!file_exists($tmpordner."/".$filedatum)) { $dirname=dirname(__FILE__); shell_exec("mkdir ".$dirname."/".$tmpordner."/".$filedatum); }
if (!file_exists($bildklein)) { $size = getimagesize($bild); $src_img = imagecreatefromjpeg($bild);$dst_img = imagecreatetruecolor(100,75);
imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, 100, 75, $size[0], $size[1]);imagejpeg($dst_img, $bildklein);imagedestroy($src_img);imagedestroy($dst_img);
}
} //Bilder kleinrechnen JPG


//Video Vorschau erzeugen
$isteinvideo=0;
if($datei!=str_replace(".mp4","",$datei)) { $isteinvideo=1; }
if($datei!=str_replace(".MP4","",$datei)) { $isteinvideo=1; }
if($datei!=str_replace(".mov","",$datei)) { $isteinvideo=1; }
if($datei!=str_replace(".MOV","",$datei)) { $isteinvideo=1; }
if($isteinvideo==1) {

$bild=$original."/".$filedatum."/".$datei;
$bildklein=$tmpordner."/".$filedatum."/".$datei.".jpg";
$bildtemp=$tmpordner."/".$filedatum."/temp.jpg";
$fileuhrzeit=date("H:i:s", filemtime($bild))." Uhr";
if (!file_exists($tmpordner."/".$filedatum)) { shell_exec("mkdir ".$tmpordner."/".$filedatum); }
if (!file_exists($bildklein)) { $dirname=dirname(__FILE__); shell_exec("avconv -i ".$dirname."/".$bild." -frames 1 ".$dirname."/".$bildtemp);
$size = getimagesize($bildtemp); $src_img = imagecreatefromjpeg($bildtemp);$dst_img = imagecreatetruecolor(100,75);
imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, 100, 75, $size[0], $size[1]);imagejpeg($dst_img, $bildklein);imagedestroy($src_img);imagedestroy($dst_img);
unlink($bildtemp); }
} // MP4 Vorschau erzeugen

} }

} // ist ordner schleife
} //for each




$alledateien = scandir($original); //Ordner "files" auslesen
foreach ($alledateien as $datei) {

if ($datei!=="." && $datei!==".." ) {
echo "<br>";$datei;

//Datum des jeweiligen Files feststellen
$filedatum=$datei;
//Datum in Sekunden umrechnen
$filedatum_sec=strtotime(date($filedatum));
//Vergleichen ob es zu den zu löschenden Dateien gehört


if ($filedatum_sec<$datum_presec) {


$delete=delTree($original."/".$filedatum);
$delete=delTree($tmpordner."/".$filedatum);

}
}
}
exit;

}

//AB HIER Normaler Webaufruf **************************************************************************

//Variablen
$ordner="WEB";
$original="ORIGINAL";

//Archivierungsdauer einlesen
$Archivierungdauer="Archivierungsdauer.txt";
if (file_exists($Archivierungdauer)) {$buffer = implode('', file($Archivierungdauer));}
$Aufhebedauer=preg_replace("/[^0-9]/","",$buffer)+0;
if ($Aufhebedauer<1) { echo "Fehler: Archivierungsdauer ist SEHR SEHR KLEIN"; exit; }

//Tag aus Url extrahieren
$datum=date("Y-m-d"); $Tag= $_GET['Tag']; if($Tag==false) {$Tag=$datum;}

//Kamera Name abrufen
if (file_exists('Kameraname.txt')) { $Kameraname = implode('', file("Kameraname.txt"));} else { $Kameraname = "Umbenannte Kamera";}

//Freien Speicherplazz ermitteln
$bytes = disk_free_space("/.");
$si_prefix = array( 'B', 'KB', 'MB', 'GB', 'TB', 'EB', 'ZB', 'YB' ); $base = 1024;
$class = min((int)log($bytes , $base) , count($si_prefix) - 1); $frei= sprintf('%1.2f' , $bytes / pow($base,$class)) . ' ' . $si_prefix[$class];

//Speicherplatz des Ordners berechnen
$dir = $original."/".$Tag."/";
$size = get_size($dir,0);
$measure = "Byte";
if ($size >= 1024)
{
$measure = "KB";
$size = $size / 1024;
}
if ($size >= 1024)
{
$measure = "MB";
$size = $size / 1024;
}
if ($size >= 1024)
{
$measure = "GB";
$size = $size / 1024;
}
$size = sprintf("%01.2f", $size);

?>
<style type="text/css">
body {
background-color: #333;
background-image: url();
}
.Stil6 {
font-size: 12px;
font-family: Tahoma, Geneva, sans-serif;
}
.gruen {
color: #066;
font-weight: bold;
font-size: 12px;
font-family: Tahoma, Geneva, sans-serif;
}
.rot {color: #906;
}
.rot {
color: #900;
}
body,td,th {
font-family: Tahoma, Geneva, sans-serif;
}
a:link {
color: #000;
text-decoration: none;
}
a:visited {
text-decoration: none;
color: #000;
}
a:hover {
text-decoration: none;
color: #fff;
}
a:active {
text-decoration: none;
}
.zehn {
font-size: 12px;
}
.vierzehn {
font-size: 14px;
}
.block {
font-family: "Courier New", Courier, monospace;
}
.rot1 {color: #906;
}
.rot1 { color: #903;
}
.courier { font-family: "Courier New", Courier, monospace;
font-size: 12px;
}
.gruen1 {
color: #066;
font-weight: normal;
}
.gruen2 {
color: #066;
font-weight: normal;
}
.rot2 {color: #906;
}
.rot2 { color: #903;
font-weight: bold;
}
.gruen3 { color: #066;
}
.Stil15 {font-size: 24px;
font-weight: bold;
}
.Stil16 {color: #333333;
}
.Stil61 {font-size: 12px}
.eht10 { font-size: 10px;
}
</style>
</head>

<body>
<table width="900" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td width="40" background="RaspBilder/Ecke_Oben_Links.png"><img src="index_Bilder/Ecke_Oben_Links.png" width="40" height="40" border="0" /></td>
<td width="145" align="center" bgcolor="#FFFFFF"><a href="../../../">ZURÜCK</a></td>
<td width="675" align="center" bgcolor="#FFFFFF"><?php echo $Kameraname; ?></td>
<td width="40" background="RaspBilder/Ecke_Oben_Rechts.png"><img src="index_Bilder/Ecke_Oben_Rechts.png" width="40" height="40" border="0" /></td>
</tr>
<tr>
<td bgcolor="#FFFFFF">&nbsp;</td>
<td colspan="2" bgcolor="#FFFFFF"><table width="820" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="143" rowspan="3" valign="top"><table width="95%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="20" height="20"><img src="index_Bilder/t_KleineEcke_Oben_Links.png" width="20" height="20" border="0" /></td>
<td align="center" valign="middle" bgcolor="#9ec3c0" class="zehn"><strong>Tagesauswahl</strong></td>
<td width="20"><img src="index_Bilder/t_KleineEcke_Oben_Rechts.png" width="20" height="20" border="0" /></td>
</tr>
<tr>
<td width="20" bgcolor="#9ec3c0">&nbsp;</td>
<td align="center" valign="top" bgcolor="#9ec3c0" class="zehn">
<?php


//Anzahl gespeicherte Tage abrufen
$seite= basename(__FILE__); //Scriptname
$alleordner = scan_dir($ordner."/"); $zahl=0;
foreach ($alleordner as $Einzelordner) {
if (is_dir($ordner."/".$Einzelordner)==true) {$zahl=$zahl+1; }
echo '<br><a href="'.$seite.'?Tag='.$Einzelordner.'">'.$Einzelordner.'</a>';
}

$alleordner = scan_dir($dir); $zahl=0;
foreach ($alleordner as $Einzelordner) {
$zahl=$zahl+1; }
$anzahldateien=$zahl;
?>


</td>
<td width="20" bgcolor="#9ec3c0">&nbsp;</td>
</tr>
<tr>
<td width="20" height="20"><img src="index_Bilder/t_KleineEcke_Unten_Links.png" width="20" height="20" border="0" /></td>
<td bgcolor="#9ec3c0"></td>
<td width="20"><img src="index_Bilder/t_KleineEcke_Unten_Rechts.png" width="20" height="20" border="0" /></td>
</tr>
</table></td>
</tr>
</table></td>
<td width="626" valign="top"><table width="667" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="20" height="20"><img src="index_Bilder/t_KleineEcke_Oben_Links.png" width="20" height="20" border="0" /></td>
<td colspan="3" bgcolor="#9ec3c0">&nbsp;</td>
<td width="20"><img src="index_Bilder/t_KleineEcke_Oben_Rechts.png" width="20" height="20" border="0" /></td>
</tr>
<tr>
<td width="20" bgcolor="#9ec3c0">&nbsp;</td>
<td width="180" align="left" valign="middle" bgcolor="#9ec3c0" class="zehn"><strong>Anzeige Datum:</strong> <?php echo $Tag; ?></td>
<td width="280" align="center" bgcolor="#9ec3c0" class="zehn"><?php echo $size." ".$measure; ?> / <?php echo $anzahldateien; ?> Dateien / von <?php echo $Aufhebedauer; ?> Tage(n)</td>
<td width="167" align="right" valign="middle" bgcolor="#9ec3c0" class="zehn"><strong>Freier Speicher: </strong><?php echo $frei ?></td>
<td width="20" bgcolor="#9ec3c0">&nbsp;</td>
</tr>
<tr>
<td width="20" height="20"><img src="index_Bilder/t_KleineEcke_Unten_Links.png" width="20" height="20" border="0" /></td>
<td colspan="3" bgcolor="#9ec3c0"></td>
<td width="20"><img src="index_Bilder/t_KleineEcke_Unten_Rechts.png" width="20" height="20" border="0" /></td>
</tr>
</table></td>
</tr>
<tr>
<td valign="top">&nbsp;</td>
</tr>
<tr>
<td valign="top"><table width="667" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="20" height="20"><img src="index_Bilder/t_KleineEcke_Oben_Links.png" width="20" height="20" border="0" /></td>
<td bgcolor="#9ec3c0">&nbsp;</td>
<td width="20"><img src="index_Bilder/t_KleineEcke_Oben_Rechts.png" width="20" height="20" border="0" /></td>
</tr>
<tr>
<td width="20" bgcolor="#9ec3c0">&nbsp;</td>
<td valign="top" bgcolor="#9ec3c0">




<?php
if ($anzahldateien!==0) {

//Inhalt des aktuellen Tagesordners abrufen
$inhalt = scan_dir($ordner."/".$Tag); $zahl=-1;$intern==0;
//if ($zahl==0) {echo "<tr>";} #Anfang einer Tabelle, Zeile einleiten
foreach ($inhalt as $file) {




//.jpg am Filenamen entfernen
$dateinameoriginal=$file;
$dateinameoriginal=str_replace(".mov.jpg",".mov",$dateinameoriginal);
$dateinameoriginal=str_replace(".mp4.jpg",".mp4",$dateinameoriginal);
$dateinameoriginal=str_replace(".MOV.jpg",".MOV",$dateinameoriginal);
$dateinameoriginal=str_replace(".MP4.jpg",".MP4",$dateinameoriginal);





//Erstellungs Uhrzeit des Files
$filedatum=date("H:i", filemtime($original."/".$Tag."/".$dateinameoriginal))." Uhr";
//Link für den Direktaufruf erzeugen
$filelink='<a href="'.$original.'/'.$Tag.'/'.$dateinameoriginal.'" target="_blank">'.$filedatum.'</a>';
//Art der Datei ermitteln
$fileart="Unbekannt";
$art=strtolower (substr($dateinameoriginal,-3,3));if ($art=="jpg") {$fileart="Bild";} if ($art=="mov") {$fileart="Video";} if ($art=="mp4") {$fileart="Video";}
//VorschauBild ermitteln 100 x 75 pixel + Rand
$filebild='<img src="'.$ordner.'/'.$Tag.'/'.$file.'" width="100" height="75" border="1" />';
$bildlink='<a href="'.$original.'/'.$Tag.'/'.$dateinameoriginal.'" target="_blank">'.$filebild.'</a>';

$leerbild='<img src="index_Bilder/1x1_50.png" width="100" height="73" border="1" />';
$leerbild2='<img src="index_Bilder/1x1_50.png" width="102" height="75" border="0" />';
if ($fileart=="Video") {$leerbild='<img src="index_Bilder/bg_video.png" width="100" height="73" border="1" />';}
if ($fileart=="Bild") {$leerbild='<img src="index_Bilder/bg_foto.png" width="100" height="73" border="1" />';}


$leerbildlink='<a href="'.$original.'/'.$Tag.'/'.$dateinameoriginal.'" target="_blank">'.$leerbild.'</a>';
//TabellenLink

$tab= '<table width="125" border="0" cellspacing="0" cellpadding="0"><tr><td align="center" valign="top"><table width="100" border="0" cellspacing="0" cellpadding="0"><tr><td background="'.$ordner.'/'.$Tag.'/'.$file.'">'.$leerbildlink.'</td></tr></table></td></tr><tr><td align="center" valign="top" class="zehn">'.$filelink.'</td></tr></table>';
$leertab='<table width="125" border="0" cellspacing="0" cellpadding="0"><tr><td align="center" valign="top"><table width="100" border="0" cellspacing="0" cellpadding="0"><tr><td > </td></tr></table></td></tr><tr><td align="center" valign="top" class="zehn"></td></tr></table>';

//Große Uhrzeit pro Zeile anzeigen
$filedatumOK="";if ($intern==0) {$filedatumOK=$filedatum;} if($intern>=3) {$intern=0;}
if ($zahl==-1) {$intern=$intern+1; if ($filedatumOK!=="") { echo '
<table width="625" border="0" cellspacing="5" cellpadding="5"><tr><td width="90" align="center" valign="top" bgcolor="#FFFFFF" class="stil15"><strong>'.$filedatumOK.'</strong></td>
<td align="left" valign="top">&nbsp;</td></tr></table>';}}
if ($zahl==-1) { $zahl=0;}



if ($zahl==0) { echo '<table width="625" border="0" cellspacing="0" cellpadding="0"><tr>'; }

if ($zahl==0) {echo '<td width="125">'.$tab.'</td>';}
if ($zahl==1) {echo '<td width="125">'.$tab.'</td>';}
if ($zahl==2) {echo '<td width="125">'.$tab.'</td>';}
if ($zahl==3) {echo '<td width="125">'.$tab.'</td>';}
if ($zahl==4) {echo '<td width="125">'.$tab.'</td>';}

$zahl=$zahl+1;
if ($zahl==5) { echo '</tr></table>'; $zahl=-1;}
}
if ($zahl==1) {echo '<td width="125">'.$leertab.'</td><td width="125">'.$leertab.'</td><td width="125">'.$leertab.'</td><td width="125">'.$leertab.'</td></tr></table>';}
if ($zahl==2) {echo '<td width="125">'.$leertab.'</td><td width="125">'.$leertab.'</td><td width="125">'.$leertab.'</td></tr></table>';}
if ($zahl==3) {echo '<td width="125">'.$leertab.'</td><td width="125">'.$leertab.'</td></tr></table>';}
if ($zahl==4) {echo '<td width="125">'.$leertab.'</td></tr></table>';}
if ($zahl==5) {echo '</tr></table>';}

} else { echo "Keine Dateien im Ordner";} 
?>



</td>
<td width="20" bgcolor="#9ec3c0">&nbsp;</td>
</tr>
<tr>
<td width="20" height="20"><img src="index_Bilder/t_KleineEcke_Unten_Links.png" width="20" height="20" border="0" /></td>
<td bgcolor="#9ec3c0"></td>
<td width="20"><img src="index_Bilder/t_KleineEcke_Unten_Rechts.png" width="20" height="20" border="0" /></td>
</tr>
</table></td>
</tr>
</table></td>
<td bgcolor="#FFFFFF">&nbsp;</td>
</tr>
<tr>
<td background="RaspBilder/Ecke_Unten_Links.png"><img src="index_Bilder/Ecke_Unten_Links.png" width="40" height="40" border="0" /></td>
<td width="145" align="center" bgcolor="#FFFFFF"><a href="../../../">ZURÜCK</a></td>
<td align="center" bgcolor="#FFFFFF"><?php echo $Kameraname; ?></td>
<td width="40" background="RaspBilder/Ecke_Unten_Rechts.png"><img src="index_Bilder/Ecke_Unten_Rechts.png" width="40" height="40" border="0" /></td>
</tr>
</table>
<p>&nbsp;</p>
</body>
</html>

<?php
function scan_dir($dir) {
$ignored = array('.', '..', '.svn', '.htaccess');

$files = array();
foreach (scandir($dir) as $file) {
if (in_array($file, $ignored)) continue;
$files[$file] = filemtime($dir . '/' . $file);
}

arsort($files);
$files = array_keys($files);

return ($files) ? $files : false;
}

 

function get_size($path,$size)
{
if(!is_dir($path))
{
$size+=filesize($path);
}
else
{
$dir = opendir($path);
while($file = readdir($dir))
{
if(is_file($path."/".$file))
$size+=filesize($path."/".$file);
if(is_dir($path."/".$file) && $file!="." && $file!="..")
$size=get_size($path."/".$file,$size);
}
}
return($size);
}

 

function delTree($dir) {
$files = array_diff(scandir($dir), array('.','..'));
foreach ($files as $file) {
(is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
}
return rmdir($dir);
}
?>

 

 

Die folgende Bash Datei "/var/www/Reboot.sh" sorgt dafür das das System rebootet und die Trashes geleert werden.

 

#!/bin/bash

rm -rf ~/.local/share/Trash/files/*

sudo reboot

 

Alles in allem war das schon...

Wenn man diese Dateien alle hat und es auch genug Rohmaterial (Fotos und Videos) gibt, kann man sich nun an die Einrichtung des Cronjobs machen, um das ganze zu automatisieren.

Im Terminal rufen die die Cronjobs auf:

 

sudo crontab -e

 

In diesen Cronjob legen wir jetzt 3 Zeilen folgendermaßen fest:

 
#Aufnahmen für Kamera 1 Reorganisieren, z.b. alle 8 Minuten das PHP Script aufrufen.
*/8 * * * * /usr/bin/curl 192.168.0.58/ftp/Kameras/Kamera_1/index.php?action=organize >/dev/null 2>&1
 
#Einmal pro Woche rebooten...
5 0 * * 6 /bin/bash /var/www/Reboot.sh >/dev/null 2>&1
 
#Aufnahmen für Kamera 2 Reorganisieren, z.b. alle 7 Minuten das PHP Script aufrufen.
*/10 * * * * /usr/bin/curl 192.168.0.58/ftp/Kameras/Kamera_2/index.php?action=organize >/dev/null 2>&1
 

Das liesst sich alles komplizierter als es ist. Hier gibt es die kompletten Dateien im Download, einfach nur entpacken, komplett in das Verzeichnis /var/www/ verschieben, evtl anpassen und den Crontab einrichten.

Es kann auch nicht schaden, wenn alles fertig angepasst ist, einen

 

sudo chmod 0777 -R /var/www/

 

zu machen um auch passende Schreibrechte für die Scripte zu haben.

Sicherheit:

Für die Sicherheit ist jeder selbst verantwortlich (.htaccess), Bash Dateien gehören z.b. nicht in den www Ordner 8-), etc..., aber das kann jeder selbst entscheiden. Bei mir ist der Raspberry nicht vom Internet aus erreichbar, lediglich über ein VPN kann man auf die Daten zugreifen.

Wer Interesse an der Version 1.0 hat, das ganze gibt es hier immer noch im "Archiv".

 

NACHTRAG:

Kamera 2 ist bei mir eine Ants Xiaoyi Smart Camera 720p Webcam mit Wlan - die gibt es ab und zu zum Preis von 13-27 Euro bei Bangood und Co (inkl Versand nach Deutschland!). Die Verarbeitung ist super, die Bildqualität auch, nur die Einrichtung ist eine Katastrophe da die Anleitung und die App auf Chinesisch sind..

Einrichtung geht nur über eine Android oder IOS App (mit ein wenig googeln findet man auch eine englische App), nachdem man die App installiert hat, muss man einen "Mi" Account anlegen, den Account bestätigen (email) , dann die Kamera mit dem heimischen Wlan verbinden.

Dann auf KEINEN FALL die Firmware Updaten. Bis zur Firmware "1.8.5.1B_2015" konnte man noch problemlos den RTSP Stream per Webbrowser abgreifen und aufzeichnen (Alternativ kann man auch Downgraden!). Ansonsten hat man nur per APP zugriff auf die Kamera - für mich ein NO GO!. Leider kann die Kamera keine Bilder/ Videos direkt auf einen FTP Server hochladen.

Der nächste Schritt war für mich die IP der Kamera in der Fritzbox ausfindig zu machen, z.b. 192.168.0.125, und in der Fritzbox eine Internet Sperre für das Gerät zu verhängen, so das die Kamera lediglich im heimischen LAN "senden" kann. Eine Speicherkarte habe ich der Kamera nicht spendiert, da ich ja direkt auf den Stream zugreife und alles mitschneide. Ausserdem schalte ich die Kamera mit der Terrarien Beleuchtung Ein und Aus - so das bei Tageslicht die heimischen Viecher "beobachtet" werden können - da ist es nicht gut wenn gerade Schreibzugriffe auf die Speicherkarte stattfinden würden.

Damit der Raspberry Pi den RTSP Stream mitschneiden kann wird ffmpeg benötigt, was wir zuerst auf dem Raspberry Pi installieren:

 

sudo apt-get install ffmpeg

 

Wenn ihr im Browser oder bei VLC diese Adresse eingebt: "rtsp://IP Adresse eurer Kamera/ch0_0.h264" dann solltet ihr einen Life Stream bekommen.

Dann habe ich ein Bash Script in den Kamera_2 Ordner gelegt "Kamera2_Aufzeichnung.sh":

 

#!/bin/bash

datum=$(date +"%Y-%m-%d_%H-%M")

/usr/bin/ffmpeg -i "rtsp://192.168.0.125/ch0_0.h264" -metadata title="Kamera" -vcodec copy -an -t 600 -bufsize 2048k -y "/var/www/ftp/Kameras/Kamera_2/INPUT/Film_$datum.mp4"

mv /var/www/ftp/Kameras/Kamera_2/INPUT/Film_$datum.mp4 /var/www/ftp/Kameras/Kamera_2/OUTPUT/Film_$datum.mp4

 

Das Script nimmt immer 10 Minuten "Happen" (hinter dem "-t" die 600 bedeuten 600 Sekunden!) in dem INPUT Ordner auf und verschiebt diese anschließend in den OUTPUT Ordner. So kann ich die Webcam aufzeichen ohne die Sch**ss App nutzen zu müssen. Den Rest, das konvertieren, verschieben und organisieren erledigt dann das obige PHP Script.

Einzelbilder vom RTSP Stream abgreifen ?

Ja, auch das ist möglich. Man möchte ja nicht nur Megabyte große Videos auf dem Server speichern, sondern auch mal ab und zu ein Jpg Einzelbild haben, welches man mal schnell abrufen und angucken kann. Auch das ist möglich, natürlich auch mit FFMPEG:

 

ffmpeg -i rtsp://192.168.0.125:554/ch0_0.h264 -f image2 -vframes 1 /var/www/ftp/Kameras/Kamera_2/OUTPUT/Schildkroeten_$(date +"%Y-%m-%d_%H-%M").jpg

 

Dieser Einzeiler speichert bei Aufruf ein Einzelbild in dem OUTPUT Ordner von Kamera_2 zur weiteren verarbeitung durch das php Script oben. Das ganze kann man jetzt automatisieren, auch durch einen Cronjob, aber dafür legen wir wieder eine Bash Datei an /var/www/ftp/Kameras/Kamera_2/Kamera2_Einzelbild.sh:

 

#!/bin/bash

datum=$(date +"%Y-%m-%d_%H-%M")

/usr/bin/ffmpeg -i "rtsp://192.168.0.125:554/ch0_0.h264" -f image2 -vframes 1 "/var/www/ftp/Kameras/Kamera_2/OUTPUT/Schildkroeten_$datum.jpg"

 

Jetzt starten wir den Cronjob:

 

sudo crontab -e

 

Hier legen wir fest WANN ein Einzelbild gepeichert werden sol. Angenommen, die Kamera ist 24 Stunden an, und man möchte jede Minute ein Bild haben, dann sind das schon 1440 Bilder pro Tag - mächtig viel. Evtl reicht ja alle 5 Minuten ? das sind dann immer noch 288 Bilder...

Aber das bleibt jedem selbst überlassen.

In den Crontab schreibt man jetzt eben folgendes rein:

 
#Alle 4 Minuten ein Einzelbild vom RTSP Stream speichern.
*/4 * * * * /bin/bash /var/www/ftp/Kameras/Kamera_2/Kamera2_Einzelbild.sh >/dev/null 2>&1
 

Viel Spaß mit euren Webcams...