Broadcast RTSP to WEB. Conversion to HLS. Boxed solution

The task was to collect all RTSP streams from a video recorder (netsurveillance) and provide quick access to the video stream for several people. Since no browser can independently display the RTSP protocol, it was necessary to find anything to convert this stream into a format suitable for WEB.



I'll make a reservation right away: during the operation of this solution, the possibility of sharing a video archive using SAMBA was discovered. This opportunity seemed very convenient for me personally, and I decided to implement it in this context. Of course, someone may have a question: "Is there a Line and why is everything else needed?" - in our case, this solution turned out to be too expensive. And they still count in dollars . So what is available:



  • A corporate network based on Mikrotik using a regular VPN
  • Several CCTVs consisting of a variety of cameras and a video recorder
  • Linux machine with deployed SAMBA-AD-DC and WEB server in the central office


Is it worth reminding that the whole thing is being converted from RTSP to HLS? I install the Shinobi host on Linux according to this instruction . There is nothing complicated in the installation, you just need to install git, some dependencies and run the installation script. Technically the same Line, only for free. Perhaps enough for the first time. The interface only seems more convenient, otherwise the same. After installation and launch, open localhost : 8080 / super, log in as admin@shinobi.video with the password admin and create a main entry for access to monitoring.



The default storage options didn't work for me. In addition, during operation, I searched for these settings for a long time, but the urgency forced me to simply disable cron.js (sudo pm2 stop cron) and use Linux tools to clean the video archive directories.



image



Number of Days to keep Videos - the number of days to keep videos.

Number of Days to keep Events - the number of days to keep events (logins, password changes, etc.).

Number of Days to keep Logs - the number of days to keep system messages: failures, errors, initialization.



All these parameters are set individually for each user, very convenient. But there is also an API. It can be used to get all streams of a specific monitor (a monitor is a set of streams for broadcasting) and present each of them separately as an online broadcast on a web page. First, you need to add information about streams from video surveillance cameras to monitoring.



image



image



image



Mode - broadcast mode: Record - recording, Watch only - viewing only.

Name - the name of the video stream

Storage location - the archive storage location , if you have set Record in Mode

Full URL Path - a link to the rtsp stream itself. For netsurveillance, this is usually the link: rtsp: // IP: 554 / user = USER & password = PASSWORD & channel = CHANNELNUMBER & stream = 1.sdp? Real_stream — rtp-caching = 100 The



resource consumption information displayed in Shinobi differs greatly from that displayed by htop . In the web interface, I constantly see half-full memory, but the processor load, by the way, is quite consistent with what can be seen from the console.



image



As far as was known, it is also possible to use the system GPU to convert the stream. But since we did not have it installed, there was no way to make sure of this. Everything happens by means of the CPU. We have converted 17 streams, 3 of which are recorded locally. I will give here information about our processor:



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








If you only need to connect an online broadcast on a web page, then you must first add the API key to the user whose monitor we are interested in. A complete API guide can be found on the official website of the application. At the top, place the cursor on the user's email, click, select the API item.



image



The main parameter for us is Allowed IPs (allowed IPs). My access is open only for the local network, but if you plan to stream your streams to the global Internet, then you need to specify 0.0.0.0/0 and forward the Shinobi port outside.



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


Information about web streams can be obtained with a simple GET request, the result is obtained in JSON format, which can be easily converted into data. An example of a simple PHP script:



<?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>";
 
?>
      
      





For some cameras, I have the Recording mode specified. In this case, in addition to converting the stream, it also records from RTSP to the local hard drive. If Default is specified in the Recording parameters, then the recording will be stored in the ./Shinobi/videos/ [MinitorID ] / [[CameraID] folder . For me, some folders from the main monitor are accessible over the network and mounted by means of GPO for a specific group as network drives.



image



Why is this done? A simple feature of logistics: it happens that a large car is loaded with goods and leaves for another city, where it is unloaded by the buyer, who can say that something is missing. And it happens that in their stores they can no longer count something. Therefore, for the warehouse, a separate recording is made from some cameras already in mp4 format. This can save tons of debriefing time.



All Articles