Fork me on GitHub
0%

m3u8视频流基础

基础

文件格式与编码格式区别:

  • 文件格式

    文件格式是指数字媒体文件的结构和组织方式,通常用于存储和传输媒体数据,例如音频、视频或图像。文件格式决定了媒体文件的扩展名(例如,.mp3、.mp4、.jpg、.png、.avi、.mkv 等),而不同的文件格式可能支持不同的编码格式和特性,例如MP4 文件格式通常可以包含 H.264 编码的视频和 AAC 编码的音频

  • 编码格式

    编码格式是指数字媒体数据的压缩和编码方式,以减小文件大小并在媒体传输和播放时提供高质量的媒体内容。不同的编码格式采用不同的算法来压缩和编码媒体数据,并最终影响到文件的质量、大小以及兼容性。对于视频,常见的编码格式包括 H.264(AVC)、H.265(HEVC)、VP9 等;对于音频,常见的编码格式包括 AAC、MP3、Opus 等。

M3U8

m3u8在线播放器

m3u8视频在线提取工具

M3U(Moving Picture Experts Group Audio Layer 3 Uniform Resource Locator)本质上说不是音频文件,而是一个记录索引的纯文本文件,一个音频文件的列表文件。它并不能在离线模式下读取网络资源音频,而是根据它的索引找到对应的音视频文件的网络地址进行在线播放。

M3U8 文件是指 UTF-8 编码格式的 M3U 文件(M3U 使用 Latin-1 字符集编码),是一种常用的直播和点播视频格式。M3U8文件中的内容主要由标签(TAG)、属性列表(Attribute Lists)、播放地址(URI)构成。

TAG

  • Basic Tags,基本标签:该类标签必须出现在每个M3U8文件中;
  • Media Segment Tags,媒体片段标签:该类标签和其跟随的URI一起指定一个媒体片段。有些媒体片段标签仅作用于其下一行的片段,而其他的媒体片段标签作用于所有子序列片段,直到另外一个相同标签实例出现。一个媒体片段标签一定不能出现在主播放列表中;
  • Media Playlist Tags,媒体播放列表标签:该类标签是描述媒体播放列表的全局参数。一个媒体播放列表中,每种类型的媒体播放列表标签只能出现一次。媒体播放列表标签不能出现在主播放列表中;
  • Master Playlist Tags,主播放列表标签:主播放标签定义了Variant Stream、Rendition和其他显示的全局参数,主播放列表标签不能出现在媒体播放列表中
  1. EXTM3U
    EXTM3U标记指示文件是扩展M3U [ M3U ]播放列表文件。它必须是每个媒体播放列表的第一行,每个主播放列表。其格式为:#EXTM3U
  2. EXT-X-VERSION
    EXT-X-VERSION标记指示兼容版本播放列表文件,其关联的媒体及其服务器。 EXT-X-VERSION标签适用于整个播放列表文件。它的格式为:#EXT-X-VERSION:
  3. EXTINF
    EXTINF标签指定媒体段的持续时间。适用仅到下一个媒体段。每个媒体都需要此标签分割。其格式为:#EXTINF:

Attribute Lists

1
属性名=属性值

在一些标签后面跟随的是属性列表,属性列表是用逗号分割开来的键值对列表。如下面的语法格式所示,属性列表中的属性名、’=’、属性值之间不能有空格,属性名可以是由数字[0,9]、大写字母[A,Z]、和’-‘这些字符构成。

URL

播放地址比较简单,一般单独占用一行。其中播放地址是比较简单的,其一般单独占用一行。该地址一般由.m3u8、.m3u、.ts结尾(实际应用中这些后缀后面还可能会带着由问号(?)分割的其他应用参数),前两种结尾的播放地址代表当前是一个一级M3U8文件,这些地址指向的是一个个二级M3U8文件;而以.ts结尾的播放地址代表当前是一个二级M3U8文件,这些地址指向的是一个个具体的ts分片下载地址。

HLS

HLS(HTTP Live Streaming)是一种用于实时流媒体传输的协议,最初由苹果公司开发并推广。它被广泛用于在互联网上实时传输音频和视频内容,并在多种设备和平台上播放。

HLS主要内容由HTTP + M3U8 + TS这三个部分共同组成,其中HTTP是最常见的应用层协议了,我们日常基本的浏览器上网就是基于HTTP协议;而TS是音视频编码标准MPEG-2中定义的一种媒体流封装复用格式,TS相关的详情可以参考文章《MPEG-2 TS流结构浅析》;HTTP和TS都是其他协议或标准中规定的内容,那么HLS的核心就是这个M3U8了

优点:

  • 跨平台兼容性:HLS 协议在多个平台上广泛支持,包括iOS设备、Android设备、桌面计算机、智能电视等。这意味着内容提供商可以使用单一的 HLS 流来覆盖多个设备,而无需定制多个传输协议。
  • 分段传输:HLS 将媒体内容分成小的媒体片段,并以连续的方式传输。这有助于减少缓冲延迟并提高播放的稳定性。
  • 自适应码率支持:HLS 允许内容提供商提供多个不同质量和分辨率的媒体流,以适应观众的设备和带宽。
  • 安全性:HLS 支持内容加密,以确保内容的安全性,并防止未经授权的访问。

缺点:

  • 延迟:HLS 在某些情况下可能引入较长的播放延迟,特别是在实时直播场景中。这个延迟对于需要低延迟的应用可能不太适用,如在线游戏或实时互动。

