视频直播流媒体服务器的http-flv是如何直播的?
我们的流媒体服务器可以输出三种格式的视频流,Http-Flv 就是 http+flv ,将音视频数据封装成FLV格式,然后通过 HTTP 协议传输给客户端。相较于 RTMP 协议,HTTP-FLV 能够好的穿透防火墙,它是基于 HTTP/80 传输,有效避免被防火墙拦截。那么本篇的问题就来了,http-flv是如何直播的?
这里我们主要研究HTTP-FLV和HLS。主流的几个web直播平台几乎都是以HTTP-FLV为主来直播的,首先我们都知道在媒体格式里,几乎都以H264视频编码为主。如今HTTP-FLV直播的FLV数据也都是H264&AAC为主的。FLV封装单元是以tag来表示的,一个tag可以是音频tag或者视频tag,或者脚本tag及其其他类型。
值得注意的是flv里面字节序是网络字节序:
flv的格式
1 flvheader+[脚本tag(metadata)]+[第一个视频tag(h264_spspps)]+[第一个音频tag(aac_header)]+[第二个视频tag(h264第一个关键帧)]+ 后面就是音频和视频tag交互存在
tag的格式
1 TYPE[1byte] + body size[3byte] + timestamp [4byte] +streamID [3byte] +[body data]+[previousTagSize 4byte]
这里的timestamp是这样存在的[ time tamp 3b,time tamp ex 1b]
h264视频tagbody
这里存储的h264是没有nal分割符的,在t的body里面是这样存储的,
[isKeyFrame(1byte)]+0x01+[compositionTime 3byte]+[h264 size 4byte]
compositionTime是h264编码结果dts和pts之间的偏移。
aac视频tag的body:
0xaf+0x01+aac raw
以上就是flv格式的详细说明,可以看出格式简单,封装的前后数据关联很小,当我们得到音频头和视频头,就可以从后面任意的一个关键帧开始播放。
当然想要HTTP-FLV正常播放,不能缺少matedata,就是第一个脚本tag里面,这里面指定了分辨率,音视频编码格式等。
HTTP-FLV直播实际上单纯就是往客户端发送flvtag,当然是先发送flv前面那几个关键的tag,然后第一帧是关键帧。
假如客户端是obs推流软件,以rtmp方式向服务器推流,在开始握手及其创建stream完成以及发送Metadata完成,及其一系列数据发送完毕,服务器就向obs发送publish result指令,此后,obs就开始向服务器推送flv tag数据,开始直播,而服务器也得到了flv数据。
当某个客户端想要来获取直播数据,比如httpflv的方式来观看直播,服务器会怎么做呢?
服务器会先发送前面几个flvtag,header+metadata+spspps+aacheader,当这几个tag发送完毕,服务器会从直播流tag中,找到最新的视频关键帧tag,从这个关键帧tag开发数据,为什么呢?因为视频流是IBP帧相互存在的,I是完整数据,BP解码都需要I帧和前面的帧,所以,正常视频数据,必须是从I帧开始发送的。这里就涉及到gop间距了,rtmp低延时秒开就是这个原理。当然发送的时候,每个连接的tag开始时间戳要从0开始递增的。
至此,http-flv客户端就可以接收到flv流数据,解码观看直播了。