Webcam Stream --> Bild erstellen und wie Proxy nutzen?

Hallo,

ich verwende mit IPS 5.5 mehrere ESP32cams um z.B. den 3D Drucker zu Überwachen un habe dazu ein neues Stream Objekt angelegt, das Funktioniert so weit auch gut.

Nur möchte ich nun bei Ereignissen auch Bilder des Streams per Telegram versenden und dazu aber nicht direkt auf die Kamera zugreifen sondern ein Bild aus dem laufenden Stream den IPS schon bekommt verwenden. Entweder finde ich das über die Suche so nicht oder…

Zweitens hat der Drucker ein Web Interface und dort kann ich eine MJPG url als Quelle angeben und im Moment habe ich einfach von dem Bild im Webfront die Quelle kopiert und verwende so IPS als „Proxy“, das klapt grundsätzlich nur weiß ich nicht ob das so gedacht ist und ob sich die URL nicht vielleicht doch ändert.

Ach ja ich nutze die RepRap Firmware auf SKR boards und mit DuetWebControll, hätte dazu ein script welchen den Status des Druckers in IPS „Dokumentiert“.

Vielen Dank für eure Rückmeldungen im voraus!

IPS hat sich inzwischen schon zweimal „verabschiedet“, der letzte Log Eintrag lautete:

