1.首先介绍一下HLS协议:
(1)简介
这个协议是由苹果公司提出并推广使用的,维基百科介绍如下:
HTTP Live Streaming(缩写是HLS)是一个由苹果公司提出的基于HTTP的流媒体网络传输协议。是苹果公司QuickTime X和iPhone软件系统的一部分。
它的工作原理是把整个流分成一个个小的基于HTTP的文件来下载,每次只下载一些。当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,
允许流媒体会话适应不同的数据速率。在开始一个流媒体会话时,客户端会下载一个包含元数据的extended M3U (m3u8)playlist文件,用于寻找可用的媒体流。
HLS只请求基本的HTTP报文,与实时传输协议(RTP)不同,HLS可以穿过任何允许HTTP数据通过的防火墙或者代理服务器。它也很容易使用内容分发网络来传输媒体流。
苹果公司把HLS协议作为一个互联网草案(逐步提交),在第一阶段中已作为一个非正式的标准提交到IETF。但是,即使苹果偶尔地提交一些小的更新,
IETF却没有关于制定此标准的有关进一步的动作。[1]
(2)HLS协议相对与RTMP协议的优势与劣势
优势:
-------1.相较于RTMP协议,HLS不会遇到被防火墙屏蔽的情况(基于http的),RTMP协议不使用标准的Http接口传输数据,所以在特殊情况下可能被防火墙屏蔽掉;
-------2.对于负载均衡,HLS比RTMP更加容易扩展,因为RTMP是一种有状态协议,需要为每一个播放视频流的客户维持状态,而HLS客户端播放下载TS文件,就跟下载普通文件一样,做负载均衡HLS更简单;
-------3.HLS协议本身实现了码率自适应,不同带宽的设备可以自动切换到最适合自己码率的视频播放。
劣势:
如果是做直播的话,使用HLS会存在比较大的延时(10s以上),而RTMP协议的延迟可以降低了3、4秒,所以对于实时性要求比较高的直播需要慎重考虑HLS存在的问题。
(苹果官网图)
(3)再来看一下m3u8文件,这个文件就是一个索引文件
(苹果官网图)
(4)播放模式
-
点播VOD的特点就是当前时间点可以获取到所有index文件和ts文件,二级index文件中记录了所有ts文件的地址。这种模式允许客户端访问全部内容。
-
Live 模式就是实时生成M3u8和ts文件。它的索引文件一直处于动态变化的,播放的时候需要不断下载二级index文件,以获得最新生成的ts文件播放视频。如果一个二级index文件的末尾没有#EXT-X-ENDLIST标志,说明它是一个Live视频流。
以上参考:https://www.jianshu.com/p/2ce402a485ca
2.安装相关软件
(1)执行如下指令(ubuntu系列)
apt-get install -y
libpcre3-dev
libssl-dev
libav-tools
libavcodec-extra
ffmpeg
(2)使用源码编译安装nginx(使用源码编译安装的目的是添加后面的功能模块),并添加(nginx-rtmp-module和
http_ssl_module两个模块
)
cd /path/to/nginx
./configure --add-module=/path/to/nginx-rtmp-module --with-http_ssl_module
make & make install
(3)基本配置
user www-data;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
rtmp {
server{
listen 1935;
chunk_size 4096;
application vod {
play /var/nginx_upload;
}
application live{
live on;
}
application hls {
live on;
hls on;
hls_path /var/hls/video;
hls_sync 200ms;
hls_fragment 10s;
#hls_cleanup off;
hls_fragment_naming system;
#hls_fragment_slicing aligned;
#hls_continuous on;
hls_type live;
hls_playlist_length 99999m;
hls_nested on;
hls_keys on;
hls_key_path /var/hls/video/keys;
hls_key_url http://121.201.116.242/hls/video/keys/;
hls_fragments_per_key 2;
}
}
}
http {
include mime.types;
default_type application/octet-stream;
client_max_body_size 3000m;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 256k;
fastcgi_buffers 2 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
add_header Access-Control-Allow-Origin "http://weibo.duoyioa.com";
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 300;
#gzip on;
server {
client_max_body_size 3000m;
client_body_buffer_size 400m;
listen 80;
listen 443 ssl;
ssl_certificate /usr/local/nginx/ssl/duoyioa.cer;
ssl_certificate_key /usr/local/nginx/ssl/duoyioa.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Upload form should be submitted to this location
location /upload {
# Pass altered request body to this location
upload_pass @python;
# Store files to this directory
# The directory is hashed, subdirectories 0 1 2 3 4 5 6 7 8 9 should exist
upload_store /var 1;
# Allow uploaded files to be read only by user
upload_store_access user:rw;
# Set specified fields in request body
upload_set_form_field $upload_field_name.name "$upload_file_name";
upload_set_form_field $upload_field_name.content_type "$upload_content_type";
upload_set_form_field $upload_field_name.path "$upload_tmp_path";
# Inform backend about hash and size of a file
upload_aggregate_form_field "$upload_field_name.md5" "$upload_file_md5";
upload_aggregate_form_field "$upload_field_name.size" "$upload_file_size";
upload_pass_form_field "^submit$|^description$";
upload_cleanup 400 404 499 500-505;
upload_limit_rate 0;
upload_max_file_size 3000m;
client_max_body_size 3000m;
}
error_page 405 =200 @405;
location @405 {
return 200;
}
# Pass altered request body to a backend
location @python {
proxy_read_timeout 3000;
proxy_connect_timeout 3000;
proxy_pass http://121.201.116.242:9999;
#return 200;
}
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
video/mp4 f4p f4v m4v mp4;
image/bmp bmp;
image/gif gif;
image/jpeg jpeg jpg;
image/png png;
image/svg+xml svg svgz;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/webp webp;
image/x-jng jng;
}
root /var;
add_header Cache-Control no-cache;
add_header Access-Control-Allow-Origin *;
}
}
}
(3)使用ffmpeg推流生成m3u8和ts文件,脚本如下:
serverName="121.201.116.242:1935"
basePath="/var/hls/video/"
filePath="/var"
HLSPath="/hls/video/"
CUTPATH="121.201.116.242:1935/hls/"
if [ ! -d "$filePath$HLSPath$2" ] && [ ! -f "$filePath$HLSPath$2/index.m3u8" ];then
ffmpeg -re -i $basePath$1/$2.mp4 -vcodec copy -vprofile baseline -acodec copy -f flv rtmp://$CUTPATH$2
sleep 10
echo "#EXT-X-ENDLIST" >> $filePath$HLSPath$2/index.m3u8
else
echo "$filePath$HLSPath$2 OR $filePath$HLSPath$3/index.m3u8 is already exist."
fi
echo "$filePath$HLSPath$2/index.m3u8"