Plot: Required components - videorecorder (DVR-system); router with opened port for public connections to a DVR; web-server with FFMPEG installed software. 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 (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 chmod +x /REPOSITORY/DVR/stream.sh ln -s /REPOSITORY/DVR/dvr_stream.service /lib/systemd/system/dvr_stream.service systemctl enable dvr_stream.service systemctl start dvr_stream.service systemctl status dvr_stream.service Erasing staled data 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 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 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> 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>