FLV 和 HTTP-FLV

FLV

简介

FLV(Flash Video)是 Adobe 公司推出的一种媒体文件格式,是一种非常常见的音视频封装格式,尤其是在流媒体场景中。在直播领域,通常采用 RTMP 推流,HTTP-FLV 播放的方案。

FLV 由 FLV Header,FLV Body 组成,FLV Body 由 FLV Tag 组成,FLV Tag 由 FLV Tag Header 和 FLV Tag Body 组成。FLV Tag 分为 Video Tag、Audio Tag 和 Script Tag,分别用来存放视频数据、音频数据和 MetaData 数据。

FLV总体格式

FLV Header

FLV Header 占用 9 个字节。

  • 3 个字节是文件的标识,固定是 FLV。
  • 1 个字节表示版本
  • 1 个字节中的第 6 位表示是否存在音频数据,第 8 位表示是否存在视频数据,其他位为 0 。
  • 4 个字节表示 FLV Header 的大小。

直播场景中的 HTTP-FLV 播放必须首先发送 FLV Header 。

FLV Tag

FLV Tag 分为Script Tag、Video Tag 和 Audio Tag,分别用来存放 MetaData 数据、视频数据和音频数据。

FLV Tag

FLV Tag Header

Reserved ~ StreamID 为 Tag Header 字段,共 11 字节。

FLV Script Tag

ScriptTagBody

Script Tag Body

示例
直播场景中的 HTTP-FLV 播放在发送 Video Tag 和 Audio Tag 之前,需要先发送 MetaData 即 Script Tag , 主要包括宽、高、时长、采样率等基础信息。

Script Data 使用 2 个 AMF(Action Message Forma) 包来存放信息。

第一个 AMF 包是 onMetaData 包。第 1 个字节表示的是 AMF 包的类型,第一个 AMF 包一般是字符串类型,字符串类型的值表示是 0x02,之后是 2 字节表示的长度,一般长度总是 10,值是 0x000A,之后就是 10 字节长度字符串,值是 onMetaData 。

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      type     |              length           |                              
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                                onMetaData 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                   |
   +-+-+-+-+-+-+-+-+

第二个 AMF 包是一个 Objcet 类型的 AMF 包,Object 类型的值表示是 0x03,Objcet 元素为元素名称和值组成的对,常见的元素如下:

常见 meta 元素

winshining/nginx-http-flv-module 的 meta :

    static ngx_rtmp_amf_elt_t       out_inf[] = {

        { NGX_RTMP_AMF_STRING,
          ngx_string("Server"),
          "NGINX HTTP-FLV (https://github.com/winshining/nginx-http-flv-module)", 0 },

        { NGX_RTMP_AMF_NUMBER,
          ngx_string("width"),
          &v.width, 0 },

        { NGX_RTMP_AMF_NUMBER,
          ngx_string("height"),
          &v.height, 0 },

        { NGX_RTMP_AMF_NUMBER,
          ngx_string("displayWidth"),
          &v.width, 0 },

        { NGX_RTMP_AMF_NUMBER,
          ngx_string("displayHeight"),
          &v.height, 0 },

        { NGX_RTMP_AMF_NUMBER,
          ngx_string("duration"),
          &v.duration, 0 },

        { NGX_RTMP_AMF_NUMBER,
          ngx_string("framerate"),
          &v.frame_rate, 0 },

        { NGX_RTMP_AMF_NUMBER,
          ngx_string("fps"),
          &v.frame_rate, 0 },

        { NGX_RTMP_AMF_NUMBER,
          ngx_string("videodatarate"),
          &v.video_data_rate, 0 },

        { NGX_RTMP_AMF_NUMBER,
          ngx_string("videocodecid"),
          &v.video_codec_id, 0 },

        { NGX_RTMP_AMF_NUMBER,
          ngx_string("audiodatarate"),
          &v.audio_data_rate, 0 },

        { NGX_RTMP_AMF_NUMBER,
          ngx_string("audiocodecid"),
          &v.audio_codec_id, 0 },

        { NGX_RTMP_AMF_STRING,
          ngx_string("profile"),
          &v.profile, sizeof(v.profile) },

        { NGX_RTMP_AMF_STRING,
          ngx_string("level"),
          &v.level, sizeof(v.level) },
    };

    static ngx_rtmp_amf_elt_t       out_elts[] = {

        { NGX_RTMP_AMF_STRING,
          ngx_null_string,
          "onMetaData", 0 },

        { NGX_RTMP_AMF_OBJECT,
          ngx_null_string,
          out_inf, sizeof(out_inf) },
    };

