close

引用網址:http://mindwatering.com/SupportRef.nsf/webpg/4172DB1EF37041FE852580D50067E487

Category: Linux 
Installation
 
Primary Intent:
Set-up a small Streaming server to do both Live and VOD sessions.

Second Intent:
Record the files as they are streamed live so they are available for VOD afterwards w/o having to manually covert and FTP to server.

Third Intent:
Have multi-bitrate streaming for VOD and Live for slower connections/"bad Internet days". (Partially delivered.)


Steps:

A. OS Installation:

Installed Ubuntu 16.04 server from ISO:
- ubuntu-16.04.1-server-amd64.iso

Created new VM, w/200 GB disk space, and 3GB RAM.

Updated Settings, to choose to boot into CMOS next restart.
- In CMOS, updated boot order so that CDROM was above Hard-drive. Saved and Exited (F10).

Upon reboot, set CDROM to point to Ubuntu ISO. Sent Cntl-Alt-Del, walked to through prompts.
- Changed set-up to not use LVM, but still Use all disk (easier for older gpartd to increase disk space).
- For software selection, left general utilities checked, added check for the checkbox for SSH server, and left all other server services unchecked. (Don't select Apache.)


B. System Configuration:

Check for system updates:
$ sudo update
<enter password>
$ sudo upgrade

Make IP Update:
Set any permanent IP, as needed.
$ sudo vi /etc/network/interfaces
<make updates>
$ sudo service networking restart

Verify VM Tools Installed:
If open-vm-tools is not installed, install it. (Since 14, this has been detected and installed "automatically" as part of those system tools/utilities.
$ sudo apt-get install open-vm-tools

B. Set-up the UFW Firewall 
We want the following ports available:
22 LIMIT Anywhere
80 ALLOW Anywhere
22 (v6) LIMIT Anywhere (v6)
80 (v6) ALLOW Anywhere (v6)

We limit port 22 (SSH) so that only our local networks have SSH access.
# sudo su
<enter password>
# ufw allow proto tcp to any port 22 from 192.168.n.0/24
# ufw allow proto tcp to any port 22 from 10.0.5.0/255
# ufw allow proto tcp to any port 80


B. Install Prerequisites:
Remote Into server via SSH. (So I can paste commands rather than hand-typing into the console.)
# apt-get install build-essential zlib1g-dev libpcre3-dev libssl-dev libxslt1-dev libxml2-dev libgd2-xpm-dev libgeoip-dev libgoogle-perftools-dev libperl-dev make git gcc automake aclocal pkg-config
# apt-get install unzip libavcodec-ffmpeg56 libavfilter-ffmpeg56
(or you can install libavcodec-extra and libavfilter-extra - neither seem to get thumbnails in the vod - at this writing, still researching this issue. )

Install GeoIP libraries/databases:
# apt-get install libgeoip-dev

Find install location:
# dpkg -L libgeoip-dev

Note: 
I left the stock nginx.conf variable set-up as:
geoip_country /usr/share/GeoIP/GeoIP.dat;


C. Install NGINX.
Download nginx (core), nginx-rtmp, and nginx-vod.
$ mkdir /home/myadminid/working/
$ cd /home/myadminid/working/
$ wget http://nginx.org/download/nginx-versionidnumbers.tar.gz
$ wget http://nginx.org/download/nginx-rtmp-module-master.zip
$ wget http://nginx.org/download/nginx-vod-module-master.zip

Download the external modules from their respective sites below. Visit the links below in a web browser, and use the Download button to download, or you can clone via git.
https://github.com/vozlt/nginx-module-vts --> nginx-module-vts-master.zip
https://github.com/vozlt/nginx-module-sts --> nginx-module-sts-master.zip
https://github.com/vozlt/nginx-module-stream-sts --> nginx-module-stream-sts-master.zip

#./configure --add-module=/home/myadminid/working/nginx-rtmp-module-master --add-module=/home/myadminid/working/nginx-vod-module-master --with-file-aio --with-threads --with-cc-opt='-O3' --with-http_ssl_module --prefix=/usr/local/nginx --with-http_stub_status_module --add-module=/home/myadminid/working/nginx-module-vts-master
# make
# make install

Copy the stat.xsl to the html folder
# cp /home/myadminid/working/nginx-rtmp-module-master/stat.xsl /usr/local/nginx/html/

# service nginx start
(Watch for errors. If they are no run-time errors, nothing will be displayed but the prompt. Use journalctl -xe to view errors. )

Verify running:
# netstat -nap | grep nginx
(If nothing is returned, it's not running.)


D. Set-up Confirm for Streaming:
At this point, you create streams for your needs. In our case, we want to create MP4s during the live stream so we can use them for VOD.
Create the directories for the locations/roots of the nginx.conf file. Update the nginx.conf file to use those locations.
# vi /usr/local/nginx/conf/nginx.conf



Sample nginx.conf:
____________________________________________________________________

worker_processes auto;
error_log logs/error.log debug;
events {
worker_connections 1024;
}
rtmp {
server {
listen 1935;
allow play all;
chunk_size 4000;

#hls - "live" full-resolution HLS videostream from our incoming encoder stream and tells where to put the HLS video manifest and video fragments
application live {
allow play all;
live on;
meta on;
record all;
record_path /video_recordings;
record_unique off;
hls on;
hls_nested on;
hls_path /HLS/live;
hls_fragment 10s;
hls_type live;
allow publish 127.0.0.1;
allow publish 192.168.2.0/24;
allow publish 192.168.22.0/24;
allow publish 70.62.116.192/27;
deny publish all;
# create the sampled HLS streams
# 240p - low def 288kbps / 480p standard def 448kbps / 720p hi def at 2048kbps / source
# create 3 other stored HLS variants in vod
exec ffmpeg -i rtmp://localhost:1935/$app/$name
-c:v libx264 -acodec copy -b:v 256k -vf "scale=480:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -g 60 -hls_list_size 0 -f flv rtmp://localhost:1935/savehls/$name_low
-c:v libx264 -acodec copy -b:v 768k -vf "scale=720:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -g 60 -hls_list_size 0 -f flv rtmp://localhost:1935/savehls/$name_mid
-c:v libx264 -acodec copy -b:v 1920k -vf "scale=1080:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -g 60 -hls_list_size 0 -f flv rtmp://localhost:1935/savehls/$name_high;

# create local mp4 archive
exec ffmpeg -i rtmp://localhost:1935/$app/$name -c:v libx264 -vprofile baseline -acodec aac -strict -2 -f mp4 /video_recordings/$name.mp4;
# exec ffmpeg -y -i $path -c:v libx264 -vprofile baseline -acodec aac -strict -2 -f mp4 $dirname/$name.mp4;
}

# hls converted streams
# - streams for mobile live and archives the HLS video manifest and video fragments
application savehls {
allow play all;
live on;
hls on;
hls_nested on;
hls_path /HLS/streams;
hls_fragment 10s;
hls_variant _low BANDWIDTH=288000; # Low bitrate, sub-SD resolution
hls_variant _mid BANDWIDTH=448000; # Medium bitrate, SD resolution
hls_variant _high BANDWIDTH=2048000; # High bitrate, HD 720p resolution
# turn off clean-up, if we want these to stay
# - note: the ts files will only have the last 5 seconds or so of ts files. so doing this is of limited help
hls_cleanup on;
}

#allows you to play your recordings of your live streams using a URL like "rtmp://my-ip:1935/vod/filename.flv"
application vod {
play /video_recordings;
}


}
}

http {
include /usr/local/nginx/conf/mime.types;
sendfile off;
tcp_nopush on;
directio 512;
# geoip variables/filters
geoip_country /usr/share/GeoIP/GeoIP.dat;
vhost_traffic_status_zone;
map $http_user_agent $filter_user_agent {
default 'unknown';
~iPhone ios;
~Android android;
~(MSIE|Mozilla) windows;
}
vhost_traffic_status_filter_by_set_key $filter_user_agent agent::*;
vhost_traffic_status_filter_by_set_key $geoip_country_code country::*;

server {
listen 80;
server_name 70.62.116.196;

# stats variables
vhost_traffic_status_filter_by_set_key $geoip_country_code country::$server_name;
vhost_traffic_status_filter_by_set_key $filter_user_agent agent::$server_name;

# vod caches
vod_metadata_cache metadata_cache 2048m;
vod_response_cache response_cache 128m;

# vod variables
open_file_cache max=1000 inactive=5m;
open_file_cache_valid 2m;
open_file_cache_min_uses 1;
open_file_cache_errors on;
aio on;
# vod share
location /vodhls/ {
vod hls;
vod_mode local;
vod_align_segments_to_key_frames on;
alias /video_recordings/;
gzip on;
gzip_types application/vnd.apple.mpegurl;
vod_last_modified_types *;
add_header Access-Control-Allow-Headers 'origin,range,accept-encoding,referrer';
add_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';
add_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';
add_header Access-Control-Allow-Origin '*';
expires 100d;
add_header Last-Modified "Sun, 19 Nov 2000 08:52:00 GMT";
}

# hls - http-location for full-resolution desktops
# - "http://my-ip/live/my-stream-key/index.m3u8"
location /live {
default_type application/octet-stream;
types {
application/dash+xml mpd;
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}

alias /HLS/live;
# disable cache and add CORS headers
add_header Cache-Control no-cache;
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
add_header 'Access-Control-Allow-Headers' 'Range';

# allow CORS preflight requests
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Headers' 'Range';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}

# HLS - create the http-location for mobile-device live streams and hls stream archives
# - "http://my-ip/mobile/my-stream-key/index.m3u8"
location /streams {
types {
application/dash+xml mpd;
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
alias /HLS/streams;
add_header Cache-Control no-cache;
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
add_header 'Access-Control-Allow-Headers' 'Range';
}

# creates http access to vod folder
location /vod {
alias /video_recordings;
index index.html;
add_header Cache-Control no-cache;
include /usr/local/nginx/conf/mime.types;
}

#allows us to see how stats on viewers on our Nginx site using a URL like: "http://my-ip/stats"
location /mwstats {
rtmp_stat all;
rtmp_stat_stylesheet /stat.xsl;
stub_status;
access_log off;
}

location /vod_status {
vod_status;
access_log off;
}

location /mwhoststats {
vhost_traffic_status_display;
vhost_traffic_status_display_format html;
}

#allows us to host some webpages which can show our videos: "http://my-ip/my-page.html"
location / {
default_type text/html;
include /usr/local/nginx/conf/mime.types;
include /usr/local/nginx/conf/cors.conf;
root html;
index index.html index.htm;

}

}
}


____________________________________________________________________




Sample VOD stream.html file:
____________________________________________________________________

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>MW SMS Livestream | HTML5 Video Player</title>
<link type="text/css" href="/videojs/video-js.min.css" rel="stylesheet" />
<script src="/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="/videojs/video.min.js"></script>
<script type="text/javascript" src="/videojs/videojs-contrib-hls.min.js"></script>

<script type='text/javascript'>
function getParmByNm(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}

</script>

<script type="text/javascript">
var w = 0 + getParmByNm('w','');
var h = 0 + getParmByNm('h','');
if (w == null ) {
w = 475;
}
if (h == null ) {
h = 264;
}
// video.js flash failover
videojs.options.flash.swf = "/videojs/video-js.swf";
// initilize player
(function ($) {
$(document).ready(function () {
// update div default size to passed variables
$("mwdiv").css("width", w + "px");
$("mwdiv").css("height", h + "px");
// add videojs object
videojs('video1', {techOrder:['flash','html5'], height:'264', width:'475'} ).ready(function () {
var myPlayer = this;
myPlayer.pause();
myPlayer.src([
{type:"video/flv", src:"http://" + window.location.hostname + "/vod/" + getParmByNm('f', '') + ".flv"},
{type:"application/x-mpegurl", src:"http://" + window.location.hostname + "/vodhls/" + getParmByNm('f', '') + ".mp4/index.m3u8"},
]);
$("#video1 > source").attr("src", "http://" + window.location.hostname + "/vod/" + getParmByNm('f', '') + ".flv" );
$("#video1 > source").attr("src", "http://" + window.location.hostname + "/vodhls/" + getParmByNm('f', '') + ".mp4/index.m3u8" );
myPlayer.load(); 
myPlayer.volume(0.8);
myPlayer.width( w );
myPlayer.height( h );
});

});
})(jQuery);

</script> 

</head>
<body>
<div id="mwdiv" class="" role="application" aria-label="media player">
<video id="video1" class="video-js vjs-default-skin" preload="auto"
controls width="475" height="264"
poster="NBAudioPic.jpg">
<source src="" type="video/flv"></source>
<source src="" type="application/x-mpegurl"></source>
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video.</p>
</video>

</div>

</body>

</html>

____________________________________________________________________




Sample live streaming.html file:
____________________________________________________________________

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>MW Stream | HTML5 Video Player</title>
<link type="text/css" href="/videojs/video-js.min.css" rel="stylesheet" />
<script src="/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="/videojs/video.min.js"></script>
<script type="text/javascript" src="/videojs/videojs-contrib-hls.min.js"></script>

<script type='text/javascript'>
function getParmByNm(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}

function changeVideo(){
myPlayer.pause();
myPlayer.src([
{type:"video/mp4", src:"http://" + window.location.hostname + "/vod/" + getParmByNm('f', '') + ".mp4"},
{"type":"application/x-mpegurl", "src":"http://" + window.location.hostname + "/streams/" + getParmByNm('f', '') + "index.m3u8"}
]);
myPlayer.load();
myPlayer.play();
}

</script>

<script type="text/javascript">
var w = getParmByNm('w','');
var h = getParmByNm('h','');
if (w == null) {
w = 475;
}
if (h == null) {
h = 264;
}
// video.js flash failover
videojs.options.flash.swf = "/videojs/video-js.swf";
// initilize player
(function ($) {
$(document).ready(function () {
// update div default size to passed variables
$("mwdiv").css("width", w + "px");
$("mwdiv").css("height", h + "px");
videojs('video1', {techOrder:['flash','html5'], height: '264', width: '475'} ).ready(function () {
var myPlayer = this;
myPlayer.pause();
myPlayer.src([
{type:"video/flv", src:"http://" + window.location.hostname + "/vod/" + getParmByNm('f', '') + ".flv"},
{type:"application/x-mpegurl", src:"http://" + window.location.hostname + "/streams/" + getParmByNm('f', '') + ".m3u8"}
]);
$("#video1 > source").attr("src", "http://" + window.location.hostname + "/vod/" + getParmByNm('f', '') + ".flv" );
$("#video1 > source").attr("src", "http://" + window.location.hostname + "/streams/" + getParmByNm('f', '') + ".m3u8" );
myPlayer.load(); 
// reset video width - fluid not working
myPlayer.width(w);
myPlayer.height(h);
});


});
})(jQuery);

</script> 

</head>

<body>
<div id="mwdiv" class="" role="application" aria-label="media player">
<video id="video1" class="video-js vjs-default-skin" preload="auto"
controls width="475" height="264"
poster="NBAudioPic.jpg">
<source src="" type="video/flv"></source>
<source src="" type="application/x-mpegurl"></source>
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video.</p>
</video>

</div>

</body>

</html>
arrow
arrow
    文章標籤
    nginx
    全站熱搜

    龍之家族 發表在 痞客邦 留言(0) 人氣()