Gerade die günstigen Webcams bieten häufig keinen MJPEG Stream an. Da kann man sich glücklich schätzen, wenn man Besitzer eine Synology NAS ist. Als erstes sind die Pakete „Surveillance Station“, „Web Station“ und „PHP 5.6 oder höher“ auf der NAS zu installieren. Anschließend ist die Webcam in der Surveillance Station einzubinden.
Bevor es aber los geht, hier kurz erklärt was MJPEG ist:
Bei Motion JPEG (MJPEG) handelt es sich um ein Videocodec, bei dem jedes Einzelbild des Videostreams separat als JPEG-Bild komprimiert im MJPEG gespeichert wird. Mann kann sich das als aneinander gereihte JPEGs in einer nicht endenden Datei vorstellen.
Sobald man die Webcam in der Surveillance Station konfiguriert hat, ist das PHP Skript auf der Webstation in dem Verzeichnis /volume1/web/ mit dem Namen webcam.php zu kopieren. Alternativ kann das PHP Script auch auf jedem anderen Webserver im Internet bzw. Intranet liegen, vorausgesetzt es besteht eine Internetverbindung zur NAS.
Nur die ersten Zeilen im Skript sind anzupassen, unter $ip ist die IP-Adresse oder der Hostname sowie unter $port der Port der NAS einzutragen. Diese Informationen werden aus Sicherheitsgründen nicht beim Aufruf des Skriptes mitgeben.
Das PHP Skript greift über die Surveillance Station WebAPI v2.0 auf den Webcam Stream der Surveillance Station zu und wandelt diesen in das MJPEG Format um und zeigt dann das MJPEG im Webbrowser. Das Bild erneuert sich alle paar Sekunden.
Das Skript folgendermaßen aufrufen:
http://webserver/webcam.php?usr=<benutzername>&pwd=<passwort>&cam=<1|2|…>&format=<mjpeg|jpeg>
Die Variablen sind wie folgt zu füllen:
Variable |
Wert |
usr |
Benutzername
(am besten einen Benutzer in der Surveillance Station mit wenig Berechtigungen anlegen) |
pwd |
Passwort (Passwort des Benutzers) |
cam |
1,2,3,4 oder … (die ersten konfigurierte Webam ist 1 die zweite 2 usw.) |
format |
jpeg für eine einzelnes Bild oder mjpeg für einen jpeg Stream |
Beispiel:
http://nas-stueben.goip.de/webcam.php?usr=thorsti&pwd=geheim&cam=2&format=mjpeg
Wer möchte kann aber auch den Variablen $user, $pass und $cameraID im Skript direkt Werte zuweisen. Dann ist das Passwort in der URL nicht sichtbar! Download
<?php
// **********************************************************************************
// Diese Beiden Werte sind ggf. anzupassen. Sonst ist nichts zu tun!
// **********************************************************************************
$ip = "localhost"; // IP-Adresse eures Synology-NAS
$port = "5000"; // default Port der Surveillance Station
// **********************************************************************************
// Anmelden an der Surveillance Station und sid zurückgeben
// **********************************************************************************
function getSid($user, $pass, $ip, $port) {
$link_login = 'http://' . $ip . ':' . $port . '/webapi/auth.cgi?api=SYNO.API.Auth&method=Login&version=3&account=' . $user . '&passwd=' . $pass . '&session=SurveillanceStation&format=sid';
// Eventuell müsst ihr die URLs von HTTP auf HTTPS anpassen, sofern ihr HTTPS aktiviert habt!
// Authentifizierung an Synology Surveillance Station WebAPI und auslesen der SID
$json = file_get_contents ( $link_login );
$obj = json_decode ( $json, true );
@$sid = $obj ["data"] ["sid"];
return $sid;
}
// **********************************************************************************
// Link für MJPEG von Surveillance Station lesen
// **********************************************************************************
function getStreamLink($user, $pass, $ip, $port, $cameraID) {
$sid = getSid ( $user, $pass, $ip, $port );
$link_stream = 'http://' . $ip . ':' . $port . '/webapi/SurveillanceStation/videoStreaming.cgi?api=SYNO.SurveillanceStation.VideoStream&version=1&method=Stream&cameraId=' . $cameraID . '&format=mjpeg&_sid=' . $sid;
return $link_stream;
}
// **********************************************************************************
// Link für JPEG von Surveillance Station lesen
// **********************************************************************************
function getImageLink($user, $pass, $ip, $port, $cameraID) {
$sid = getSid ( $user, $pass, $ip, $port );
$link_image = 'http://' . $ip . ':' . $port . '/webapi/entry.cgi?camStm=1&version=8&cameraId=' . $cameraID . '&api="SYNO.SurveillanceStation.Camera"&preview=true&method=GetSnapshot&_sid=' . $sid;
return $link_image;
}
// **********************************************************************************
// MJPEG Stream von Surveillance Station ausgeben
// **********************************************************************************
function printStream($user, $pass, $ip, $port, $cameraID) {
$link_stream = getStreamLink ( $user, $pass, $ip, $port, $cameraID );
set_time_limit ( 60 );
$r = "";
$i = 0;
$boundary = "\n--myboundary";
$new_boundary = "newboundary";
$f = fopen ( $link_stream, "r" );
if (! $f) {
// **** cannot open
print "error";
} else {
// **** URL OK
header ( "Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0" );
header ( "Cache-Control: private" );
header ( "Pragma: no-cache" );
header ( "Expires: -1" );
header ( "Content-type: multipart/x-mixed-replace;boundary={$new_boundary}" );
while ( true ) {
while ( substr_count ( $r, "Content-Length:" ) != 2 ) {
$r .= fread ( $f, 32 );
}
$pattern = "/Content-Length\:\s([0-9]+)\s\n(.+)/i";
preg_match ( $pattern, $r, $matches, PREG_OFFSET_CAPTURE );
$start = $matches [2] [1];
$len = $matches [1] [0];
$end = strpos ( $r, $boundary, $start ) - 1;
$frame = substr ( "$r", $start + 2, $len );
print "--{$new_boundary}\n";
print "Content-type: image/jpeg\n";
print "Content-Length: ${len}\n\n";
print $frame;
usleep ( 40 * 1000 );
$r = substr ( "$r", $start + 2 + $len );
}
}
fclose ( $f );
}
// **********************************************************************************
// JPEG Image von Surveillance Station ausgeben
// **********************************************************************************
function printImage($user, $pass, $ip, $port, $cameraID) {
$link_image = getImageLink ( $user, $pass, $ip, $port, $cameraID );
$image = file_get_contents ( $link_image );
header ( "Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0" );
header ( "Cache-Control: private" );
header ( "Pragma: no-cache" );
header ( "Expires: -1" );
header ( "Content-type: image/jpeg" );
header ( "Content-Length: " . ( string ) (filesize ( $image )) );
print $image;
}
// **********************************************************************************
// Stream als MJPEG ausgeben
// http://nas-stueben.goip.de/webcam.php?usr=<benutzername>&pwd=<passwort>&cam=<1|2|...>&format=<mjpeg|jpeg>
// **********************************************************************************
$user = $_GET ["usr"]; // Synology Benutzer mit Berechtigung die Kamera anzuzeigen
$pass = $_GET ["pwd"]; // Passwort zu eben eingegebenem Benutzer
$cameraID = $_GET ["cam"]; // ID der Kamera, welche angezeigt werden soll
$format = $_GET ["format"]; // format = jpeg für Image oder mjpeg für Stream
if (strtolower ( $format ) == "jpeg") {
printImage ( $user, $pass, $ip, $port, $cameraID );
} else {
printStream ( $user, $pass, $ip, $port, $cameraID );
}
?>
Jetzt kann man noch in dem Webstation Verzeichnis /volume1/web/ ein Unterverzeichnis webcam anlegen (/volume1/web/webcam) und dort die Datei .httaccess anlegen. Da das Passwort für den Webam Benutzer in der Datei hinterlegt ist, sollten die entsprechenden Berechtigungen für die Datei .httaccess gesetzt sein.
bis Apache 2.2:
# ********************************************************
# .htaccess bis Apache 2.2
# ********************************************************
# Nur im lokalem Netz gilt die Regel
order deny,allow
deny from all
allow from 192.168.20.0/24
# Regel jpg -> php bzw. mjpg -> php
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^cam(.*)\.jpg$ /webcam.php?usr=<user>&pwd=<password>&cam=$1&format=jpeg [L,NC]
RewriteRule ^cam(.*)\.mjpg$ /webcam.php?usr=<user>&pwd=<password>&cam=$1&format=mjpeg [L,NC]
ab Apache 2.4:
# ********************************************************
# .htaccess ab Apache 2.4
# ********************************************************
# Nur im lokalem Netz gilt die Regel
Require ip 192.168.20.0/24
# Regel jpg -> php bzw. mjpg -> php
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^cam(.*)\.jpg$ /webcam.php?usr=<user>&pwd=<password>&cam=$1&format=jpeg [L,NC]
RewriteRule ^cam(.*)\.mjpg$ /webcam.php?usr=<user>&pwd=<password>&cam=$1&format=mjpeg [L,NC]
Jetzt könnt Ihr die Webcam wie folgt aufrufen:
# Webcam 1 / Einzelbild
http://webserver/webcam/cam1.jpg
# Webcam 2 / Einzelbild
http://webserver/webcam/cam2.jpg
# Webcam 1 / MJPEG Stream
http://webserver/webcam/cam1.mjpg
# Webcam 2 / MJPEG Stream
http://webserver/webcam/cam2.mjpg