FLV Tag Audio Header

FLV Tag Audio Header

特别说明:

  1. SoundFormat = 3, Linear PCM little endian,存储原始 PCM 样本。如果数据为 8 位,则样本为无符号字节。如果数据是 16 位,则样本存储为小端、有符号数字。如果数据是立体声,则左右样本交错存储:左-右-左-右-等等。
  2. SoundFormat = 0 的 PCM 与 SoundFormat = 3 的 PCM 区别:SoundFormat = 0 的 PCM 按创建文件的平台的字节序顺序存储 16 位 PCM 样本。
  3. SoundFormat = 5 的 Nellymoser 8 kHz 和 SoundFormat = 6 的 Nellymoser 16 kHz 是特殊情况,因为 SoundRate 字段不能表示 8 kHz 和 16 kHz 采样率。当在 SoundFormat 中指定 Nellymoser 8 kHz 或 Nellymoser 16 kHz 时,Flash Player 将忽略 SoundRate 和 SoundType 字段。对于其他 Nellymoser 采样率,请指定正常的 Nellymoser SoundFormat 并照常使用 SoundRate 和 SoundType 字段。
  4. 如果 SoundFormat = 10 指示 AAC,SoundType 应为 1 (立体声),SoundRate 应为 3(44kHz)。但是,这并不意味着 FLV 中的 AAC 音频总是立体声、44kHz。相反,Flash Player会忽略 SoundType 和 SoundRate,而是根据 AAC Audio Data 中的 AAC sequence header 提取通道(单/双通道)和采样率。
  5. 如果 SoundFormat = 11 指示 Speex,则音频是以 16 kHz 采样的压缩单声道,SoundRate 应为 0,SoundSize 应为 1,SoundType 应为 0 。

FLV Tag Audio Data

AudioData 包含音频有效载荷:

  1. 如果加密,则为 EncrytedBody
  2. 如果非加密,则为 AudioTagBody

AudioTagBody :

  1. 如果 SoundFormat == 10 (AAC),则为 AACAudioData
  2. 否则,因 SoundFormat 而异,通常是对应格式的 Raw audio frame data

AACAudioData :

  1. 如果 AACPacketType == 0,表示 AAC Header
  2. 如果 AACPacketType == 1,表示 AAC Raw audio frame data

在直播场景中,若使用 AAC 格式的音频,则通常需要首先发送 AAC Header(包含通道(单/双通道)、采样率等信息 ),再发送 AAC Raw audio frame data 。

FLV Tag Video Header

Tag Video Header

FLV Tag Video Data

VideoData 包含音频有效载荷:

  1. 如果加密,则为 EncrytedBody
  2. 如果非加密,则为 VideoTagBody

VideoTagBody :

  1. 如果 FrameType == 5,则 VideoTagBody 为 Video frame payload 或 frame info
  2. 否则
    2.1 如果 CodecId == 2,则 VideoTagBody 为 H263 Video Packet
    2.2 如果 CodecId == 3,则 VideoTagBody 为 Screen Video Packet
    2.3 如果 CodecId == 4,则 VideoTagBody 为 VP6 FLV Video Packet
    2.4 如果 CodecId == 5,则 VideoTagBody 为 VP6 FLV Alpha Video Packet
    2.5 如果 CodecId == 6,则 VideoTagBody 为 Screen V2 Video Packet
    2.6 如果 CodecId == 7,则 VideoTagBody 为 AVC Video Packet

