Transmita RTSP a WEB. Conversión a HLS. Solución en caja

La tarea consistía en recopilar todas las transmisiones RTSP de una grabadora de video (vigilancia por red) y proporcionar acceso rápido a la transmisión de video para varias personas. Dado que ningún navegador puede mostrar de forma independiente el protocolo RTSP, fue necesario encontrar algo para convertir este flujo en un formato adecuado para WEB.



Haré una reserva de inmediato: durante el funcionamiento de esta solución, se descubrió la posibilidad de compartir un archivo de video usando SAMBA. Esta oportunidad me pareció muy conveniente personalmente y decidí implementarla en este contexto. Por supuesto, alguien puede tener una pregunta: "¿Existe una línea y por qué se necesita todo lo demás?" - en nuestro caso, esta solución resultó ser demasiado cara. Y todavía cuentan en dólares . Entonces, ¿qué hay disponible?



  • Red corporativa basada en Mikrotik usando una VPN normal
  • Varios CCTV que constan de una variedad de cámaras y una grabadora de video.
  • Máquina Linux con SAMBA-AD-DC implementado y servidor WEB en la oficina central


¿Vale la pena recordar que todo se está convirtiendo de RTSP a HLS? Instalo el host Shinobi en Linux de acuerdo con estas instrucciones . No hay nada complicado en la instalación, solo necesitas instalar git, algunas dependencias y ejecutar el script de instalación. Técnicamente la misma línea, solo que gratis. Quizás suficiente por primera vez. La interfaz solo parece más conveniente, por lo demás igual. Después de la instalación y el lanzamiento, abra localhost : 8080 / super, inicie sesión como admin@shinobi.video con la contraseña admin y cree una entrada principal para acceder a la supervisión.



Las opciones de almacenamiento predeterminadas no funcionaron para mí. Además, durante la operación, busqué estas configuraciones durante mucho tiempo, pero la urgencia me obligó a simplemente deshabilitar cron.js (sudo pm2 stop cron) y usar herramientas de Linux para limpiar los directorios de archivos de video.



imagen



Número de días para guardar videos : el número de días para guardar videos.

Número de días para guardar eventos : el número de días para guardar eventos (inicios de sesión, cambios de contraseña, etc.).

Número de días para mantener registros : el número de días para mantener los mensajes del sistema: fallas, errores, inicialización.



Todos estos parámetros se configuran individualmente para cada usuario, muy conveniente. Pero también hay una API. Usando sus medios, puede obtener todas las transmisiones de un monitor específico (un monitor es un conjunto de transmisiones para transmisión) y presentar cada una de ellas por separado como una transmisión en línea en una página web. Primero, debe agregar información sobre las transmisiones desde las cámaras de videovigilancia hasta el monitoreo.



imagen



imagen



imagen



Modo : modo de transmisión: grabación : grabación, solo visualización: solo visualización.

Nombre : el nombre de la secuencia de video

Ubicación de almacenamiento : la ubicación de almacenamiento del archivo, si ha configurado Grabar en el modo

Ruta URL completa : un enlace a la transmisión rtsp en sí. Para la vigilancia por red, este suele ser el enlace: rtsp: // IP: 554 / user = USER & password = PASSWORD & channel = CHANNELNUMBER & stream = 1.sdp? Real_stream - rtp-caching = 100 La



información de consumo de recursos que se muestra en Shinobi es diferente mucho de lo mostrado por htop . En la interfaz web, veo constantemente la memoria medio llena, pero la carga del procesador, por cierto, es bastante consistente con lo que se puede ver desde la consola.



imagen



Hasta donde se sabía, también es posible utilizar la GPU del sistema para convertir la transmisión. Pero como no lo teníamos instalado, no había forma de asegurarnos de esto. Todo sucede por medio de la CPU. Hemos convertido 17 transmisiones, 3 de las cuales se graban localmente. Daré aquí información sobre nuestro procesador:



lscpu
Architecture: x86_64

CPU op-mode(s): 32-bit, 64-bit

Byte Order: Little Endian

Address sizes: 36 bits physical, 48 bits virtual

CPU(s): 8

On-line CPU(s) list: 0-7

Thread(s) per core: 2

Core(s) per socket: 4

Socket(s): 1

NUMA node(s): 1

Vendor ID: GenuineIntel

CPU family: 6

Model: 30

Model name: Intel(R) Xeon(R) CPU X3440 @ 2.53GHz

Stepping: 5

CPU MHz: 1210.183

CPU max MHz: 2534,0000

CPU min MHz: 1200,0000

BogoMIPS: 5066.32

Virtualization: VT-x

L1d cache: 32K

L1i cache: 32K

L2 cache: 256K

L3 cache: 8192K

NUMA node0 CPU(s): 0-7