视频I/P/B帧

  • I 帧 (Intra-coded frame):关键帧,它是独立的帧,不依赖其他帧的信息。I 帧包含完整的图像信息,因此它的压缩效果相对较差,但是它可以独立地被解码。
  • P 帧 (Predicted frame):预测帧。它依赖于前面的 I 帧或者 P 帧,P 帧在存储图像信息的同时,还记录了图像的变化量,因此它的压缩效果比 I 帧更好。
  • B 帧 (Bidirectional frame):双向预测帧。它依赖于前面和后面的 I 帧或者 P 帧,B 帧可以从多个方向预测图像,因此其压缩效果比 P 帧更好,但是不能独立地被解码,必须和相邻的 I 帧或者 P 帧配合使用。

播放示例

mp4转m3u8

1
2
3
4
5
6
7
8
9
10
$  ffmpeg -i inupt.mp4 -c:v libx264 -c:a aac -strict -2 -f hls -hls_list_size 2 -hls_time 15 output.m3u8

# -i: 指定输入文件
# -c:v 指定视频编码的视频编解码器
# -c:a 指定音频编码的音频编解码器
# -strict 用于启用或禁用编码器的严格性。-2 表示禁用所有警告和错误,以便 FFmpeg 可以自动进行最佳设置
# -f 指定了输出格式,即要生成的流媒体格式是 HLS
# -hls_list_size 指定 HLS 播放列表文件(M3U8 文件)的最大条目数。在这个例子中,最多会有 2 个 M3U8 文件
# -hls_time 指定 HLS 分段的持续时间(以秒为单位)。在这个例子中,每个分段的持续时间为 15 秒
# 最后是输出文件名

测试地址

Q&A

  1. ffplay播放m3u8网络流错误?

    1
    2
    [tcp @ 0x561907287000] Connection to tcp://192.168.4.16:8082 failed: Connection timed out
    https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8: Connection timed out

    如上所示即为报错内容,这个ip及端口明显是我的本机之前所配置的代理,而ffplay在网络拉流的时候使用了错误的代理。最终在/etc/environment文件中找到这个ip并修改成目前正在使用的代理。source /etc/environment 刷新环境变量,并使用export查看,再次播放即可。

  2. mplayer播放https的网络直播数据流出错?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
        $ mplayer  https://mobilelive.gxtv.cn/live/nn_live1006/playlist.m3u8 
    MPlayer 1.5-9 (C) 2000-2022 MPlayer Team

    Playing https://mobilelive.gxtv.cn/live/nn_live1006/playlist.m3u8.
    libavformat version 59.17.102 (internal)
    Cannot seek backward in linear streams!
    Cannot seek backward in linear streams!
    Cannot seek backward in linear streams!
    Cannot seek backward in linear streams!
    Cannot seek backward in linear streams!
    Cannot seek backward in linear streams!
    Cannot seek backward in linear streams!
    Cannot seek backward in linear streams!
    Cannot seek backward in linear streams!


    // 解决方案
    在命令行的位置添加一个选项 -cache 4096

    3. m3u8视频流不能跳转

    ```shell
    *** ftime=0.040 ***
    delay=0.371519
    seekTime : 60.000000
    A: 13.6 V: 13.6 A-V: -0.006 ct: -0.016 0/ 0 7% 32% 7.1% 25 0 0%
    demux_seek_lavf(0x854a00, 60.000000, 0.000000, 1)
    [AVIOContext @ 0x77192444]Statistics: 1019312 bytes read, 0 seeks
    ds_fill_buffer(d_audio) called
    demux_lavf_fill_buffer()
    [mpegts @ 0x77190bc8]Skipping after seek
    [hls @ 0x77190bc8]HLS request for url 'http://video.english163.com/uploadfile/vieo/xindongfang/xindongfangd01j01/500kb/hls/index5.ts', offset 0, playlist 0
    [hls @ 0x77190bc8]Opening 'crypto+http://video.english163.com/uploadfile/vieo/xindongfang/xindongfangd01j01/500kb/hls/index5.ts' for reading

    定位问题的方法:如果可以将所有的config都打开,这样子确认是否能够支持。随后通过二分法,定位到具体是哪一个配置文件起作用。

  3. mplayer没有详细的打印?

    mplayer -msglevel all=9可以将所有打印显示出来,其中all可以替换成network、xxx等等

  4. m3u8使用本地key进行解密?

    首先需要把播放文件下载到本地m3u8文件,该文件将包含EXTM3U信息头和ts切片链接。接下来,将解密key写成文件的形式存放在本地。最后,修改m3u8本地文件,修改字段为 EXT-X-KEY: METHOD=AES-128,URI=”file//home/user/key.m3u8”,IV=xxxxxxxx。

    这里需要注意的是,对于密钥文件的名字扩展名一定是.m3u8。因为新版本ffmpeg出于安全限制了文件扩展名,只有白名单里的才能被读取,而.key文件不在白名单里,.m3u8一定在白名单中。如果一定要使用其它的扩展名,对于ffplay需要添加 -allowed_extensions ALL 字段才可以正常播放。

    1
    2
    # 以下扩展名是允许的
    .str = "3gp,aac,avi,ac3,eac3,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,wav"

参考资料

  1. H264编码格式–图文解释
  2. HLS协议剖析
  3. HTTP Live Streaming draft-pantos-http-live-streaming-12
  4. 视频的I、P、B帧通俗解释