AVC Video Packet :

  1. 如果 AVCPacketType == 0,表示 AVC sequence Header
  2. 如果 AVCPacketType == 1,表示 One or more NALUs (more 是因为 AVC slice,在 AVC 中)

在直播场景中,若使用 AVC 格式的视频,则通常需要首先发送 AVC sequence Header (包含解码信息等 ),再发送 NALUs 。

AVCPacketType == 0 时,AVCPacket 为 AVC sequence header。 AVC sequence header 是 AVCDecoderConfigurationRecord 结构(包含SPS、PPS等编码参数集),该结构在标准文档 ISO-14496-15 AVC file format 中有详细说明。

AVCPacketType == 1 时 AVCPacket 包含 1个 或 多个 NALU。一个 AVCPacket 应该包含一个 frame,但是在 H.264 的 VCL (视频编码层)中可能会将 frame 分成 slice,每个 slice 作为 RBSP 被封装在单独的 NALU 中,因此一个 AVCPacket 包含一个 frame 时可能需要包含多个 NALU (即多个 slice)。

FLV 中包含的 NALU 通常采用 AVCC 格式封装,AVCC在每个NALU前都加上一个大端格式的前缀(1、2、4 字节,通常采用 4 字节)代表NALU长度。

HTTP-FLV

HTTP-FLV 是将音视频数据以 FLV 文件格式进行封装,再将 FLV 格式数据封装在 HTTP 协议中进行传输的一种流媒体传输方式。

HTTP-FLV 被广泛采用的原因:

  1. HTTP 优点:
    a. 一些防火墙会墙掉 RTMP 或者其他的一些协议,但是防火墙对 HTTP 非常友好,不会墙掉 HTTP,因此基于 HTTP 传输的成功率更高。
  2. FLV 优点:
    a. MP4、MKV 等封装格式将音视频数据和音视频元数据、索引、时间戳等分开存放,必须拿到完整的音视频文件才能播放,因为里面的单个音视频数据块不带有时间戳信息,播放器不能将这些没有时间戳信息的数据块连续起来,因此不能实时的解码播放。(当然 MP4 后来扩展了 FMP4 用于流媒体)
    b. FLV 格式的 FLV Tag Header 中携带时间戳,FLV 将每一帧音视频数据(Tag Body)封装成包含时间戳等音视频元数据(Tag Header)的数据包(Tag)。当播放器拿到 Tag 后,可根据时间戳等音视频元数据进行解码和播放。

HTTP-FLV 的实现原理: HTTP-FLV 利用 HTTP/1.1 分块传输机制发送 FLV 数据。虽然直播服务器无法知道直播流的长度,但是 HTTP/1.1 分块传输机制可以不填写 conten-length 字段而是携带 Transfer-Encoding: chunked 字段,这样客户端就会一直接受数据。

HTTP FLV
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容

  • FLV封装格式 FLV(Flash Video)是Adobe公司推出的一种流媒体格式,由于其封装后的音视频文件体积...
    _zzbb阅读 7,988评论 3 11
  • FLV 简介 FLV(Flash Video) 是 Adobe 公司推出的一种流媒体格式,由于其封装后的音视频文件...
    远方竹叶阅读 2,487评论 0 0
  • Rtmp 分析参见:https://blog.csdn.net/fdsafwagdagadg6576/articl...
    mfdalf阅读 1,690评论 0 0
  • FLV简介 FLV(Flash Video)是现在非常流行的流媒体格式,由于其视频文件体积轻巧、封装播放简单等特点...
    FlyerGo阅读 796评论 0 1
  • FLV 文件 = File Header(FLV 文件头)+ File Body(FLV 文件体)。其中文件体又由...
    Coder_Sven阅读 2,067评论 1 1