前言
传统的直播协议要么使用 Adobe 的基于 TCP 的 RTMP 协议, 要么使用 Apple 的基于 HTTP 的 HLS 协议。本文介绍另外一种结合了 RTMP 的低延时, 以及可以复用现有 HTTP 分发资源的流式协议 HTTP-FLV。
一、HTTP-FLV 简介
HTTP-FLV,即将音视频数据封装成 FLV,然后通过 HTTP 协议传输给客户端。
HLS 其实是一个 “文本协议” ,而并非流媒体协议,(ts0,ts1,…)。 那么,什么样的协议才能称之为流媒体协议呢?
答:流(stream):数据在网络上按时间先后次序传输和播放的连续音/视频数据流。之所以可以按照顺序传输和播放连续是因为在类似 RTMP、FLV 协议中,每一个音视频数据都被封装成了包含时间戳信息头的数据包。而当播放器拿到这些数据包解包的时候能够根据时间戳信息把这些音视频数据和之前到达的音视频数据连续起来播放。
MP4、MKV 等等类似这种封装,必须拿到完整的音视频文件才能播放,因为里面的单个音视频数据块不带有时间戳信息,播放器不能将这些没有时间戳信息数据块连续起来,所以就不能实时的解码播放。
1、市场上使用 http-flv 的商家
优酷的 pc 网页直播,斗鱼、 熊猫 tv、 虎牙 pc 网页上也使用了 http-flv
2、http-flv、rtmp 和 hls 直播的优缺点
- 三者的延迟性
- http-flv:低延迟,内容延迟可以做到 2-5 秒;
- Rtmp:低延迟,内容延迟可以做到 2-5 秒。
- Hls:延迟较高(ts0,segment-time:5,10s)。
- 三者的易用性
- rtmp 和 http-flv:播放端安装率高。只要浏览器支持 FlashPlayer 就能非常简易的播放。
- hls:最大的优点:HTML5 可以直接打开播放;这个意味着可以把一个直播链接通过微信等转发分享,不需要安装任何独立的 APP,有浏览器即可。
- rtmp 和 http-flv 比较
- 穿墙:很多防火墙会墙掉 RTMP,但是不会墙 HTTP,因此 HTTP FLV 出现奇怪问题的概率很小。
- 调度:RTMP 也有个 302,可惜是播放器 as 中支持的,HTTP FLV 流就支持 302 方便 CDN 纠正 DNS 的错误。
- 容错:SRS 的 HTTP FLV 回源时可以回多个,和 RTMP 一样,可以支持多级热备。
- 简单:FLV 是最简单的流媒体封装,HTTP 是最广泛的协议,这两个组合在一起维护性更高,比 RTMP 简单多了。
3、http-flv 技术实现
HTTP 协议中有个约定:content-length 字段,http 的 body 部分的长度。
- 服务器回复 http 请求的时候如果有这个字段,客户端就接收这个长度的数据然后就认为数据传输完成了。
- 如果服务器回复 http 请求中没有这个字段,客户端就一直接收数据,直到服务器跟客户端的 socket 连接断开。 (流式传输)
http-flv 直播就是利用第二个原理,服务器回复客户端请求的时候不加 content-length 字段,在回复了 http 内容之后,紧接着发送 flv 数据,客户端就一直接收数据了。
二、Nginx 配置 http-flv
1、Windows 安装 nginx,已经集成 nginx-http-flv-module
RTMP 服务器:Nginx+rtmp(windows)的环境搭建如有需要可自取:
链接:https://pan.baidu.com/s/1AcIVERWUPbJL1zu8yCcAzw
提取码:mtdf
2、nginx.conf 配置文件
nginx.conf 配置文件如下:
worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #error_log logs/error.log debug; #pid logs/nginx.pid; events { worker_connections 1024; } # 添加RTMP服务 rtmp { server { listen 1935; # 监听端口 chunk_size 4000; application live { live on; gop_cache on; hls on; hls_path html/hls; } } } # HTTP服务 http { include mime.types; default_type application/octet-stream; #access_log logs/access.log main; server { listen 8080; # 监听端口 location /flv { flv_live on; chunked_transfer_encoding on; add_header 'Access-Control-Allow-Origin' '*'; add_header "Access-Control-Allow-Credentials" "true"; add_header "Access-Control-Allow-Methods" "*"; add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token"; add_header "Access-Control-Expose-Headers" "*"; } location /stat.xsl { root html; } location /stat { rtmp_stat all; rtmp_stat_stylesheet stat.xsl; } location / { root html; } } }
其中涉及到跨域问题:#http-flv
location /flv { flv_live on; chunked_transfer_encoding on; add_header 'Access-Control-Allow-Origin' '*'; add_header "Access-Control-Allow-Credentials" "true"; add_header "Access-Control-Allow-Methods" "*"; add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token"; add_header "Access-Control-Expose-Headers" "*"; }
3、运行 nginx 服务器
双击 nginx8080.exe
在任务管理器可以看到目前 nginx 已开始工作
4、ffmpeg 推流
ffmpeg -re -i SampleVideo_1280x720_20mb.mp4 -vcodec libx264 -acodec aac -f flv -y rtmp://127.0.0.1:1935/live/test1 • 1
这个命令使用 FFmpeg 工具来将输入视频文件 SampleVideo_1280x720_20mb.mp4 转换为 FLV 格式并通过 RTMP 协议流式传输到指定的 URL 地址 rtmp://127.0.0.1:1935/live/test1;
-re
:以实时模式(real-time)读取输入文件,模拟实时流传输的速度。-i SampleVideo_1280x720_20mb.mp4
:指定输入文件名为 SampleVideo_1280x720_20mb.mp4。-vcodec libx264
:选择 H.264 编码器作为视频编码器;-acodec aac
:选择 AAC 编码器作为音频编码器;-f flv
:指定输出格式为FLV(Flash Video);-y
:自动覆盖输出文件,如果存在同名文件则会被替换;rtmp://127.0.0.1:1935/live/test1
:指定输出的 URL 地址,以 RTMP 协议传输到 192.168.36.176 服务器的 1935 端口的 live 应用程序中的 test1 流
5、VLC 播放
- http-flv:
http://localhost:8080/flv?port=1935&app=live&stream=test1
对应关系如下:
VLC 进行拉流
- rtmp:
rtmp://127.0.0.1:1935/live/test1
- Hls:
http://localhost:8080/hls/test1.m3u8
此外,视频和音频内容分割为小的 TS 文件,并生成相应的 M3U8 文件,以便客户端能够获取和播放这些文件。M3U8 文件可以通过 HTTP 服务器提供给客户端,并使用流媒体播放器(如VLC、HLS播放器等)进行解析和播放。
这个目录是由 nginx.conf 配置文件决定的:
HTTP-FLV详解及分析(二)https://developer.aliyun.com/article/1472363