Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Русский
    3. ioBroker
    4. Визуализация
    5. ioBroker.vis Драйвер
    6. Просмотр видеокамер,DVR

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    Просмотр видеокамер,DVR

    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Haus last edited by

      @andrey99986:

      Настроил просмотр видеокамер через интернет с web-сайта iobroker, используя временные ссылки (нужно поднять nginx для rtmp потока). Хоть какой-то минимальный уровень безопасности (нет пароля в открытом виде и время действия ссылки ограничено).

      Если кому интересно - выложу подробно решение. `
      Я думаю любые готовые решения с описанием будут многим интересны, выкладывайте не стесняйтесь 🙂

      1 Reply Last reply Reply Quote 0
      • A
        andrey99986 last edited by

        Исходные данные:

        Есть IP камера, выдающая RTSP поток, типа:

        "rtsp://user:password@192.168.2.20:554/Streaming/Channels/1?tcp"

        Задача:

        получить видео-поток с этой камеры на веб-странице ioBroker не разглашая пароль в сетевом трафике.

        Решение:

        Так как поток rtsp не понимает ни один браузер конвертируем его в более дружелюбный rtmp. Для этого понадобится скомпилировать nginx с поддержкой rtmp (https://github.com/arut/nginx-rtmp-module). Также в nginx понадобится поддержка secure_link.

        Поэтому собираем nginx так:

        ./configure --add-module=/path/to/nginx-rtmp-module --with-http_secure_link_module 
        make
        make install
        

        В конфиге nginx меняем номер порта (опция listen) в http секции на любой свободный, например 65080 и создаём секцию "location /on_play" в секции "server":

        location /on_play {
        
                    # set connection secure link
                    secure_link $arg_st,$arg_e;
                    secure_link_md5 mysecretkey$arg_app/$arg_name$arg_e;
        
                    # bad hash
                    if ($secure_link = "") {
                        return 501;
                    }
        
                    # link expired
                    if ($secure_link = "0") {
                        return 502;
                    }
                    return 200;
                }
        

        и секцию "rtmp" как в примере http://helping-squad.com/nginx-rtmp-how … ure-links/ :

        rtmp {
            server {
                listen 1935;
                notify_method get;
        
                # protected application
                application camera1 {
                    live on;
                    wait_video on;
                    on_play http://localhost:65080/on_play;
                    exec_pull /usr/local/bin/ffmpeg -thread_queue_size 5120 -i rtsp://user:password@192.168.2.20:554/Streaming/Channels/1?tcp -thread_queue_size 5120 -f alsa -ac 1 -i hw:1 -map 0  -map 1 -vcodec copy -acodec libfdk_aac -ab 24k -ar 22050 -f flv rtmp://localhost:1935/camera2/stream ;
        
                }
            }
        }
        
        

        Nginx настроен. Опция exec_pull означает что поток rtsp будет браться с камеры только при запросе.

        Можно добавить аудиопоток с микрофона, как в моём примере. Буфер "-thread_queue_size 5120" сглаживает данные при перекодировке и микшировании со звуком. В этом примере перекодировки video нет (опция -vcodec copy).

        Теперь надо создать url в iobroker к rtmp-потоку.

        В настройке драйвера js добавляем библиотеку "crypto".

        Создаём скрипт:

        createState('rtmp1',url_1);
        createState('rtmp1_local',url_local_1);
        schedule("*/15 * * * *", function () {
        
        var crypto = require('crypto');
        var time = Math.round(Date.now()/1000) + 3600;
        var md5_1 = crypto.createHash('md5').update("mysecretkeycamera1/stream" + time).digest('binary');
        var hash_1 = new Buffer(md5_1, "binary").toString('base64');
        hash_1 = hash_1.replace(/\+/g, '-');
        hash_1 = hash_1.replace(/\//g, '_');
        hash_1 = hash_1.replace(/=/g, '');
        var url_1    = "rtmp://www.mydnsurl.ru:8095/camera1/stream?e=" + time + "&st=" +  hash_1;
        var url_local_1    = "rtmp://192.168.2.200:1935/camera1/stream?e=" + time + "&st=" +  hash_1;
        setState("javascript.0.rtmp1",url_1);
        setState("javascript.0.rtmp1_local",url_local_1);
        });
        

        Один url для локального доступа, второй для внешнего. При внешнем доступе на роутере настраиваем проброс портов на нужный сервер:порт.

        Обратите внимание что первая часть пароля "mysecretkeycamera1/stream" состоит из собственно пароля "mysecretkey" и присоединённой части образованной из "camera1/stream" : "camera1" это имя приложения в конфиге nginx, а "stream", используется при создании потока ffmpeg: "-f flv rtmp://localhost:1935/camera2/stream". Время действия ссылки в этом примере - 3600 сек.

        В редакторе vis создаём кнопку элементом basic html:

        Здесь в зависимости от типа вход (lan/wan) , а также в зависимости от клиента (андроид или десктоп) выбираем урл.

        Для IOS тоже можно приготовить поток в формате hls, nginx это умеет.

        Для андроида нужно установить vlc, mx-player или иное приложение, понимающее rtmp. При клике андроид спросит чем открыть.

        Для десктопа открывается страница cam1:

        
            RTMP player
        
        
        1 Reply Last reply Reply Quote 0
        • W
          wantsoft last edited by

          Заткнулся на

          ./configure --add-module=/path/to/nginx-rtmp-module --with-http_secure_link_module 
          make
          make install
          

          После сборки не запускается nginx````
          Failed to start nginx.service: Unit nginx.service failed to load: No such file or directory.

          Не силен в linuxe. А нет готового пакета nginx с rtmp-module для debian ?
          1 Reply Last reply Reply Quote 0
          • A
            andrey99986 last edited by

            @wantsoft:

            Заткнулся на

            ./configure --add-module=/path/to/nginx-rtmp-module --with-http_secure_link_module 
            make
            make install
            

            После сборки не запускается nginx````
            Failed to start nginx.service: Unit nginx.service failed to load: No such file or directory.

            Не силен в linuxe. А нет готового пакета nginx с rtmp-module для debian ? `  
            

            Скорее всего если до этого стоял пакет из репозитария linux (debian/ubuntu или что у вас там) то пути в стартовом скрипте остались старые, не соответствующие откомпиленной версии. Если ещё актуально дам стартовый скрипт.

            1 Reply Last reply Reply Quote 0
            • A
              andrey99986 last edited by

              В связи со скорым прекращением поддержки flash в браузерах предлагаю более современный вариант стриминга видео в vis,

              пока для локальной сети (без секурных ссылок), работает в браузерах Chrome и FireFox на pc и android .

              Исходные данные:

              IP камера (адрес 10.10.10.10), отдающая поток в формате rtsp.

              Задача:

              Получить видео на странице iobroker без использования flash.

              Решение:

              1. Компилируем nginx с поддержкой rtmp, как было описано ранее.

              2. Правим конфиг nginx для отдачи видео в формате mpeg-dash:

              worker_processes 2;
              
              error_log /var/log/nginx/error.log warn;
              pid /var/run/nginx.pid;
              
              events {
                worker_connections 1024;
              }
              
              http {
                include /etc/nginx/mime.types;
                default_type application/octet-stream;
              
                log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for"';
              
                access_log /var/log/nginx/access.log main;
                sendfile on;
                keepalive_timeout 65;
              
                server {
                  listen 80;
                  add_header 'Access-Control-Allow-Origin' '*';
                  location /dash {
                          root /usr/html;
              	    add_header 'Access-Control-Allow-Origin' '*';
                          add_header Cache-Control no-cache;
                  }
              
                  location /dash.js {
                  root /usr/html;
                  }
               }
               include /etc/nginx/conf.d/*.conf;
              }
               rtmp {
                   access_log /var/log/nginx/rtmp_access.log;
                   server {
                   listen 1935;
                   ping 30s;
                   notify_method get;
              
                   # генерация dash-манифеста и фрагментов
                      application cam1 {
                        live on;
                        dash on;
                        dash_path /usr/html/dash;
                        exec_static ffmpeg -i rtsp://admin:password@10.10.10.10:554/Streaming/Channels/2 -an -vcodec copy -f flv rtmp://127.0.0.1:1935/cam1/stream;
                     }
               }
              }
              

              3. Как описано на https://habrahabr.ru/post/204666/

              ` > Скачиваем и устанавливаем dash.js из форка

              скачаем dash.js в /usr/html

              cd /usr/html

              git clone https://github.com/arut/dash.js.git

              cd dash.js

              git checkout live

              Открываем в редакторе baseline.html и находим строчку со стандартным урлом

              url = "http://dash.edgesuite.net/envivio/dashp … nifest.mpd",

              Заменяем на наш урл

              url = "http://172.16.1.120:80/dash/stream.mpd". `

              Теперь можно проверить воспроизведение видео до встраивание его в iobroker:

              http://172.16.1.120/dash.js/baseline.html

              4. В vis-е в элементе basic-HTML согласно инструкции https://github.com/Dash-Industry-Forum/ … /README.md :

              
              <title>Auto-player instantiation example, single videoElement, using src attribute</title>
              
              

              5. Пробуем открыть страницу в режиме просмотра и видим ошибку (правая кнопка мыши-посмотреть код):

              Refused to load media from 'blob:http://172.16.1.120:8082/f75ba73c-3f5e- … 389bfdca45' because it violates the following Content Security Policy directive: "media-src 'self' 'unsafe-inline' *".

              6. До обновления vis или придумывания обходного решения правим файл /home/iobroker/node_modules/iobroker.vis/www/index.src.html:

              Находим строку media-src 'self' 'unsafe-inline' *

              и добавляем параметр blob:

              В итоге должно быть:

              media-src 'self' 'unsafe-inline' * blob:

              7. Выполняем команду: iobroker upload vis

              8. Видео отображается.

              P.S. Для уменьшения задержки (только при хорошем канале) в конфиге nginx добавляем параметры (****__dash_playlist_length 10s;

              dash_fragment 2s;__****):

              application cam1 {
                        live on;
                        dash on;
              dash_playlist_length 10s;
              dash_fragment 2s;
                        dash_path /usr/html/dash;
                        exec_static ffmpeg -i rtsp://admin:password@10.10.10.10:554/Streaming/Channels/2 -an -vcodec copy -f flv rtmp://127.0.0.1:1935/cam1/stream;
                     }
              

              P.P.S. Каталог с фрагментами dash (в данном случае "/usr/html/dash") рекомендуется размещать на ram-disk, чтобы не насиловать hdd/sdd.

              1 Reply Last reply Reply Quote 0
              • A
                andrey99986 last edited by

                Протестировав HLS и mpeg-dash пришёл к заключению что HLS-поток лучше справляется с передачей видео на медленном и нестабильном канале связи. Поэтому оставляю у себя HLS. Плюс у него ещё в том, что поток можно смотреть с любого устройства - android, apple, desktop с Windows.

                Привожу настройки с секурными ссылками (актуально при просмотре через интернет) :

                1. Nginx надо будет скомпилировать с такими ключами:

                ./configure –with-http_sub_module --with-http_secure_link_module --add-module=/path/to/nginx-rtmp-module

                make; make install

                2. Конфиг nginx (проверяется переданный пароль (mypassword) 😞
                ` > user www-data;

                worker_processes 1;

                pid /var/run/nginx.pid;

                error_log /var/log/nginx/error.log;

                events {

                worker_connections 1024;

                }

                http {

                limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

                include mime.types;

                default_type application/octet-stream;

                sendfile on;

                keepalive_timeout 65;

                access_log /var/log/nginx/access.log;

                server {

                client_max_body_size 12M;

                listen 65080;

                root /var/www;

                index main.php;

                rewrite_log on;

                uninitialized_variable_warn on;

                server_name http://www.mysite.ru;

                add_header 'Access-Control-Allow-Origin' '*';

                location / {

                rtmp_control all;

                auth_basic "closed site";

                auth_basic_user_file /etc/apache2/htpasswd.cfg;

                }

                location ~* .(?:ico|jpg|jpeg)$ {

                expires 10m;

                add_header Pragma public;

                add_header Cache-Control "public";

                }

                location /hls1/ {

                add_header 'Access-Control-Allow-Origin' '*';

                root /mnt/ramdisk;

                add_header Cache-Control no-cache;

                secure_link $arg_sth1,$arg_expiresh1;

                secure_link_md5 mypassword$arg_expiresh1;

                sub_filter .ts .ts?sth1=$arg_sth1&expiresh1=$arg_expiresh1;

                sub_filter_once off;

                sub_filter_types *;

                if ($secure_link = "") {

                return 403;

                }

                if ($secure_link = "0") {

                return 410;

                }

                }

                }

                }

                rtmp {

                access_log /var/log/nginx/rtmp_access.log;

                server {

                listen 1935;

                ping 30s;

                notify_method get;

                application hlscamera1 {

                live on;

                hls on;

                hls_playlist_length 20s;

                hls_fragment 4s;

                hls_path /mnt/ramdisk/hls1;

                exec_static /usr/bin/ffmpeg -thread_queue_size 5120 -i rtsp://user:password@192.168.2.30:554/Streaming/Channels/2 -thread_queue_size 5120 -f alsa -i default -map 0 -map 1 -vcodec copy -acodec libfdk_aac -ab 24k -ar 22050 -f flv rtmp://localhost:1935/hlscamera1/stream1;

                }

                } `

                3. Скрипт, генерирующий безопасные ссылки (1 при web доступе, другая при ЛВС-доступе), задаётся пароль (mypassword) в iobroker:

                schedule("* * * * *", function () {
                
                var crypto = require('crypto');
                var time = Math.round(Date.now()/1000) + 10*3600;
                
                var md5_hls1 = crypto.createHash('md5').update("mypassword"+time).digest('binary');
                var hash_hls1 = new Buffer(md5_hls1, "binary").toString('base64');
                hash_hls1 = hash_hls1.replace(/\+/g, '-');
                hash_hls1 = hash_hls1.replace(/\//g, '_');
                hash_hls1 = hash_hls1.replace(/=/g, '');
                var url_hls1    = "http://www.mysite.ru:65080/hls1/stream1.m3u8?sth1=" +  hash_hls1 + "&expiresh1=" + time;
                var url_local_hls1    = "http://192.168.2.200:65080/hls1/stream1.m3u8?sth1=" +  hash_hls1 + "&expiresh1=" + time;
                
                createState('hls1',url_hls1);
                createState('hls1_local',url_local_hls1);
                setState("javascript.0.hls1",url_hls1);
                setState("javascript.0.hls1_local",url_local_hls1);
                
                });
                

                4. В vis - редакторе создаём кнопку :

                5. И страницу cam1:

                1 Reply Last reply Reply Quote 0
                • A
                  andrey99986 last edited by

                  Протестировав HLS и mpeg-dash пришёл к заключению что HLS-поток лучше справляется с передачей видео на медленном и нестабильном канале связи. Поэтому оставляю у себя HLS. Плюс у него ещё в том, что поток можно смотреть с любого устройства - android, apple, desktop с Windows.

                  Привожу настройки с секурными ссылками (актуально при просмотре через интернет) :

                  1. Nginx надо будет скомпилировать с такими ключами:

                  ./configure –with-http_sub_module --with-http_secure_link_module --add-module=/path/to/nginx-rtmp-module

                  make; make install

                  2. Конфиг nginx (проверяется переданный пароль (mypassword) 😞
                  ` > user www-data;

                  worker_processes 1;

                  pid /var/run/nginx.pid;

                  error_log /var/log/nginx/error.log;

                  events {

                  worker_connections 1024;

                  }

                  http {

                  limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

                  include mime.types;

                  default_type application/octet-stream;

                  sendfile on;

                  keepalive_timeout 65;

                  access_log /var/log/nginx/access.log;

                  server {

                  client_max_body_size 12M;

                  listen 65080;

                  root /var/www;

                  index main.php;

                  rewrite_log on;

                  uninitialized_variable_warn on;

                  server_name http://www.mysite.ru;

                  add_header 'Access-Control-Allow-Origin' '*';

                  location / {

                  rtmp_control all;

                  auth_basic "closed site";

                  auth_basic_user_file /etc/apache2/htpasswd.cfg;

                  }

                  location ~* .(?:ico|jpg|jpeg)$ {

                  expires 10m;

                  add_header Pragma public;

                  add_header Cache-Control "public";

                  }

                  location /hls1/ {

                  add_header 'Access-Control-Allow-Origin' '*';

                  root /mnt/ramdisk;

                  add_header Cache-Control no-cache;

                  secure_link $arg_sth1,$arg_expiresh1;

                  secure_link_md5 mypassword$arg_expiresh1;

                  sub_filter .ts .ts?sth1=$arg_sth1&expiresh1=$arg_expiresh1;

                  sub_filter_once off;

                  sub_filter_types *;

                  if ($secure_link = "") {

                  return 403;

                  }

                  if ($secure_link = "0") {

                  return 410;

                  }

                  }

                  }

                  }

                  rtmp {

                  access_log /var/log/nginx/rtmp_access.log;

                  server {

                  listen 1935;

                  ping 30s;

                  notify_method get;

                  application hlscamera1 {

                  live on;

                  hls on;

                  hls_playlist_length 20s;

                  hls_fragment 4s;

                  hls_path /mnt/ramdisk/hls1;

                  exec_static /usr/bin/ffmpeg -thread_queue_size 5120 -i rtsp://user:password@192.168.2.30:554/Streaming/Channels/2 -thread_queue_size 5120 -f alsa -i default -map 0 -map 1 -vcodec copy -acodec libfdk_aac -ab 24k -ar 22050 -f flv rtmp://localhost:1935/hlscamera1/stream1;

                  }

                  } `

                  3. Скрипт, генерирующий безопасные ссылки (1 при web доступе, другая при ЛВС-доступе), задаётся пароль (mypassword) в iobroker:

                  schedule("* * * * *", function () {
                  
                  var crypto = require('crypto');
                  var time = Math.round(Date.now()/1000) + 10*3600;
                  
                  var md5_hls1 = crypto.createHash('md5').update("mypassword"+time).digest('binary');
                  var hash_hls1 = new Buffer(md5_hls1, "binary").toString('base64');
                  hash_hls1 = hash_hls1.replace(/\+/g, '-');
                  hash_hls1 = hash_hls1.replace(/\//g, '_');
                  hash_hls1 = hash_hls1.replace(/=/g, '');
                  var url_hls1    = "http://www.mysite.ru:65080/hls1/stream1.m3u8?sth1=" +  hash_hls1 + "&expiresh1=" + time;
                  var url_local_hls1    = "http://192.168.2.200:65080/hls1/stream1.m3u8?sth1=" +  hash_hls1 + "&expiresh1=" + time;
                  
                  createState('hls1',url_hls1);
                  createState('hls1_local',url_local_hls1);
                  setState("javascript.0.hls1",url_hls1);
                  setState("javascript.0.hls1_local",url_local_hls1);
                  
                  });
                  

                  4. В vis - редакторе создаём кнопку :

                  5. И страницу cam1:

                  1 Reply Last reply Reply Quote 0
                  • A
                    andrey99986 last edited by

                    Протестировав HLS и mpeg-dash пришёл к заключению что HLS-поток лучше справляется с передачей видео на медленном и нестабильном канале связи. Поэтому оставляю у себя HLS. Плюс у него ещё в том, что поток можно смотреть с любого устройства - android, apple, desktop с Windows.

                    Привожу настройки с секурными ссылками (актуально при просмотре через интернет) :

                    1. Nginx надо будет скомпилировать с такими ключами:

                    ./configure –with-http_sub_module --with-http_secure_link_module --add-module=/path/to/nginx-rtmp-module

                    make; make install

                    2. Конфиг nginx - nginx.conf (проверяется переданный пароль (mypassword) 😞

                    3. Скрипт - script.txt, генерирующий безопасные ссылки (1 при web доступе, другая при ЛВС-доступе), задаётся пароль (mypassword) в iobroker.

                    4. В vis - редакторе создаём кнопку - but1.txt.

                    5. И страницу cam1 - cam1.txt.
                    1444_video-hls.rar

                    1 Reply Last reply Reply Quote 0
                    • Gavrik
                      Gavrik last edited by

                      Добрый день.

                      Решил заморочится тоже выводом видео с камер в IoBroker.

                      По инструкции выше от andrey99986 скомпилировал nginx с модулем rmtp.

                      Для проверки настроек пришлось выкинуть все секурные ссылки, а то не было понятно что не работает и подобрать параметры ffmpeg.

                      На данный момент nginx на малинке принимает поток с камеры в rstp и отдает ее rmtp.

                      Настроил трансляцию в HLS. С самим ngnix вроде все пока.

                      Добрался до iobroker, и вот тут две странности на которых я завис.

                      1. Первая - если урл на hls напрямую вставить в скрипт в строку hls.loadSource("http://192.168.13.232:65080/hls/stream1.m3u8"); то видео есть, если его передавать через переменную как в оригинале hls.loadSource("{javascript.0.hls1}"); то видео нет 😞

                      В переменной правильный урл есть, проверял.

                      2. Вторая, самая странная - если указываем hls.loadSource("http://192.168.13.232:65080/hls/stream1.m3u8") то в редакторе видео есть, а на странице - нет 😞

                      Почему ?

                      ! 7522_2018_06_28_17_14_46_edit_vis.png
                      ! 7522_2018_06_28_17_17_51_vis.png

                      1 Reply Last reply Reply Quote 0
                      • Gavrik
                        Gavrik last edited by

                        С второй проблемой стало понятнее, после внимательного чтения темы.

                        Но все равно не работает..

                        После правки index.src.html

                        в результате в коде станицы blob все равно отсутствует.

                        и даже если в его прямо в хроме вставить , имеем ошибку :
                        > Refused to load media from 'blob:[http://192.168.13.232:8082/1b359eb4-402 … 01580bc8e1](http://192.168.13.232:8082/1b359eb4-4027-454c-8b65-9d01580bc8e1)' because it violates the following Content Security Policy directive: "media-src 'self' 'unsafe-inline' * blob".

                        Куда копать , подскажите ?

                        p.s. Докопался, пропустил двоеточие после blob.

                        M 1 Reply Last reply Reply Quote 0
                        • M
                          medjai @Gavrik last edited by

                          Не придумалось случайно ничего нового? )

                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post

                          Support us

                          ioBroker
                          Community Adapters
                          Donate

                          645
                          Online

                          31.8k
                          Users

                          80.0k
                          Topics

                          1.3m
                          Posts

                          8
                          23
                          14324
                          Loading More Posts
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes
                          Reply
                          • Reply as topic
                          Log in to reply
                          Community
                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                          The ioBroker Community 2014-2023
                          logo