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
Denis Fillweber
Hallo Thorsten!
danke für das schöne howto!
leider funktioniert das bei mir nicht! wenn ich php script auf dem webserver abgelegt habe, und diesen dann über deine Url ( http://192.168.10.100/webcam.php?usr=filliboy&pwd=meingeheimespassword&cam=<2&format= ) aufrufe bekommen ich immer nur das script selber im webbrowser angezeigt. Aber leider kein bild oder stream der camera.
hast du evtl eine Idee woran das liegen mag
Webstation und PHP sind installiert und laufen.
gruß Denis
Denis Fillweber
Hatte eben das format nicht mit kopiert! Das hatte ich natürlich auch mit angegeben!
( http://192.168.10.100/webcam.php?usr=filliboy&pwd=meingeheimespassword&cam=<2&format=mjpeg )
Stübi
Erstelle mal ein PHP Script mit Namen phpinfo.php und folgendem Inhalt:
Wird das Script richtig ausgeführt?
Denis Fillweber
Danke für die schnelle Antwort!
Folgendes bekomme ich ausgegeben wenn ich die phpinfo aufrufe:
{\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf820 {\fonttbl\f0\fnil\fcharset0 Monaco;} {\colortbl;\red255\green255\blue255;\red184\green14\blue61;\red247\green238\blue241;} {\*\expandedcolortbl;;\cssrgb\c78039\c14510\c30588;\cssrgb\c97647\c94902\c95686;} \paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0 \deftab720 \pard\pardeftab720\partightenfactor0 \f0\fs21\fsmilli10800 \cf2 \cb3 \expnd0\expndtw0\kerning0 }
ist das richtig ausgeführt?
Denis Fillweber
Hallo, nochmal ich!
Habe das script jetzt noch mal in einem anderen scripteditor bearbeitet und gespeichert, jetzt läuft es zum teil.
mit der mjpeg URL bekomme ich ein bild bei der jpeg URL leider nicht. Genau diese bräuchte ich aber um die camera in meine hausautomation mit einzubinden.
wenn ich die jpeg URL im firefox öffne bekomme ich die fehlermeldung die grafik kann nicht angezeigt werden da sie fehler enthält.
muss ich da im script noch was ändern?
thorsten
ich schaue morgen einmal
Filli
Super! Danke dir!
thorsten
Hi Filli,
funktioniert es jetzt mit dem JPEG Stream? Ich kann keinen Fehler im PHP Skript entdecken. Echt merkwürdig.
Gruß
Thorsten
filliboy
nein leider noch nicht, aber ich werde mich heute auch noch mal ran setzen, denn bei Olli funktioniert es ja auch.
also muss der Fehler irgendwo bei mir liegen!
Olli
Hi Thorsten,
ich habs soweit laufen nur bekomme ich die .htaccess datei nicht zum laufen, bzw. die ReWrite Conditions.
Das Format der Datei stimmt wohl, aber es kommt immer ein 404.
Noch ne idee?
thorsten
Hi Olli,
hast Du Apache als Webserver im Einsatz? Damit läuft es bei mir.
VG
thorsten
Oli, ich habe eben festgestellt, dass die .httaccess unter Apache 2.4 etwas anders aussieht. Ich habe die Beschreibung entsprechend angepaßt!
Denis Fillweber
Hi Olli,
Funktioniert bei die auch die Jpeg Ausgabe? oder auch nur die Mjpeg streams? Bei mir ist es so das ich nur die Mjpeg streams abfragen kann, bei den jpeg abfragen bekomme ich leider kein Bild. Hast du das Problem auch und hast es evtl. schon gelöst?
Gruß Denis
Denis Fillweber
Noch eine Frage ist es evtl. auch möglich sich den mjpeg stream scaliert ausgeben zu lassen? Dann könnte ich auch diesen super in meine Hausautomation mit einbauen! Das hätte auch den vorteil das da Bild nicht so stocken würde wie wenn ich als sekündlich als jpeg abfragen würde!
Ich habe auch schon getestet ob ich so in meiner hausautomation ein bild bekomme wenn ich den stream als websiteelement mit einbinde.
Das funktioniert einwandfrei nur leider ist der Stream viel zu groß für meine automationsoberfläche. Deshalb auch die frage ob man den mjpeg stream auch scaliert ausgeben lassen kann?
Olli
Ich check das später nochmal. Kam am WE nicht dazu. Aber ich meine auch das nur die mjpeg ausgabe funktioniert hat. Nur leider bekomme ich das nicht mit der htaccess Datei hin.
Olli
Hi, also bei mir läuft auch die jpeg variante.
Olli
So, hab Apache 2.2 installiert damit läuft alles. Danke !
Alex01
Hallo zusammen,
irgendwie will es bei mir nicht…
Habe auf meiner DS frisch die Webstation und php 5.6 installiert. Benutze die Standart-Einstellungen.
Wenn ich die phpinfo schreibe und aufrufe bekomme ich folgende Ausgabe: „“
Wenn ich das Kamerascript ausführe, bekomme ich nur die Eieruhr und die CPU-Last der DS geht gewaltig hoch.
Was habe ich übersehen?
Danke für Eure Hilfe!!
Alex01
Jetzt kam noch eine Fehlermeldung:
Fatal error: Maximum execution time of 60 seconds exceeded in /volume1/web/webcam.php on line 68
Boris
Hallo,
vielen Dank für die tolle Anleitung. Funktioniert bei mir einwandfrei! 🙂
Viele Grüße
Filli
Hi Olli!
Danke für die Info! Dann muss der Fehler doch irgendwo bei mir liegen! Ich werde mal weiter recherchieren! Verstehe einfach nicht warum das eine funktioniert und jpeg nicht!
Alex01
Ich verzweifle…
Ich habe eine neue DS216j gekauft, alles neu aufgesetzt und dennoch bekomme ich das Script nicht an’s laufen.
Ich habe den Verdacht, das was mit meiner Webcam.php nicht stimmt… könnte jemand von Euch eine Funktionierende Datei hochladen?
Vielleicht hilft das…
Danke!
thorsten
Hi Alex,
hier das webcam.php Script zum downloaden.
http://www.stueben.de/wp-content/uploads/2017/03/webcam.zip
Gruß
Stübi
Alex01
Vielen Dank!
Leider keine Änderung am Zustand… also bin ich nicht nur zu blöd für copy&paste.
Ich bekomme immer einen Error 500…
Alex01
Was auch immer passiert ist… jetzt beim fünften Versuch geht es!
Großartig, vielen Dank!
thorsten
perfekt! super!
Björn
Ich kann mich nach ein paar tagen nicht mehr auf der Synology anmelden. Es kommt als Meldung der Speicher wäre voll und ich soll die Diskstation Neustarten.
thorsten
Und was passiert wenn du die NAS neu startest?
Björn
Das Nas braucht sehr lange zum Neustarten. Danach geht wieder alles bis es nach ein paar Tagen wieder zu der Meldung kommt.
Steffen
Hallo erstmal und vielen Dank für diesen Blog.
Das Originalskript läuft wunderbar (nach Anfangsschwierigkeiten 🙂
Ich habe versucht das ausgegebene Bild zu skalieren, da das FritzFon (nur eine Auflösung von 240X320 Bildpunkten hat und mit dem FullHD Bild nicht klar kommt, Nachdazu soll eben aus gewisser Bildbereich ausgegeben werden. Hierzu habe ich folgenden Teil in das Skript kopiert:
// Bild laden
$thumb = imagecreatetruecolor(240,320);
// Skalieren
imagecopyresized($thumb, $image, 0, 0, 500, 250, 240, 320, 240, 320);
// Ausgabe
imagejpeg($thumb);
print $thumb;
Aber das hatte ich mir wohl zu leicht vorgestellt, denn dies funktionert leider nicht mehr. Für einen Tipp bin ich sehr dankbar.
Gruß Steffen
Sigi
Hi,
ich habe ein Problem, vielleicht können Sie mir helfen…
Habe eine DS 213+ und PHP 7.0 und Apache 2.4.
ich bekomme das PHP Skript nicht ans Laufen…
Kommt die Fehlermeldung ( 500 ) Bei der Verarbeitung dieser Anforderung ist ein Fehler aufgetreten.
Vermutlich liegt es nur an einer winzigen Fehleinstellung. Was könnte ich noch prüfen ?
Grüße
Sigi
Sigi
OK jetzt klappt es, habe noch ein wenig mit den Einstellungen auf der SYNO gespielt.. Keine Ahnung wo der Fehler lag, Hauptsache es klappt jetzt…., VIELEN DANK für den tollen Beitrag 🙂
Philipp
Was war denn die Lösung/ Was hast du denn geändert.
Ich habe nämlich das gleiche Problem…
Daniel
Bei mir funktioniert mit Apache 2.2 und php 5.6 die Verlinkung nicht http://webserver/webcam/cam1.jpg
Was muss ich noch in der php einstellen?
Daniel
Ich erhalte 404 Fehler.
Thomas C
Hallo,
falls noch jemand Probleme mit dem Zugriff via .htaccess hat: die Datei muss tatsächlich .htaccess heißen, nicht .httaccess – sieht nach einem Tippfehler von thorsten aus ;-). Und die Zeile mit „Require ip“ muss ggf. auf das eigene Subnetz angepasst werden.
So klappt’s bei mir, zumindest wenn ich meinen Standarduser mit quasi allen Rechten eintrage.
Allerdings würde ich natürlich viel lieber einen Benutzer nehmen, der möglichst wenig darf. Genau da ist mein Problem: was muss er denn dürfen? Zugriff auf /web und darunter kann ich mir vorstellen, das reicht aber offensichtlich nicht (schon der Aufruf via webcam.php klappt nicht, gibt mit .jpeg eine quasi leere Seite, mit .mjpeg nach einiger Zeit Fehler 504) …
Gruß
Thomas
Danny Roes
Hello Thorsten,
I can read German very good, but writing is something else. That’s why I reply in English, sorry.
Does this php script stll works with the latest DSM an Surveillance station 8.1.4-4598?
As I’m testing the script and don’t seem to get past the authentication. When I print the sid I get an empty value.
Brgrds,
Danny
thorsten
It still works with DSM version 6.1.6-15266 Update 1 and Surveillance Station Version 8.1.4-5498.
Danny Roes
Thorsten,
Got it working. Apparently there’s a difference between port 9900, which I use for surveillancestation and port 9000 which I used in the script. Time to get new glasses I think.
Also, my cameras have a different numbers than 1, 2 and so on. After using the webapi to get the camera numbers my problems were solved. Works like a charm.
Thank a lot
Danny
Wouter Stegenga
Hallo Thorsten,
Thanks for your solution, but I have the following fatal error in the php script running on my synology.
PHP Fatal error: Maximum execution time of 60 seconds exceeded in /volume1/web/webcam.php on line 72
Fatal error: Maximum execution time of 60 seconds exceeded in /volume1/web/webcam.php on line 72
Can you help me?
Benni
Vielen Dank für die Anleitung, bei meiner ersten Cam bekomme ich den Stream angezeigt, bei der 2 ob mjpeg oder jpg, lädt er den stream nicht, es kommt der Fehler ,, Die Grafik kann nicht angezeigt werden, weil sie Fehler enthält“
Maarten
Hi,
Looks like Synology has removed the stream function in the latest version of Surveillance Station (8.2.3-5828). I confirm I cannot get it working in the latest version.
More info here: https://www.reddit.com/r/synology/comments/alrl24/livestream_api_removed_from_surveillance_station/
🙁
Nick
Yes, it was removed. But they’ve provided an inofficial fixed version.
See James comment here: https://community.synology.com/forum/3/post/123094?page=4
Stübi
Thanks for the link. The inofficial version works great with the script again.
David
Hallo, vielen Dank für deinen tollen Text und die Erklärung.
Funktioniert das noch so vom Aufbau her, wenn ich die letzten Kommentare lese? Ich bekomme es leider nicht eingebunden. Bin auch neu auf dem Gebiet, daher habe ich eigentlich keine Erfahrungen dazu.
Stübi
Hast du den Fix von Nick eingespielt? Damit funktioniert das php Skript weiterhin.
Andi
Hi leider funktioniert das Script bei mir auch nicht…. :-/
evtl kann jmd mit dieser Fehlermeldung was anfangen.
Warning: filesize(): stat failed for {„error“:{„code“:401},“success“:false} in /volume1/web/webcam.php on line 103
Call Stack:
0.0003 352472 1. {main}() /volume1/web/webcam.php:0
0.0004 352472 2. printImage() /volume1/web/webcam.php:118
6.5842 355128 3. filesize() /volume1/web/webcam.php:103
{„error“:{„code“:401},“success“:false}
Vanessa
Guten Abend miteinander,
bei mir passiert etwas dass ich hier noch nicht in den Kommentaren lesen konnte = die Seite lädt sich quasi zu Tode = keine Fehlermeldung oder sonstwas.
Installiert ist die aktuellste Surveillance Station 8.2.5-5820.
Hat mir hier jemand einen Rat? 🙂
LG
Henne
Hallo leider bekomme ich das Script auch nicht zum laufen.
Der Fix von Nick lässt sich nicht mehr laden, Schein von der verlinkten Seite gelöscht. Hat die Datei noch jemand?
Oder gibt es schon etwas neues für aktuellste Synology Versionen von SS?
Gruß Henne
joe
Hallo,
ich habe über ioBroker ein Bild von meiner Haustürklingel realisieren können, da die Kamera kein mjpeg kann, läuft es alles über mein Synology Nas Server, wenn ich allerdings die URL in meine Fritzbox eintrage, habe ich leider kein Bild auf meinem Fritzfon, was mache ich da falsch, bzw. ist es überhaupt möglich auf diesem Wege eine nicht mjpeg fähige Kamera am Fritzfon anzuzeigen?
Markus
Ich denke das Script würde funktionieren, allerdings kann ich es nicht testen, da der Patch von Synology nicht mehr verfügbar ist, hat den zufällig jemand?
Hendrik
Hallo Thorsten,
kannst du bei deinem Script aushelfen?
Ich glaube ab Version 8.2 der Surveillance Station hat sich an der API etwas verändert.
Ich bin bei meinen Recherchen hier rüber gestolpert, weiß aber nicht genau ob und wie das helfen kann.
https://community.synology.com/enu/forum/3/post/123094
Wäre toll, wenn du eine überarbeitete Version bringen kannst.
Kamerabilder via Telegram - uniXa-Blog
[…] Stelle kommt meine Synology Surveillance Station ins Spiel.Nach einiger Recherche bin ich auf ein PHP-Script aufmerksam geworden welches die WebAPI anzapft und ein jpeg Datei […]
Martin
Hallo, vielen Dank für die „Datei“. Nach dem Update auf DSM 7 (ja ich habe es erst jetzt gemacht) funktioniert es nicht mehr. Liegt es daran, dass jetzt PHP 5.6 nicht installiert ist sondern PHP 7.4.30?
Welche Anpassungen müssen gemacht werden?
Danke und Gruß
Martin