Si solo necesita conectar una transmisión en línea en una página web, primero debe agregar la clave API al usuario cuyo monitor nos interesa. Se puede encontrar una guía API completa en el sitio web oficial de la aplicación. En la parte superior, coloque el cursor en el correo electrónico del usuario, haga clic en, seleccione el elemento API.



imagen



El parámetro principal para nosotros son las IP permitidas (IP permitidas). Mi acceso está abierto solo para la red local, pero si planea transmitir sus transmisiones a Internet global, debe especificar 0.0.0.0/0 y reenviar el puerto Shinobi al exterior.



, Shinobi RTSP , -. . : , 100% -, - RJ-45. , IP : - . AHD . , , ( ) — , .


La información sobre los flujos web se puede obtener con una simple solicitud GET, el resultado se obtiene en formato JSON, que se puede convertir fácilmente en datos. Un ejemplo de un script PHP simple:



<?php
 
$url = array(
    'host'          => '192.168.2.104',                      # ,    Shinobi
    'port'          => '8080',                               #  web- Shinobi
    'api'           => 'TyIp1yRhqPLnJmlDpMzAenWYqVW8vt', # API 
    'monitor'       => 'f2xnMN0VAv'                          # ID ,   
);
 
$link = file_get_contents("http://". $url['host'] .":". $url['port'] ."/". $url['api'] ."/monitor/". $url['monitor'] ."/");
 
foreach(json_decode($link) as $data) {
     
    $source['title'][]  = $data->name;
    $source['url'][]    = "http://". $url['host'] .":". $url['port'] . $data->streams[0];
    $source['width'][]  = $data->width;
    $source['height'][] = $data->height;
    $source['status'][] = $data->status;
 
}
 
print "<html>
 
    <head>
        <title> </title>
        <link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css' integrity='sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T' crossorigin='anonymous'>
        <link href='https://vjs.zencdn.net/7.2.3/video-js.css' rel='stylesheet'>
    </head>
    <body>
     
    <div class='container' style='padding: 30pt 0;'>
 
        <div class='row'>
        <div class='col-sm-12' style='margin: 10pt 0 10pt;'>  
 
            <div class='card'>
                <div class='card-body'>
 
                <form action='' method='POST'>
                  <select class='form-control form-control-lg' name='streamId' onchange='this.form.submit()'>
                    ";
 
for($i = 0; $i <= count($source['title']); $i++){
     
    if( $_POST['streamId'] == $i) {
        print "<option value=". $i ." selected>". $source['title'][$i] ."</option>";
    } else {
        print "<option value=". $i .">". $source['title'][$i] ."</option>";
    }
}
 
if( isset($_POST['streamId']) ) {
    $id = $_POST['streamId'];
} else {
    $id = 0;
}
 
print "         </select></form>
        </div>
      </div>
</div>
 
<div class='col-sm-12'>   
 
    <div class='card'>
        <div class='card-body'>
         <video id='hls-example' style='margin: 0 auto;' class='video-js vjs-default-skin' width='". $source['width'][$id] ."' height='". $source['height'][$id] ."' controls>
            <source type='application/x-mpegURL' src='". $source['url'][$id] ."'>
            </video>
         <!-- <p class='card-text'>This is another card with title and supporting text below. This card has some additional content to make it slightly taller overall.</p> -->
          <p class='card-text' style='text-align: center;'> <small class='text-muted'>  : ". $source['status'][$id] ."</small></p>
        </div>
      </div>
    </div>
 
</div>
 
 
    <script src='https://vjs.zencdn.net/ie8/ie8-version/videojs-ie8.min.js'></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/videojs-contrib-hls/5.14.1/videojs-contrib-hls.js'></script>
    <script src='https://vjs.zencdn.net/7.2.3/video.js'></script>
 
    <script>
    var player = videojs('hls-example');
    player.play();
    </script>
 
 
 
    </div>
         
    </body>
</html>";
 
?>
      
      





Para algunas cámaras, tengo el modo de grabación especificado. En este caso, además de convertir el flujo, también graba desde RTSP al disco duro local. Si se especifica Predeterminado en los parámetros de grabación, la grabación se almacenará en la carpeta ./Shinobi/videos/ [MinitorID] / [[CameraID] . Para mí, algunas carpetas del monitor principal son accesibles a través de la red y se montan mediante GPO para un grupo específico como unidades de red.



imagen



¿Por qué se hace esto? Una característica simple de la logística: sucede que un automóvil grande se carga con mercancías y sale hacia otra ciudad, donde es descargado por el comprador, quien puede decir que falta algo. Y sucede que en sus tiendas ya no pueden contar algo. Por lo tanto, se realiza una grabación separada para el almacén de algunas cámaras que ya están en formato mp4. Esto puede ahorrar toneladas de tiempo para informar.



All Articles