HowTo... live broadcast to website?

Discussion in 'Programming/Scripts' started by Alex Mamatuik, Dec 9, 2022.

  1. Alex Mamatuik

    Alex Mamatuik Member

    Plot:
    Screen Shot 2022-12-10 at 05.08.20-fullpage.png
    Required components -
    • videorecorder (DVR-system);
    • router with opened port for public connections to a DVR;
    • web-server with FFMPEG installed software.
    1. Let's make some streaming script - nano stream.sh:
      Code:
      #!/bin/bash
      
      while true
      do
      if [ -z "$1" ]; then
        IP_ADDRESS=<my_ip_to_connect_with_camera_via_dvr>;
      USER=<name>; PASS=<password> RTSP_PORT=<enabled_port>
      else
        IP_ADDRESS=$1
      fi
      
      # FFMPEG command for creating segments from RTSP stream
      ffmpeg -re -i rtsp://${USER}:${PASS}@${IP_ADDRESS}:${RTSP_PORT=}/trackID=1 \
      -c:v libx264 -crf 21 -map 0 -b:v 500k -r 24 -preset veryfast  \
      -g 25 -sc_threshold 0 \
      -hls_flags append_list+delete_segments -hls_playlist_type event -hls_time 6 -hls_list_size 3200 \
      -hls_delete_threshold 3200  \
      -f segment -segment_list_flags +live -segment_time 6 -segment_list_size 3200 -segment_list \
      /var/www/websites/client0/domain1/web/PALS/DVR/live.m3u8 \
      -segment_list_type m3u8 /var/www/websites/client0/domain1/web/PALS/DVR/%d.ts
      
       sleep 2
      done
      • "/var/www/websites/client0/domain1/web/PALS/DVR" - path, where we store video data:
      • live.m3u8
      • %d.ts

    2. (making service) nano dvr_stream.service
      Code:
      [Unit]
      Description=DVR live stream
      
      [Service]
      ExecStart=/REPOSITORY/DVR/stream.sh
      Restart=on-failure
      
      [Install]
      WantedBy=multi-user.target
    3. chmod +x /REPOSITORY/DVR/stream.sh

    4. ln -s /REPOSITORY/DVR/dvr_stream.service /lib/systemd/system/dvr_stream.service
    5. systemctl enable dvr_stream.service
    6. systemctl start dvr_stream.service
    7. systemctl status dvr_stream.service

      Erasing staled data
    8. nano remove_dvr_live.sh:
      Code:
      #!/bin/bash
      
      while true
      do
        LOCATION=/var/www/websites/client0/domain1/web/PALS/DVR
        REQUIRED_FILES=*.ts
      
      find $LOCATION -name $REQUIRED_FILES -type f -mmin +360 -delete
       sleep 21650
      done


    9. nano remove_dvr_live.service
      Code:
      [Unit]
      Description=Remove ts-segments for the live DVR broadcast
      
      [Service]
      ExecStart=/REPOSITORY/DVR/remove_dvr_live.sh
      Restart=on-failure
      
      [Install]
      WantedBy=multi-user.target


      • chmod +x /REPOSITORY/DVR/remove_dvr_live.sh
      • ln -s /REPOSITORY/DVR/remove_dvr_live.service /lib/systemd/system/remove_dvr_live.service
      • systemctl enable remove_dvr_live.service
      • systemctl start remove_dvr_live.service
      • systemctl status remove_dvr_live.service
    10. RTSP through Video-JS player
      HTML:
      <link href="/sites/all/libraries/video-js_v5/video-js.min.css" rel="stylesheet">
       
       <style type="text/css">
        /* Change all text and icon colors in the player. */
      .vjs-matrix.video-js {
        color:#f70505;
      }
      
      /* Change the border of the big play button. */
      .vjs-matrix .vjs-big-play-button {
        border-color: #f70505;
      }
      
      /* Change the color of various "bars". */
      .vjs-matrix .vjs-volume-level,
      .vjs-matrix .vjs-play-progress,
      .vjs-matrix .vjs-slider-bar {
        background: #f70505;
      }
      </style>
      
      <script src="/sites/all/libraries/video-js_v5/video.js"></script>
      <script src="/sites/all/libraries/video-js_v5/videojs-contrib-hls.min.js"></script>
      
      <video id=live-video width=600 height=300 class="video-js" controls >
        <!--<source-->
        <!--   src="/PALS/DVR/live.m3u8"-->
        <!--   type="application/x-mpegURL"/>-->
      </video>
      
      <script>
      var player = videojs('live-video', {
        liveui: true,
        // fluid: false,
        // fill: false,
        responsive: true,
        autoplay:'muted',
        loop: true,
        preload: 'metadata',
        playbackRates: [0.5, 1, 1.5, 2]
       
      });
      
      player.src({type: 'application/x-mpegURL', src: '/PALS/DVR/live.m3u8'});
      
      // myPlayer.src([
      //   {type: 'video/mp4', src: 'http://www.example.com/path/to/video.mp4'},
      //   {type: 'video/webm', src: 'http://www.example.com/path/to/video.webm'},
      //   {type: 'video/ogg', src: 'http://www.example.com/path/to/video.ogv'}
      // ]);
      // set
      // player.poster('/sites/all/libraries/projekktor/theme/maccaco.png');
      
      // get
      // console.log(player.poster());
      // 'http://example.com/myImage.jpg'
      player.addClass('vjs-matrix');
      
      player.ready(function() {
        // example 0.11 aka 11%
        var howMuchIsDownloaded = player.bufferedPercent();
        
        player.play();
        player.pause();
       
        // get
        var howLoudIsIt = player.volume();
        // set
        player.volume(0.5); // Set volume to half
       
        // get, should be false
        console.log(player.muted());
        // set to true
        player.muted(true);
        // get should be true
        console.log(player.muted());
       
        // duration will give you the total duration of the video that is playing
        var lengthOfVideo = player.duration();
       
        // get the current time, should be 120 seconds
        var whereYouAt = player.currentTime();
       
        // should be 10 seconds less than duration
         console.log(player.remainingTime());
         
      });
      
      
      // modal.on('show', function() {
      //   var videoEl = modal.findEl('video');
      //   modal.player = videojs(videoEl);
      // });
      
      // modal.on('hide', function() {
      //   modal.player.dispose();
      // });
      
      player.on('ended', function() {
        this.dispose();
      });
      </script>

    11. Streaming through MediaElement:
      HTML:
      <link rel="stylesheet" href="/sites/all/libraries/mediaelement/build/mediaelementplayer.css">
      <link rel="stylesheet" href="/sites/all/libraries/mediaelement/build/speed.min.css">
      <link rel="stylesheet" href="/sites/all/libraries/mediaelement/build/snapshot.min.css">
      
          <style type="text/css">        
          </style>
      
          <div id="container">
               <section>
                  <form action="#" method="get">
                      <label>Language <select name="lang">
                          <option value="en" selected>English (en)</option>
                          <option value="ko">한국어 / Korean (ko)</option>
                          <option value="ru">Русский / Russian (ru)</option>
                      </select>
                      </label>
                      <label>Stretching (Video Only)<select name="stretching">
                          <option value="auto" selected>Auto (default)</option>
                          <option value="responsive">Responsive</option>
                          <option value="fill" selected>Fill</option>
                          <option value="none" selected>None (original dimensions)</option>
                      </select>
                      </label>
                  </form>
              </section>
      
              <br>
              <div class="players" id="player1-container">
      
                  <div class="media-wrapper">
                      <video id="player_mediaelement" width="640" height="360" style="max-width:100%;" poster="" preload="none" controls playsinline webkit-playsinline loop="true">
                          <source src="/PALS/DVR/live.m3u8" type="application/x-mpegURL">
                          
                      </video>
                  </div>
                
              </div>
      
              <br>
              <hr>
              
          </div>
      
          <script src="/sites/all/libraries/mediaelement/build/mediaelement-and-player.js"></script>
          <script src="/sites/all/libraries/mediaelement/build/speed.min.js"></script>
      <script src="/sites/all/libraries/mediaelement/build/speed-i18n.min.js"></script>
      <script src="/sites/all/libraries/mediaelement/build/snapshot.min.js"></script>
          <script src="/sites/all/libraries/mediaelement/build/lang/ko.js"></script>
          <script src="/sites/all/libraries/mediaelement/build/lang/ru.js"></script>
      
          <!--<script src="/sites/all/libraries/mediaelement/demo/demo.js"></script>-->
      
      <script type="text/javascript">
      var player = new MediaElementPlayer('player_mediaelement', {
              defaultSpeed: 0.75,              
       });
          
          function getQueryStringValue (key) {
          return decodeURIComponent(window.location.search.replace(new RegExp("^(?:.*[&\\?]" + encodeURIComponent(key).replace(/[\.\+\*]/g, "\\$&") + "(?:\\=([^&]*))?)?.*$", "i"), "$1"));
      }
      
      // borrowed from https://gist.github.com/niyazpk/f8ac616f181f6042d1e0
      function updateUrlParameter (uri, key, value) {
          // remove the hash part before operating on the uri
          var
              i = uri.indexOf('#'),
              hash = i === -1 ? '' : uri.substr(i)
              ;
      
          uri = i === -1 ? uri : uri.substr(0, i);
      
          var
              re = new RegExp("([?&])" + key + "=.*?(&|$)", "i"),
              separator = uri.indexOf('?') !== -1 ? "&" : "?"
              ;
      
          if (!value) {
              // remove key-value pair if value is empty
              uri = uri.replace(new RegExp("([?&]?)" + key + "=[^&]*", "i"), '');
      
              if (uri.slice(-1) === '?') {
                  uri = uri.slice(0, -1);
              }
              // replace first occurrence of & by ? if no ? is present
      
              if (uri.indexOf('?') === -1) {
                  uri = uri.replace(/&/, '?');
              }
      
          } else if (uri.match(re)) {
              uri = uri.replace(re, '$1' + key + "=" + value + '$2');
          } else {
              uri = uri + separator + key + "=" + value;
          }
          return uri + hash;
      }
      
      var
          lang = getQueryStringValue('lang') || 'en',
          stretching = getQueryStringValue('stretching') || 'auto',
          languageSelector = document.querySelector('select[name=lang]'),
          stretchingSelector = document.querySelector('select[name=stretching]'),
          sourcesSelector = document.querySelectorAll('select[name=sources]'),
          sourcesTotal = sourcesSelector.length
      ;
      
      languageSelector.value = lang;
      languageSelector.addEventListener('change', function () {
          window.location.href = updateUrlParameter(window.location.href, 'lang', languageSelector.value);
      });
      stretchingSelector.value = stretching;
      stretchingSelector.addEventListener('change', function () {
          window.location.href = updateUrlParameter(window.location.href, 'stretching', stretchingSelector.value);
      });        
      </script>
     

Share This Page