Transmita RTSP para WEB. Conversão para HLS. Solução em caixa

A tarefa era coletar todos os streams RTSP de um gravador de vídeo (netsurveillance) e fornecer acesso rápido ao stream de vídeo para várias pessoas. Uma vez que nenhum navegador pode exibir independentemente o protocolo RTSP, foi necessário encontrar algo para converter esse fluxo em um formato adequado para WEB.



Vou fazer uma reserva de imediato: durante o funcionamento desta solução, foi descoberta a possibilidade de partilhar um arquivo de vídeo através do SAMBA. Esta oportunidade pareceu-me muito conveniente pessoalmente e decidi implementá-la neste contexto. Claro, alguém pode ter uma pergunta: "Existe uma linha e por que tudo o mais é necessário?" - no nosso caso, essa solução acabou sendo muito cara. E eles ainda contam em dólares . Então, o que está disponível:



  • Rede corporativa baseada em Mikrotik usando VPN regular
  • Vários CCTVs consistindo em uma variedade de câmeras e um gravador de vídeo
  • Máquina Linux com SAMBA-AD-DC implantado e servidor WEB no escritório central


Vale lembrar que tudo está sendo convertido de RTSP para HLS? Eu instalo o host Shinobi no Linux de acordo com esta instrução . Não há nada complicado na instalação, você só precisa instalar o git, algumas dependências e executar o script de instalação. Tecnicamente a mesma linha, apenas de graça. Talvez o suficiente pela primeira vez. A interface só parece mais conveniente, caso contrário, a mesma. Após a instalação e o lançamento, abra localhost : 8080 / super, faça login como admin@shinobi.video com a senha admin e crie uma entrada principal para acessar o monitoramento.



As opções de armazenamento padrão não funcionaram para mim. Além disso, durante a operação, procurei por essas configurações por um longo tempo, mas a urgência me forçou a simplesmente desativar o cron.js (sudo pm2 stop cron) e usar as ferramentas do Linux para limpar os diretórios de arquivo de vídeo.



imagem



Número de dias para manter os vídeos - o número de dias para manter os vídeos.

Número de dias para manter eventos - o número de dias para manter eventos (logins, alterações de senha, etc.).

Número de dias para manter os registros - o número de dias para manter as mensagens do sistema: falhas, erros, inicialização.



Todos esses parâmetros são definidos individualmente para cada usuário, muito conveniente. Mas também existe uma API. Usando seus meios, você pode obter todos os streams de um monitor específico (um monitor é um conjunto de streams para transmissão) e apresentar cada um deles separadamente como uma transmissão online em uma página da web. Primeiro, você precisa adicionar informações sobre fluxos de câmeras de vigilância por vídeo ao monitoramento.



imagem



imagem



imagem



Modo - modo de transmissão: Gravação - gravação, Assistir apenas - apenas visualização.

Nome - o nome do

local de armazenamento do fluxo de vídeo - o local de armazenamento do arquivo, se você configurou Gravação no Modo

Caminho de URL completo - um link para o próprio fluxo rtsp. Para netsurveillance, geralmente é o link: rtsp: // IP: 554 / user = USER & password = PASSWORD & channel = CHANNELNUMBER & stream = 1.sdp? Real_stream - rtp-caching = 100 As



informações de consumo de recursos exibidas no Shinobi são diferentes muito daquele exibido pelo htop . Na interface da web, vejo constantemente a memória meio cheia, mas a carga do processador, a propósito, é bastante consistente com o que pode ser visto no console.



imagem



Tanto quanto se sabe, também é possível usar a GPU do sistema para converter o fluxo. Mas, como não o tínhamos instalado, não havia como ter certeza disso. Tudo acontece por meio da CPU. Convertemos 17 fluxos, 3 dos quais são registrados localmente. Vou dar aqui informações sobre o nosso processador:



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








Se você só precisa conectar uma transmissão online em uma página da web, você deve primeiro adicionar a chave API ao usuário em cujo monitor estamos interessados. Um guia completo da API pode ser encontrado no site oficial do aplicativo. Na parte superior, coloque o cursor no e-mail do usuário, clique em, selecione o item da API.



imagem



O principal parâmetro para nós são os IPs permitidos (IPs permitidos). Meu acesso é aberto apenas para a rede local, mas se você planeja transmitir seus streams para a Internet global, você precisa especificar 0.0.0.0/0 e encaminhar a porta Shinobi para fora.



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


Informações sobre web streams podem ser obtidas com uma simples solicitação GET, o resultado é obtido no formato JSON, que pode ser facilmente convertido em dados. Um exemplo de um script PHP simples:



<?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 algumas câmeras, tenho o modo de gravação especificado. Nesse caso, além de converter o stream, também grava do RTSP para o disco rígido local. Se Default for especificado nos parâmetros de Gravação, a gravação será armazenada na pasta ./Shinobi/videos/ [MinitorID] / [[CameraID] . Para mim, algumas pastas do monitor principal podem ser acessadas pela rede e montadas por meio de GPO para um grupo específico como unidades de rede.



imagem



Por que isso é feito? Uma característica simples da logística: acontece que um grande carro é carregado com a mercadoria e parte para outra cidade, onde é descarregado pelo comprador, que pode dizer que falta algo. E acontece que em suas lojas não conseguem mais contar nada. Portanto, uma gravação separada é feita para o warehouse de algumas câmeras já no formato mp4. Isso pode economizar muito tempo de análise.



All Articles