12.04.2021 01:10:23 | 00000 | ERROR   | DataServer           | Fehler beim Hinzufügen der Verbindung für Stream (http://192.168.1.185/)

Wobei das eine der ESP32cams ist.

Auch werden die ESP32cams mit den Geräten ein und Ausgeschalten.

Wie kann ich diesen Fehler beheben?

Du kannst leider keine Bilder aus Streams mit IP-Symcon extrahieren.

Die URL aus dem WebFront bleibt eigentlich gleich - zumindest solange wir nichts an der API ändern.

Abstürze müsstest du leider damit prüfen: Debugging für Experten (Raspberry Pi, Linux, SymBox)

paresy

Kann ich irgendwie mit der id des streams zu einer url kommen über der ich ein Bild des streams ablegen kann?

Die URL in das script zu schreiben ist nicht so „schön“…

Gibt es irgendwo eine Doku was mit den Streams per script so alles gemacht werden kann?

Hab den Symcon Dienst jetzt mit gdb in einer screen session laufen, damit sollte ich auf jeden Fall mehr Informationen bei einem erneuten Absturz haben.

Nach dem neuerlichen Absturz hatte ich folgendes in der gdb screen session:

[Thread 0x7fffe7fff700 (LWP 11073) exited]
[Thread 0x7fffecbff700 (LWP 11072) exited]
[Thread 0x7fffed7ff700 (LWP 11071) exited]
[Thread 0x7fffee376700 (LWP 11070) exited]
[Thread 0x7fffeeb77700 (LWP 11069) exited]
[Thread 0x7ffff7bffc80 (LWP 11065) exited]
--Type <RET> for more, q to quit, c to continue without paging--c

Program terminated with signal SIGABRT, Aborted.
The program no longer exists.

Leider habe ich erst jetzt gesehen das ich auch das logging einschalten hätte müssen:

set logging on
thread apply all bt
set logging off

nur wie weiß ich nicht da in dem Moment als ich den dienst aus (gdb) mit run starte sämtliche log Meldungen auf dessen Konsole angezeigt werden und ich so keine weiteren Befehle ausführen kann.

Und die letzte Zeile im log ist wieder:

2021-04-12 20:17:09 | 00000 | ERROR   | DataServer           | Fehler beim Hinzufügen der Verbindung für Stream (http://192.168.199.181/)

Das war Zeitlich kurz nachdem ich die Kamera von der Stromversorgung genommen habe.

Also denke ich das hier ein Problem mit dem webcam Stream ist wenn die Kamera nicht mehr da ist.

Wie kann ich per Script den Kamera Stream aktivieren / deaktivieren? Von Unifi würde ich zeitnah sehen wenn die Kamera weg ist und könnte diese deaktivieren.

Deshalb nochmal die Frage nach einer Dokumentation für die Kamera streams.

Danke!

Grundsätzlich sollte das mit PHP gehen wenn man den das boundary wissen würde das ihr beim recoding in IPS nutzt.

Du kannst die Streams leider nicht deaktivieren. Übrigens möchtest du bei GDB die drei Zeilen eintippen sobald der Fehler passiert. Du müsstest dann einen (gdb) Prompt sehen bei dem du etwas eintippen kannst.

paresy

Hallo und danke für die Antwort.

Danke für den hinweiß mit gdb aber inzwischen habe ich den Dienst wieder neu gestartet.

Ist es in IPS geplant die Stream besser steuerbar und das System auch stabiler zu machen oder seit ihr dabei andere Wege hinsichtlich der Webcam Integration zu gehen?

Wir sind aktuell am prüfen, wie wir weiter vorgehen - die aktuelle Implementation ist sehr kompatibel d.h. sie läuft überall und wir haben sehr gute Latenzen. Was nicht gut ist, ist die Kompression (MJPEG ist nicht so cool) und die Browser (insbesondere Chrome) können auf einer Seite maximal 6 Cam’s gleichzeitig anzeigen. Das ist nicht so cool, aber aktuell eine Limitation der Browser. Alternativen sind WebRTC (Könnte sogar Ton/Gegensprechen) oder FFMPEG als WebAssembly, was aber wiederum andere Probleme mit sich bringt. :frowning:

paresy

Halo @paresy,

WebRTC ist sehr Interessant, wenn ihr dann auch noch einen aktuellen Codec VP9 verwendet.

Grundsätzlich spricht gerade im LAN wenig gegen MJEPG, jeder kann es und es wird auch in Zukunft noch lange zwecks Kompatibilität nötig sein (siehe Internet Explorer!)

Deshalb wäre es super wen IPS die aktuelle MJPEG Technik etwas besser unterstützen würde, es also möglich wäre einen Stream zu deaktivieren und auch ein Standbild aus dem Stream zu extrahieren sowie die Auflösung zurück zu rechnen oder die Bild rate, gerade damit wäre ein Integration in die App über den schwächeren WAN uplink sehr sinnvoll.

Andere Programme wie z.B. xeoma machen das mit einfachen get parametern also:

„url?resolution=640x480&fps=1“

Kannst du uns das boundary für die MJPEG Implementierung die ihr in IPS verwendet nennen?

Falls es jemand auch braucht, das boundary für die Streams ist:

--symconboundary

Damit kann mit dem hier verlinkten php code ein Bild aus einem MJPEG stream von Symcon extrahiert werden.

Der Aufruf der Funktion unten mit der URL von IPS gibt die ID des Bildes zurück.

grabImageFromMJPG(„http://192.168.0.100:3777/wfc/(webfront id)/proxy/(id des streams)“, „/var/lib/symcon/media/temp.jpg“, IPS_GetParent($_IPS[‚SELF‘]), $boundary="–symconboundary");

function grabImageFromMJPG($camurl, $filename, $parent, $boundary="--symconboundary"){
    // $boundary = The boundary string between jpegs in an mjpeg stream
    // NOTE: $boundary changes between mjpeg stream providers. For example, https://github.com/Motion-Project/motion uses '--BoundaryString'. https://github.com/ZoneMinder/ZoneMinder uses '--ZoneMinderFrame'. 
    // To find out $boundary for your stream you will need to save 1 or more frames of the mjpeg and open it with a text editor. --<boundary string> should be visible on the first line

    $f = fopen($camurl, "r");                                       // Open mjpeg url as $f in readonly mode
    $r = "";                                                        // Set $r to blank variable

    if($f) {
        while (substr_count($r,"Content-Length") < 2){               // While the number of times "Content-Length" appears in $r is less than 2
            $r.=fread($f, 16384);                                   // Append 16384 bytes of $f to $r
        }
        // print "r:>".$r."<";
        $start = strpos("$r", $boundary);                           // $start is set to the position of the first occurrence of '$boundary' in $r
        $end = strpos("$r", $boundary, $start + strlen($boundary)); // $end is essentially set to the position of the second occurrence of '$boundary' in $r. I use $start + strlen($boundary) to offset the start position and skip the first occurrence
        $boundaryAndFrame = substr("$r", $start, $end - $start);    // $boundaryAndframe is set to the string in $r starting at position $start and with a length of ($end - $start)

        $pattern="/(Content-Length:\s*\d*\r\n\r\n)([\s\S]*)/";      // Use regex to search for '(Content-Length:       90777\r\n\r\n)(<jpeg image data>)
        preg_match_all($pattern, $boundaryAndFrame, $matches);      // Search for regex matches in $boundaryAndFrame
        $frame = $matches[2][0];                                    // $frame is set to the second regex character group (in this case, <jpeg image data>)
        //header("Content-type: image/jpeg");                       // Set header for jpeg image
        //echo $frame;                                              // Echo the jpeg image data
        file_put_contents($filename, $frame);
        
        $MediaID = @IPS_GetObjectIDByIdent("temp_grab_image", $parent);
	
        if ($MediaID === false){
            $MediaID = IPS_CreateMedia(1);                  		// Image im MedienPool anlegen
            IPS_SetIdent($MediaID, "temp_grab_image");
            IPS_SetParent($MediaID, $parent); 	// Medienobjekt einsortieren unter dem Objekt mit der ID $did
            IPS_SetName($MediaID, "temp_grab_image");                          // Medienobjekt benennen
        }
        IPS_SetMediaFile($MediaID, $filename, true);  	 	        // Image im MedienPool mit Image-Datei verbinden
        return $MediaID;
    } else {
        echo "Error, cannot open URL";                              // Error message if $camurl cannot be opened
        return 0;
    }

    fclose($f);                                                     // Close the url
}

Nun ist mir aufgefallen das wenn die Webcam kurz vom Netzwerk weg ist der Stream nicht wieder zeitnah (5 Minuten) kommt wenn die Kamera wieder da ist.

Das einzige was man dann machen kann ist die Adresse des Streams auf eine andere zu ändern und dann wieder zurück um den Stream wieder zu „starten“ ohne eine neue ID der Instanz zu erhalten.

Also die Instanz zu deaktivieren und aktivieren fehlt hier leider komplett.

Medien Objekte sind keine Instanz.
Die Funktion ist auch anders; nur wenn ein Frontend den Stream anfordert, fängt Symcon an diese zu laden und auszuliefern.
Wenn kein Frontend verbunden ist, läuft kein Stream.
Michael

Seit dem ich die Streams der ESP32cams als RTSP eingebunden habe ist IPS nicht mehr abgestürzt auch wenn die Kameras für einen Tag aus sind.

Hallo Michael,

danke für die Erklärung, Sinn macht es zwar keinen es so zu handhaben denn wenn ich mir die drei Meldungen pro Kamera anschaue die wenn sie nicht Online sind jede Sekunde auflaufen und die daraus resultierenden Ressourcen die dafür verschwendet werden nur weil…

Scheinbar sind wir wieder in der Situation wie damals als wir die Kunden auf die Integration von MQTT gepocht haben und von euch dem IPS Team nur belächelt wurden und mit Kommentaren wie „wer braucht den sowas“ bedacht wurden.

Ich dachte es ist alles was IPS besser / stabiler macht willkommen oder sehe ich das falsch?

Bin auch nur User (und Mod im Forum :slight_smile: ).
Somit ist deine Kritik bei mir an der falschen Stelle.
Zumal es sachlich nichts mit deinem Problem zu tun hat.
Michael

@PaulG4H Du kannst die Stream Objekte einfach „unsichtbar“ schalten. Dann werden diese in der Visu nicht geladen. :slight_smile:
paresy

Also mal ehrlich Michael, du bist mehr als nur ein User und Mod hier :wink:

So viel und lange wie du IPS schon Unterstützt zähle ich dich auf jeden Fall zum IPS Team!

@paresy Unsichtbar schalten bringt nur nichts wenn die DWC (DuetWebControl) webseite der RepRapFirmware die Bilder noch über den IPS Proxy Anfordert.

Mir wäre es grundsätzlich lieber eine andere Software als Webcam Proxy laufen zu lassen da es so bei einem Fehler hier gleich zu einem Totalausfall von Symcon kommt.

Habe mit ffmpeg versucht aber der ffserver ist ja nicht mehr teil davon und viele Informationen dazu sind nicht mehr nutzbar. Hat jemand eine andere kleine Open Source Lösung neben, Xeoma, ZoneMinder und Shinobi die nur das Transcodieren von rtsp auf mjpeg übernimmt und diesen Stream „verteilt“?

Also so sieht es aus nach nicht einmal 24 Stunden aus wenn mann die IPS Streams extern abgreift und die Kameras nicht immer Online sind:
image