Weiter zum Inhalt
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Hell
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dunkel
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Tester
  4. ...nicht in offiziellem Repo
  5. Test Adapter für Blink Kameras entwickelt mit KI

NEWS

  • Neuer ioBroker-Blog online: Monatsrückblick März/April 2026
    BluefoxB
    Bluefox
    8
    1
    522

  • Verwendung von KI bitte immer deutlich kennzeichnen
    HomoranH
    Homoran
    10
    1
    426

  • Monatsrückblick Januar/Februar 2026 ist online!
    BluefoxB
    Bluefox
    18
    1
    994

Test Adapter für Blink Kameras entwickelt mit KI

Geplant Angeheftet Gesperrt Verschoben ...nicht in offiziellem Repo
49 Beiträge 4 Kommentatoren 411 Aufrufe 6 Beobachtet
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • O oFbEQnpoLKKl6mbY5e13

    @Pischleuder

    Wie witzig, genau damit habe ich mich gerade beschäftig. Ja, haben wir. Diese konnte über den HAM-Adapter nicht gesteuert werden. Leider mit deinem Adapter auch nicht:

    Befehl fehlgeschlagen (blink.0.cameras.******.commands.motion_detect): HTTP 404: {"message":"Camera not found","error":null,"code":500}
    
    PischleuderP Online
    PischleuderP Online
    Pischleuder
    schrieb am zuletzt editiert von
    #9

    @oFbEQnpoLKKl6mbY5e13

    wird denn das dazugehörige sync-modul korrekt eingebunden ?

    O 1 Antwort Letzte Antwort
    0
    • PischleuderP Pischleuder

      @oFbEQnpoLKKl6mbY5e13

      wird denn das dazugehörige sync-modul korrekt eingebunden ?

      O Abwesend
      O Abwesend
      oFbEQnpoLKKl6mbY5e13
      schrieb am zuletzt editiert von oFbEQnpoLKKl6mbY5e13
      #10

      @Pischleuder

      Ja.

      Edit:
      Klingel

      1 Antwort Letzte Antwort
      0
      • PischleuderP Online
        PischleuderP Online
        Pischleuder
        schrieb am zuletzt editiert von
        #11

        ich habe zumindest eine Idee: vermutlich wird der Gerätetyp nicht korrekt ausgelesen. Wenn das richtig gemacht wird, dann wird auch die Doorbell erkannt. Ich nehme das einmal mit auf die To-Do Liste - habe aber keine Doorbell zum Testen , dafür musst Du dann herhalten :-)

        O 1 Antwort Letzte Antwort
        1
        • PischleuderP Pischleuder

          ich habe zumindest eine Idee: vermutlich wird der Gerätetyp nicht korrekt ausgelesen. Wenn das richtig gemacht wird, dann wird auch die Doorbell erkannt. Ich nehme das einmal mit auf die To-Do Liste - habe aber keine Doorbell zum Testen , dafür musst Du dann herhalten :-)

          O Abwesend
          O Abwesend
          oFbEQnpoLKKl6mbY5e13
          schrieb am zuletzt editiert von
          #12

          @Pischleuder

          Mache ich selbstverständlich gerne!

          1 Antwort Letzte Antwort
          0
          • PischleuderP Online
            PischleuderP Online
            Pischleuder
            schrieb am zuletzt editiert von
            #13

            hab dir etwas per chat gesendet

            1 Antwort Letzte Antwort
            0
            • A Offline
              A Offline
              adarof
              schrieb am zuletzt editiert von adarof
              #14

              Hallo
              Nun bleibt der Adapter bei mir Gelb - die Verbindung scheint mir aber da zu sein, wenn ich das Log richtig verstehe. Hat jemand eine Idee ?

              Gruss -

              blink.0
              Zeit
              silly
              Nachricht
              
              blink.0
              2026-04-25 12:41:17.408	silly	sendTo "send" to system.adapter.pushover.0 from system.adapter.blink.0
              
              blink.0
              2026-04-25 12:41:17.318	silly	States user redis pmessage blink.0.cameras.*.commands.*/blink.0.cameras.1097548.commands.fetch_video:{"val":false,"ack":true,"ts":1777113677315,"q":0,"from":"system.adapter.blink.0","user":"system.user.admin","lc":1777057429539}
              
              blink.0
              2026-04-25 12:41:17.270	silly	States user redis pmessage blink.0.cameras.*.commands.*/blink.0.cameras.1097548.commands.motion_detect:{"val":true,"ack":true,"ts":1777113677270,"q":0,"from":"system.adapter.blink.0","user":"system.user.admin","lc":1777057429574}
              
              blink.0
              2026-04-25 12:41:17.232	silly	States user redis pmessage blink.0.cameras.*.commands.*/blink.0.cameras.928274.commands.fetch_video:{"val":false,"ack":true,"ts":1777113677230,"q":0,"from":"system.adapter.blink.0","user":"system.user.admin","lc":1777057429363}
              
              blink.0
              2026-04-25 12:41:17.186	silly	States user redis pmessage blink.0.cameras.*.commands.*/blink.0.cameras.928274.commands.motion_detect:{"val":true,"ack":true,"ts":1777113677186,"q":0,"from":"system.adapter.blink.0","user":"system.user.admin","lc":1777057429400}
              
              blink.0
              2026-04-25 12:41:17.074	silly	States user redis pmessage blink.0.cameras.*.commands.*/blink.0.cameras.897864.commands.fetch_video:{"val":false,"ack":true,"ts":1777113677071,"q":0,"from":"system.adapter.blink.0","user":"system.user.admin","lc":1777057429177}
              
              blink.0
              2026-04-25 12:41:17.028	silly	States user redis pmessage blink.0.cameras.*.commands.*/blink.0.cameras.897864.commands.motion_detect:{"val":true,"ack":true,"ts":1777113677027,"q":0,"from":"system.adapter.blink.0","user":"system.user.admin","lc":1777057429219}
              
              blink.0
              2026-04-25 12:41:16.934	silly	States user redis pmessage blink.0.cameras.*.commands.*/blink.0.cameras.851424.commands.fetch_video:{"val":false,"ack":true,"ts":1777113676931,"q":0,"from":"system.adapter.blink.0","user":"system.user.admin","lc":1777057429008}
              
              blink.0
              2026-04-25 12:41:16.888	silly	States user redis pmessage blink.0.cameras.*.commands.*/blink.0.cameras.851424.commands.motion_detect:{"val":true,"ack":true,"ts":1777113676888,"q":0,"from":"system.adapter.blink.0","user":"system.user.admin","lc":1777057429037}
              
              blink.0
              2026-04-25 12:41:16.797	silly	States user redis pmessage blink.0.cameras.*.commands.*/blink.0.cameras.786011.commands.fetch_video:{"val":false,"ack":true,"ts":1777113676795,"q":0,"from":"system.adapter.blink.0","user":"system.user.admin","lc":1777057428833}
              
              blink.0
              2026-04-25 12:41:16.752	silly	States user redis pmessage blink.0.cameras.*.commands.*/blink.0.cameras.786011.commands.motion_detect:{"val":true,"ack":true,"ts":1777113676751,"q":0,"from":"system.adapter.blink.0","user":"system.user.admin","lc":1777057428867}
              
              blink.0
              2026-04-25 12:41:16.655	silly	States user redis pmessage blink.0.sync.*.commands.*/blink.0.sync.548399.commands.armed:{"val":true,"ack":true,"ts":1777113676654,"q":0,"from":"system.adapter.blink.0","user":"system.user.admin","lc":1777057428695}
              
              blink.0
              2026-04-25 12:41:16.586	silly	States user redis pmessage blink.0.sync.*.commands.*/blink.0.sync.395317.commands.armed:{"val":true,"ack":true,"ts":1777113676585,"q":0,"from":"system.adapter.blink.0","user":"system.user.admin","lc":1777057428656}
              
              blink.0
              2026-04-25 12:41:15.241	silly	States system redis pmessage system.adapter.blink.0.logLevel/system.adapter.blink.0.logLevel:{"val":"silly","ack":true,"ts":1777113675236,"q":0,"from":"system.adapter.blink.0","lc":1777113573231}
              
              blink.0
              2026-04-25 12:41:15.228	info	starting. Version 0.0.2 (non-npm: Pischleuder1/ioBroker.blink#10cdba4ba984acc72eb546e632d851ddfcc9ea6a) in /opt/iobroker/node_modules/iobroker.blink, node: v22.22.2, js-controller: 7.0.7
              
              1 Antwort Letzte Antwort
              0
              • PischleuderP Online
                PischleuderP Online
                Pischleuder
                schrieb am zuletzt editiert von
                #15

                da sehe ich kein Problem - es startet alles ganz normal. Stell das Log doch einmal auf Info, oder starte den Adapter neu.

                sigi234S A 2 Antworten Letzte Antwort
                0
                • PischleuderP Pischleuder

                  da sehe ich kein Problem - es startet alles ganz normal. Stell das Log doch einmal auf Info, oder starte den Adapter neu.

                  sigi234S Online
                  sigi234S Online
                  sigi234
                  Forum Testing Most Active
                  schrieb am zuletzt editiert von sigi234
                  #16

                  @Pischleuder

                  Danke, läuft bei mir. 👍

                  Erkannte Instanzen:    92 (73 aktiv, 19 inaktiv)
                  Plattform:             Windows
                  js-controller:         7.1.1
                  Node.js:               v22.22.2
                  npm:                   10.9.7
                  RAM:                   ~4157 MB (alle Adapter)
                  CPU:                   9.27 %
                  Host:                  SmartHome
                  Repository:            beta
                  

                  Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
                  Immer Daten sichern!

                  1 Antwort Letzte Antwort
                  1
                  • PischleuderP Online
                    PischleuderP Online
                    Pischleuder
                    schrieb am zuletzt editiert von
                    #17

                    Mit @ofbeqnpolkkl6mby5e13 arbeite ich gerade daran, dass die Video Doorbell eingebunden werden kann. Motion detect geht wohl schon, auch die Batterieanzeige - jedoch wird die Temperatur noch nicht korrekt ausgelesen. Sobald wir das hinbekommen erscheint ein neues Release.

                    1 Antwort Letzte Antwort
                    0
                    • PischleuderP Online
                      PischleuderP Online
                      Pischleuder
                      schrieb am zuletzt editiert von
                      #18

                      Wer das Widget für die Videos benötigt, bitte das javascript und das html neu aus dem Startpost laden. Hier habe ich Veränderungen eingearbeitet, da der Chrome-Browser Probleme bereitet hatte und Überlagerungen entfernt wurden.

                      1 Antwort Letzte Antwort
                      0
                      • PischleuderP Pischleuder

                        da sehe ich kein Problem - es startet alles ganz normal. Stell das Log doch einmal auf Info, oder starte den Adapter neu.

                        A Offline
                        A Offline
                        adarof
                        schrieb am zuletzt editiert von
                        #19

                        @Pischleuder sagte:

                        da sehe ich kein Problem - es startet alles ganz normal. Stell das Log doch einmal auf Info, oder starte den Adapter neu.

                        Ich starte neu und es kommt genau die Ausgabe von oben. Es scheint auch keine Funktion zu geben (ausser dass die Kameras gefunden werden -> Also die Verbindung wohl da ist)

                        1 Antwort Letzte Antwort
                        0
                        • PischleuderP Online
                          PischleuderP Online
                          Pischleuder
                          schrieb am zuletzt editiert von Pischleuder
                          #20

                          stoppe den Adapter einmal, lösche dann Deinen Pin und starte ihn erneut. Dann solltest Du einen neuen Pin erhalten. Diesen wieder eingeben und neu starten.
                          Die Kameras sind immer da, insofern er einmal den Adapter sauber gestartet hat. Die states werden dann aber nicht aktualisiert.

                          1 Antwort Letzte Antwort
                          0
                          • A Offline
                            A Offline
                            adarof
                            schrieb am zuletzt editiert von
                            #21

                            Ja okay - nun ist wieder grün. Merkwürdig. Wie lange braucht er denn von Gelb auf Grün normalerweise?

                            und noch eine Frage:
                            blink.0.cameras.<id>.commands.motion_detect ist true. Setzen auf "false" (mit Bestätigung) scheint keinen Effekt zu haben. Der wert geht nach einigen Sekunden auch wieder auf true.
                            Das sollte doch die Bewegungserkennung dieser einen Kamera ausschalten, richtig?

                            Gruss

                            1 Antwort Letzte Antwort
                            0
                            • PischleuderP Online
                              PischleuderP Online
                              Pischleuder
                              schrieb am zuletzt editiert von Pischleuder
                              #22

                              Edit : blink.0.cameras.xxxxx.commands.motion_detect ist korrekt aber ohne Bestätigung.

                              Von gelb auf grün ca. 3 Sekunden.

                              1 Antwort Letzte Antwort
                              0
                              • A Offline
                                A Offline
                                adarof
                                schrieb am zuletzt editiert von
                                #23

                                Ah - okay. Danke - ohne Bestätigung tat es nun!
                                Background: Ich schalte die Kameras aus, wenn ich zu Hause bin und an, wenn die Haustuer verschlossen ist.

                                1 Antwort Letzte Antwort
                                0
                                • PischleuderP Online
                                  PischleuderP Online
                                  Pischleuder
                                  schrieb am zuletzt editiert von
                                  #24

                                  Das kannst Du bspw. auch automtisch mit einem Blockly tun in Verbindung mit geofencing.

                                  1 Antwort Letzte Antwort
                                  0
                                  • A Offline
                                    A Offline
                                    adarof
                                    schrieb am zuletzt editiert von
                                    #25

                                    Die Frau lässt sich nicht geofencen - lässt ihr Handy permanent irgendwo rumliegen.
                                    Aber abschliessen macht sie zuverlässig - das ist damit der beste Indikator :-D

                                    Danke nochmal - sieht nun alles gut aus hier!

                                    1 Antwort Letzte Antwort
                                    1
                                    • PischleuderP Pischleuder
                                      Aktuelle Testversion 0.0.6
                                      Github Link https://github.com/Pischleuder1/ioBroker.blink
                                      Veröffentlichungsdatum 28.04.2026

                                      In den letzten Jahren gab es diverse BLINK Adapter für die Amazon Kameras, die jedoch nicht weiterentwickelt wurden und alle, mehr oder weniger, auf blinkpy basierten. Als Alternative funktionierten temporär python scripte mit blinkpy oder die Option über IFTTT.

                                      Zuletzt sind die meisten sicherlich am HAM Adapter oder Homeassistant hängen geblieben, um die Kameras zu steuern. Da Amazon jedoch wieder einmal an den API herumbastelt, funktioniert das tlw. nur noch suboptimal.
                                      Die Idee mit blinkpy zu arbeiten habe ich auf anraten des Forums verworfen und einen Adapter (unter Zuhilfenahme von KI) erstellt, um die gesamte Login - Logik im Adapter nachzubauen.

                                      Funktionen:
                                      • Kameras und Sync-Modul werden ausgelesen und die entsprechenden States etc. angezeigt
                                      • Temperaturanzeige über die Kamera in Grad Celsius und Fahrenheit
                                      • Batterienanzeige der Kamera, umgerechnet in Volt
                                      • bei geringem Batteriestand wird / kann eine pushover oder telegram Info gesendet werden
                                      • Snapshot von Bildern über commands in einen state bzw. auch lokal in den Ordner /opt/iobroker/iobroker-data/blink
                                      • Snapshot als image_base64 mit Zeitstempel
                                      • automatische Erzeugung von Snapshots nach Zeit über admin Bereich
                                      • motion detect
                                      • aktuell, von Blink gespeicherte Videos werden in die entsprechenden Datenpunkte geschrieben oder per fetch geholt
                                      • Speicherort kann im Admin Bereich festgelegt werden

                                      Was funktioniert (noch) nicht:
                                      • kein Echtzeit Video (in Arbeit)
                                      • Video Doorbell (in Arbeit) sollte mit 0.0.4 unterstützt werden, jedoch keine Temperaturanzeige, da diese offensichtlich bei der Doorbell nicht verbaut ist

                                      VIS-Widget
                                      Zusätzlich habe ich ein VIS-Widget Generator erstellt, bei dem ihr lediglich die Kamera ID´s eingeben müsst und es wird daraus ein json erstellt, welches als widget in Vis importiert werden kann


                                      Widget.png
                                      blink-vis-raster-widget-generator.html

                                      1.) Widgetgenerator für Cameras ohne letzte Videodarstellung:

                                      • blink-vis-raster-widget-generator.html

                                      2.) Widgetgenerator mit Anzeige der zuletzt gespeicherten Videos. Dazu muss ein javascript in den Scripten erstellt werden mit dem Inhalt unter Code, im Code bitte die Kamera ID´s anpassen !:

                                      • blink-vis-raster-widget-generator-video-2.html
                                      // ioBroker JavaScript Adapter Script
                                      // Blink-Videos aus blink.0.cameras.<ID>.video.file lesen,
                                      // per ffmpeg konvertieren und direkt als Data-URL-States bereitstellen.
                                      //
                                      // Ergebnis:
                                      // javascript.0.blinkVideos.<ID>.data_url       = MP4 / H.264 + AAC, gut für Safari
                                      // javascript.0.blinkVideos.<ID>.data_url_webm  = WebM / VP8 + Opus, gut für Chrome/Edge
                                      //
                                      // Voraussetzung auf dem ioBroker-Server:
                                      // sudo apt install ffmpeg
                                      
                                      const fs = require('fs');
                                      const path = require('path');
                                      const { execFile } = require('child_process');
                                      
                                      const BLINK_INSTANCE = 'blink.0';
                                      
                                      // HIER deine Kamera-IDs eintragen/anpassen:
                                      const CAMERA_IDS = [
                                        '548730',
                                        '1136145',
                                        '1136121',
                                        '1723473'
                                      ];
                                      
                                      const OUT_PREFIX = 'blinkVideos';
                                      
                                      const FFMPEG = '/usr/bin/ffmpeg';
                                      const FFPROBE = '/usr/bin/ffprobe';
                                      
                                      const CACHE_DIR = '/opt/iobroker/iobroker-data/blink-vis-cache';
                                      
                                      // Limit pro fertiger Datei, bevor sie als Base64 in einen State geschrieben wird
                                      const MAX_MB_MP4 = 50;
                                      const MAX_MB_WEBM = 50;
                                      
                                      // Warten, damit Blink/ioBroker die Datei sicher fertig geschrieben hat
                                      const READ_DELAY_MS = 5000;
                                      
                                      const timers = {};
                                      const running = {};
                                      const rerun = {};
                                      
                                      function localId(camera, name) {
                                        return `${OUT_PREFIX}.${camera}.${name}`;
                                      }
                                      
                                      function ensureState(id, def, common) {
                                        try {
                                          createState(id, def, Object.assign({
                                            read: true,
                                            write: false
                                          }, common));
                                        } catch (e) {
                                          log(`createState ${id}: ${e.message || e}`, 'warn');
                                        }
                                      }
                                      
                                      function setLocal(camera, name, value) {
                                        try {
                                          setState(localId(camera, name), value, true);
                                        } catch (e) {
                                          log(`setState ${localId(camera, name)}: ${e.message || e}`, 'warn');
                                        }
                                      }
                                      
                                      function ensureCameraStates(camera) {
                                        ensureState(localId(camera, 'data_url'), '', {
                                          name: `Blink ${camera} MP4 Data URL`,
                                          type: 'string',
                                          role: 'text'
                                        });
                                      
                                        ensureState(localId(camera, 'data_url_webm'), '', {
                                          name: `Blink ${camera} WebM Data URL`,
                                          type: 'string',
                                          role: 'text'
                                        });
                                      
                                        ensureState(localId(camera, 'source_file'), '', {
                                          name: `Blink ${camera} Original video.file`,
                                          type: 'string',
                                          role: 'text'
                                        });
                                      
                                        ensureState(localId(camera, 'converted_file'), '', {
                                          name: `Blink ${camera} konvertierte MP4-Datei`,
                                          type: 'string',
                                          role: 'text'
                                        });
                                      
                                        ensureState(localId(camera, 'converted_file_webm'), '', {
                                          name: `Blink ${camera} konvertierte WebM-Datei`,
                                          type: 'string',
                                          role: 'text'
                                        });
                                      
                                        ensureState(localId(camera, 'original_size'), 0, {
                                          name: `Blink ${camera} Originalgröße`,
                                          type: 'number',
                                          role: 'value',
                                          unit: 'Bytes'
                                        });
                                      
                                        ensureState(localId(camera, 'converted_size'), 0, {
                                          name: `Blink ${camera} MP4 Größe`,
                                          type: 'number',
                                          role: 'value',
                                          unit: 'Bytes'
                                        });
                                      
                                        ensureState(localId(camera, 'converted_size_webm'), 0, {
                                          name: `Blink ${camera} WebM Größe`,
                                          type: 'number',
                                          role: 'value',
                                          unit: 'Bytes'
                                        });
                                      
                                        ensureState(localId(camera, 'data_url_length'), 0, {
                                          name: `Blink ${camera} MP4 Data URL Länge`,
                                          type: 'number',
                                          role: 'value'
                                        });
                                      
                                        ensureState(localId(camera, 'data_url_webm_length'), 0, {
                                          name: `Blink ${camera} WebM Data URL Länge`,
                                          type: 'number',
                                          role: 'value'
                                        });
                                      
                                        ensureState(localId(camera, 'updated'), 0, {
                                          name: `Blink ${camera} aktualisiert`,
                                          type: 'number',
                                          role: 'date'
                                        });
                                      
                                        ensureState(localId(camera, 'ffprobe'), '', {
                                          name: `Blink ${camera} ffprobe MP4`,
                                          type: 'string',
                                          role: 'text'
                                        });
                                      
                                        ensureState(localId(camera, 'ffprobe_webm'), '', {
                                          name: `Blink ${camera} ffprobe WebM`,
                                          type: 'string',
                                          role: 'text'
                                        });
                                      
                                        ensureState(localId(camera, 'status'), '', {
                                          name: `Blink ${camera} Status`,
                                          type: 'string',
                                          role: 'text'
                                        });
                                      
                                        ensureState(localId(camera, 'error'), '', {
                                          name: `Blink ${camera} Fehler`,
                                          type: 'string',
                                          role: 'text'
                                        });
                                      }
                                      
                                      function readStateValue(id) {
                                        const s = getState(id);
                                        return s && s.val !== null && s.val !== undefined ? String(s.val).trim() : '';
                                      }
                                      
                                      function finish(camera) {
                                        running[camera] = false;
                                      
                                        if (rerun[camera]) {
                                          rerun[camera] = false;
                                          scheduleConvert(camera, 3000);
                                        }
                                      }
                                      
                                      function fail(camera, message) {
                                        setLocal(camera, 'status', 'Fehler');
                                        setLocal(camera, 'error', message);
                                        log(`Blink ${camera}: ${message}`, 'warn');
                                        finish(camera);
                                      }
                                      
                                      function waitForStableFile(filePath, callback) {
                                        let lastSize = -1;
                                        let stableCount = 0;
                                        let tries = 0;
                                      
                                        const timer = setInterval(() => {
                                          tries++;
                                      
                                          fs.stat(filePath, (err, stat) => {
                                            if (err) {
                                              clearInterval(timer);
                                              callback(err);
                                              return;
                                            }
                                      
                                            if (stat.size > 0 && stat.size === lastSize) {
                                              stableCount++;
                                            } else {
                                              stableCount = 0;
                                              lastSize = stat.size;
                                            }
                                      
                                            if (stableCount >= 2) {
                                              clearInterval(timer);
                                              callback(null, stat);
                                              return;
                                            }
                                      
                                            if (tries >= 25) {
                                              clearInterval(timer);
                                              callback(new Error(`Dateigröße wurde nicht stabil: ${filePath}`));
                                            }
                                          });
                                        }, 1000);
                                      }
                                      
                                      function probeFile(camera, filePath, stateName, callback) {
                                        const args = [
                                          '-v', 'error',
                                          '-show_streams',
                                          '-show_format',
                                          filePath
                                        ];
                                      
                                        execFile(FFPROBE, args, { timeout: 30000 }, (err, stdout, stderr) => {
                                          const output = String(stdout || stderr || (err && err.message) || '').slice(0, 12000);
                                          setLocal(camera, stateName, output);
                                          callback();
                                        });
                                      }
                                      
                                      function removeIfExists(filePath) {
                                        try {
                                          if (fs.existsSync(filePath)) {
                                            fs.unlinkSync(filePath);
                                          }
                                        } catch (e) {
                                          // ignorieren
                                        }
                                      }
                                      
                                      function transcodeToMp4(inputFile, outputFile, callback) {
                                        const tmpFile = `${outputFile}.tmp.mp4`;
                                      
                                        removeIfExists(tmpFile);
                                      
                                        const args = [
                                          '-hide_banner',
                                          '-nostdin',
                                          '-y',
                                      
                                          '-fflags', '+genpts',
                                          '-err_detect', 'ignore_err',
                                      
                                          '-i', inputFile,
                                      
                                          '-map', '0:v:0',
                                          '-map', '0:a:0?',
                                      
                                          '-c:v', 'libx264',
                                          '-preset', 'veryfast',
                                          '-crf', '23',
                                          '-pix_fmt', 'yuv420p',
                                          '-profile:v', 'baseline',
                                          '-level', '3.1',
                                          '-tag:v', 'avc1',
                                          '-vf', 'scale=trunc(iw/2)*2:trunc(ih/2)*2',
                                      
                                          '-c:a', 'aac',
                                          '-b:a', '128k',
                                          '-ac', '2',
                                          '-ar', '44100',
                                      
                                          '-movflags', '+faststart',
                                          '-f', 'mp4',
                                      
                                          tmpFile
                                        ];
                                      
                                        execFile(FFMPEG, args, { timeout: 120000 }, (err, stdout, stderr) => {
                                          if (err) {
                                            callback(new Error(`ffmpeg MP4 Fehler: ${stderr || err.message}`));
                                            return;
                                          }
                                      
                                          try {
                                            removeIfExists(outputFile);
                                            fs.renameSync(tmpFile, outputFile);
                                          } catch (e) {
                                            callback(new Error(`MP4 konnte nicht übernommen werden: ${e.message}`));
                                            return;
                                          }
                                      
                                          callback(null);
                                        });
                                      }
                                      
                                      function transcodeToWebm(inputFile, outputFile, callback) {
                                        const tmpFile = `${outputFile}.tmp.webm`;
                                      
                                        removeIfExists(tmpFile);
                                      
                                        const args = [
                                          '-hide_banner',
                                          '-nostdin',
                                          '-y',
                                      
                                          '-fflags', '+genpts',
                                          '-err_detect', 'ignore_err',
                                      
                                          '-i', inputFile,
                                      
                                          '-map', '0:v:0',
                                          '-map', '0:a:0?',
                                      
                                          // Chrome/Edge-kompatibles WebM
                                          '-c:v', 'libvpx',
                                          '-deadline', 'realtime',
                                          '-cpu-used', '5',
                                          '-b:v', '0',
                                          '-crf', '32',
                                          '-pix_fmt', 'yuv420p',
                                          '-vf', 'scale=trunc(iw/2)*2:trunc(ih/2)*2',
                                      
                                          // Audio behalten und nach Opus wandeln
                                          '-c:a', 'libopus',
                                          '-b:a', '96k',
                                          '-ac', '2',
                                          '-ar', '48000',
                                      
                                          '-f', 'webm',
                                      
                                          tmpFile
                                        ];
                                      
                                        execFile(FFMPEG, args, { timeout: 180000 }, (err, stdout, stderr) => {
                                          if (err) {
                                            callback(new Error(`ffmpeg WebM Fehler: ${stderr || err.message}`));
                                            return;
                                          }
                                      
                                          try {
                                            removeIfExists(outputFile);
                                            fs.renameSync(tmpFile, outputFile);
                                          } catch (e) {
                                            callback(new Error(`WebM konnte nicht übernommen werden: ${e.message}`));
                                            return;
                                          }
                                      
                                          callback(null);
                                        });
                                      }
                                      
                                      function writeDataUrl(camera, filePath, mimeType, dataState, lengthState, sizeState, maxMb, callback) {
                                        fs.stat(filePath, (statErr, stat) => {
                                          if (statErr) {
                                            callback(new Error(`Datei nicht lesbar: ${statErr.message}`));
                                            return;
                                          }
                                      
                                          const maxBytes = maxMb * 1024 * 1024;
                                      
                                          if (stat.size > maxBytes) {
                                            callback(new Error(`Video zu groß für State: ${stat.size} Bytes, Limit ${maxBytes} Bytes`));
                                            return;
                                          }
                                      
                                          fs.readFile(filePath, (readErr, buf) => {
                                            if (readErr) {
                                              callback(new Error(`Video konnte nicht gelesen werden: ${readErr.message}`));
                                              return;
                                            }
                                      
                                            const dataUrl = `data:${mimeType};base64,${buf.toString('base64')}`;
                                      
                                            setLocal(camera, dataState, dataUrl);
                                            setLocal(camera, lengthState, dataUrl.length);
                                            setLocal(camera, sizeState, stat.size);
                                      
                                            callback(null);
                                          });
                                        });
                                      }
                                      
                                      function convertVideo(camera) {
                                        if (running[camera]) {
                                          rerun[camera] = true;
                                          return;
                                        }
                                      
                                        running[camera] = true;
                                      
                                        const sourceState = `${BLINK_INSTANCE}.cameras.${camera}.video.file`;
                                        const sourceFile = readStateValue(sourceState);
                                      
                                        if (!sourceFile) {
                                          fail(camera, `${sourceState} ist leer`);
                                          return;
                                        }
                                      
                                        setLocal(camera, 'source_file', sourceFile);
                                        setLocal(camera, 'data_url', '');
                                        setLocal(camera, 'data_url_webm', '');
                                        setLocal(camera, 'data_url_length', 0);
                                        setLocal(camera, 'data_url_webm_length', 0);
                                        setLocal(camera, 'error', '');
                                        setLocal(camera, 'status', 'Warte auf stabile Videodatei ...');
                                      
                                        setTimeout(() => {
                                          waitForStableFile(sourceFile, (stableErr, originalStat) => {
                                            if (stableErr) {
                                              fail(camera, stableErr.message);
                                              return;
                                            }
                                      
                                            setLocal(camera, 'original_size', originalStat.size);
                                      
                                            try {
                                              if (!fs.existsSync(CACHE_DIR)) {
                                                fs.mkdirSync(CACHE_DIR, { recursive: true });
                                              }
                                            } catch (e) {
                                              fail(camera, `Cache-Verzeichnis konnte nicht erstellt werden: ${e.message}`);
                                              return;
                                            }
                                      
                                            const mp4File = path.join(CACHE_DIR, `${camera}_browser.mp4`);
                                            const webmFile = path.join(CACHE_DIR, `${camera}_browser.webm`);
                                      
                                            setLocal(camera, 'converted_file', mp4File);
                                            setLocal(camera, 'converted_file_webm', webmFile);
                                      
                                            setLocal(camera, 'status', 'Konvertiere MP4 für Safari ...');
                                      
                                            transcodeToMp4(sourceFile, mp4File, (mp4Err) => {
                                              if (mp4Err) {
                                                fail(camera, mp4Err.message);
                                                return;
                                              }
                                      
                                              setLocal(camera, 'status', 'Prüfe MP4 ...');
                                      
                                              probeFile(camera, mp4File, 'ffprobe', () => {
                                                setLocal(camera, 'status', 'Schreibe MP4 Data URL ...');
                                      
                                                writeDataUrl(
                                                  camera,
                                                  mp4File,
                                                  'video/mp4',
                                                  'data_url',
                                                  'data_url_length',
                                                  'converted_size',
                                                  MAX_MB_MP4,
                                                  (mp4WriteErr) => {
                                                    if (mp4WriteErr) {
                                                      fail(camera, mp4WriteErr.message);
                                                      return;
                                                    }
                                      
                                                    setLocal(camera, 'status', 'Konvertiere WebM für Chrome/Edge ...');
                                      
                                                    transcodeToWebm(sourceFile, webmFile, (webmErr) => {
                                                      if (webmErr) {
                                                        fail(camera, webmErr.message);
                                                        return;
                                                      }
                                      
                                                      setLocal(camera, 'status', 'Prüfe WebM ...');
                                      
                                                      probeFile(camera, webmFile, 'ffprobe_webm', () => {
                                                        setLocal(camera, 'status', 'Schreibe WebM Data URL ...');
                                      
                                                        writeDataUrl(
                                                          camera,
                                                          webmFile,
                                                          'video/webm',
                                                          'data_url_webm',
                                                          'data_url_webm_length',
                                                          'converted_size_webm',
                                                          MAX_MB_WEBM,
                                                          (webmWriteErr) => {
                                                            if (webmWriteErr) {
                                                              fail(camera, webmWriteErr.message);
                                                              return;
                                                            }
                                      
                                                            setLocal(camera, 'updated', Date.now());
                                                            setLocal(camera, 'status', 'Fertig');
                                                            setLocal(camera, 'error', '');
                                      
                                                            log(`Blink ${camera}: MP4 + WebM Data-URLs aktualisiert`, 'info');
                                                            finish(camera);
                                                          }
                                                        );
                                                      });
                                                    });
                                                  }
                                                );
                                              });
                                            });
                                          });
                                        }, READ_DELAY_MS);
                                      }
                                      
                                      function scheduleConvert(camera, delayMs) {
                                        if (timers[camera]) {
                                          clearTimeout(timers[camera]);
                                        }
                                      
                                        timers[camera] = setTimeout(() => {
                                          convertVideo(camera);
                                        }, delayMs || 3000);
                                      }
                                      
                                      CAMERA_IDS.forEach((camera) => {
                                        ensureCameraStates(camera);
                                      
                                        on({ id: `${BLINK_INSTANCE}.cameras.${camera}.video.file`, change: 'any' }, () => scheduleConvert(camera, 3000));
                                        on({ id: `${BLINK_INSTANCE}.cameras.${camera}.video.timestamp`, change: 'any' }, () => scheduleConvert(camera, 3000));
                                        on({ id: `${BLINK_INSTANCE}.cameras.${camera}.video.ready`, change: 'any' }, () => scheduleConvert(camera, 3000));
                                      
                                        // Einmal beim Scriptstart ausführen
                                        scheduleConvert(camera, 5000);
                                      });
                                      [/s]
                                      
                                      sigi234S Online
                                      sigi234S Online
                                      sigi234
                                      Forum Testing Most Active
                                      schrieb am zuletzt editiert von
                                      #26

                                      @Pischleuder
                                      Was ist eigentlich der Pin?

                                      Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
                                      Immer Daten sichern!

                                      O 1 Antwort Letzte Antwort
                                      0
                                      • sigi234S sigi234

                                        @Pischleuder
                                        Was ist eigentlich der Pin?

                                        O Abwesend
                                        O Abwesend
                                        oFbEQnpoLKKl6mbY5e13
                                        schrieb am zuletzt editiert von
                                        #27

                                        @sigi234

                                        Wenn man bei Blink die Zweifaktor-Authentifizierung aktiviert hat, erhält man eine Zufallszahl per SMS. Das ist die PIN.

                                        1 Antwort Letzte Antwort
                                        -1
                                        • PischleuderP Online
                                          PischleuderP Online
                                          Pischleuder
                                          schrieb am zuletzt editiert von
                                          #28

                                          Moin, mir ist aufgefallen, dass das Log unter /tmp/blink_debug.log immer größer wurde. Im Git habe ich das so geändert, dass bei jedem Adapter Neustart ein frisches Log angelegt wird. Also bitte noch einmal neu laden.

                                          1 Antwort Letzte Antwort
                                          0

                                          Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.

                                          Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.

                                          Mit deinem Input könnte dieser Beitrag noch besser werden 💗

                                          Registrieren Anmelden
                                          Antworten
                                          • In einem neuen Thema antworten
                                          Anmelden zum Antworten
                                          • Älteste zuerst
                                          • Neuste zuerst
                                          • Meiste Stimmen


                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate

                                          529

                                          Online

                                          32.8k

                                          Benutzer

                                          82.9k

                                          Themen

                                          1.3m

                                          Beiträge
                                          Community
                                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                          ioBroker Community 2014-2025
                                          logo
                                          • Anmelden

                                          • Du hast noch kein Konto? Registrieren

                                          • Anmelden oder registrieren, um zu suchen
                                          • Erster Beitrag
                                            Letzter Beitrag
                                          0
                                          • Home
                                          • Aktuell
                                          • Tags
                                          • Ungelesen 0
                                          • Kategorien
                                          • Unreplied
                                          • Beliebt
                                          • GitHub
                                          • Docu
                                          • Hilfe