MP4 文件结构深入解析
- 如果是元数据在文件开头,那么[mdat]和[moov]替换位置
 
+---------------------------------------------------------------+
|                         MP4 文件结构                           |
|                                                               |
|  +--------+          +--------+          +--------+           |
|  | [ftyp] | -------> | [mdat] | -------> | [moov] |           |
|  +--------+          +--------+          +--------+           |
|  文件类型标识           媒体数据            元数据容器           |
|                                             |                 |
|                      +---------------------+                  |
|                      |                                        |
|  +--------------------------------------------------+         |
|  |                     [moov]                       |         |
|  |  +-----------------------------+                 |         |
|  |  |           [mvhd]           |                 |          |
|  |  +-----------------------------+                 |         |
|  |        影片头部信息                               |         |
|  |                                                  |         |
|  |  +-----------------------------+                 |         |
|  |  |           [trak]           |                 |          |
|  |  +-----------------------------+                 |         |
|  |        轨道信息                                  |          |
|  |       /                \                        |          |
|  |      /                  \                       |          |
|  |  +-------------+    +-------------+             |          |
|  |  |   [tkhd]    |    |   [mdia]    |             |          |
|  |  +-------------+    +-------------+             |          |
|  |    轨道头信息          媒体信息                    |         |
|  |                        |                        |          |
|  |                        |                        |          |
|  |              +------------------+               |          |
|  |              |      [minf]      |               |          |
|  |              +------------------+               |          |
|  |                 媒体信息容器                     |          |
|  |                /          \                     |          |
|  |               /            \                    |          |
|  |      +-------------+    +-------------+         |          |
|  |      | [vmhd/smhd] |    |   [stbl]    |         |          |
|  |      +-------------+    +-------------+         |          |
|  |       视频/音频信息         样本表                |          |
|  |                            |                    |          |
|  |                  +------------------+           |          |
|  |                  |                  |           |          |
|  |                  |  +-------------+ |           |          |
|  |                  |  |   [stsd]    | |           |          |
|  |                  |  +-------------+ |           |          |
|  |                  |     样本描述      |           |          |
|  |                  |                  |           |          |
|  |                  |  +-------------+ |           |          |
|  |                  |  |   [stts]    | |           |          |
|  |                  |  +-------------+ |           |          |
|  |                  |  时间到样本映射    |           |          |
|  |                  |                  |           |          |
|  |                  |  +-------------+ |           |          |
|  |                  |  |   [stss]    | |           |          |
|  |                  |  +-------------+ |           |          |
|  |                  |   同步样本表      |           |          |
|  |                  |                  |           |          |
|  |                  |  +-------------+ |           |          |
|  |                  |  |   [stsz]    | |           |          |
|  |                  |  +-------------+ |           |          |
|  |                  |    样本大小       |           |          |
|  |                  +------------------+           |          |
|  +--------------------------------------------------+         |
|                                                               |
+---------------------------------------------------------------+
HTTP Range 请求机制详解
HTTP Range请求是HTTP/1.1协议中的一个重要特性,允许客户端请求资源的部分内容。这对于大型媒体文件(如视频)的传输尤为重要。
Range 请求头格式与语法
Range: bytes=<start>-<end>
播放支持 http-range 的视频
1. 发送一个 GET 请求 (with range)
Chrome                                          Server
+----------------------------+                  +--------------------------------------------------+     
| GET    /video.mp4 HTTP/1.1 |                  | HTTP/1.1 206 Partial Content                     |
| Host:  cdn.com             |   <-------->     | Accept-Ranges: bytes                             |
| Range: bytes=0-            |                  | Content-Range: bytes 0-11799707/828908176        |
+--------------------------+                    | Content-Length: 827040401                        |
                                                | (body: .........)                                |
                                                +--------------------------------------------------+
2. 当你快进播放的时候
Chrome                                         Server
+--------------------------------+                +-----------------------------------------------------+
| GET /a.mp4 HTTP/1.1            |   <-------->   | HTTP/1.1 206 Partial Content                        |
| Host: cdn.com                  |                | Accept-Ranges: bytes                                |
| Range: bytes=1867776-828908176 |                | Content-Range: bytes 1867776-828908176/828908177    |
+--------------------------------+                | Content-Length: 827040400                           |
                                                  | (body: .........)                                   |
                                                  +-----------------------------------------------------+
播放不支持 http-range 的视频
- GET视频流式播放, 不能快进快退, 每次从头开始播放
 - 服务器需要配置 Accept-Ranges: none 或不返回 Accept-Ranges 头
 - 浏览器检测到不支持 Range 请求时,会采用线性播放模式
 
元数据位置对播放的影响
- MP4文件中moov box的位置对视频播放有重大影响:
 
- 
元数据在文件开头 (faststart) :
- 浏览器可以立即获取视频的关键信息
 - 无需下载整个文件即可开始播放
 - 支持快速定位到任意时间点
 
 - 
元数据在文件结尾 :
- 浏览器需要下载完整文件或使用Range请求获取文件末尾
 - 在获取元数据前无法确定视频时长和其他关键信息
 - 影响用户体验,尤其是大文件
 
 
生成视频测试
## ## 元数据在开始
ffmpeg -f lavfi -i testsrc=duration=60:size=1920x1080:rate=30 -c:v libx264 -c:a aac -movflags +faststart meta_at_start.mp4
## 元数据在末尾
ffmpeg -f lavfi -i testsrc=duration=60:size=1920x1080:rate=30 -c:v libx264 -c:a aac -movflags empty_moov+default_base_moof meta_at_end.mp4
测试结果
- 下面表格的顺序是上面的图
 
| 视频 | 描述 | 播放过程 | 
|---|---|---|
| meta_at_start.mp4 | 元信息在开头 | 一开始就能播放, 不能快进快退(只能流式播放) | 
| meta_at_end.mp4 | 元信息在结尾 | 一开始就能播放, 不能快进快退(显示视频时长 0:08 有问题,因为没加载元信息) | 
| meta_at_start_with_range.mp4 | 元信息在开头并且支持 range | 一开始就能播放, 可以快进快退 | 
| meta_at_end_with_range.mp4 | 元信息在结尾并且支持 range | 一开始不能播放,必须下载完成才能播放 (下载完了可以快进快退) | 
HLS 与 M3U8 流媒体技术
除了基于 HTTP Range 的视频流媒体播放,另一种广泛使用的技术是 HTTP Live Streaming (HLS),它使用 M3U8 播放列表文件来管理视频分片。
+--------------------------------------------------------------------------------------+
|                                    M3U8 文件结构                                      |
|                                                                                      |
|  主播放列表 (master.m3u8)                                                             |
|  +--------------------------------------------------------------------------------+  |
|  | #EXTM3U                                                                        |  |
|  | #EXT-X-VERSION:3                                                               |  |
|  | #EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080                       |  |
|  | stream_0.m3u8                                                                  |  |
|  | #EXT-X-STREAM-INF:BANDWIDTH=3000000,RESOLUTION=1280x720                        |  |
|  | stream_1.m3u8                                                                  |  |
|  | #EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360                         |  |
|  | stream_2.m3u8                                                                  |  |
|  +--------------------------------------------------------------------------------+  |
|                                       |                                              |
|            +-------------+-------------------------------------------+               |
|            |                          |                              |                |
|            v                          v                              v                |
|  +------------------------+  +------------------------+ +------------------------+    |
|  | 高清播放列表            |  | 标清播放列表             | | 低清播放列表           |     |
|  | stream_0.m3u8          |  | stream_1.m3u8          | | stream_2.m3u8          |    |
|  |                        |  |                        | |                        |    |
|  | #EXTM3U                |  | #EXTM3U                | | #EXTM3U                |    |
|  | #EXT-X-VERSION:3       |  | #EXT-X-VERSION:3       | | #EXT-X-VERSION:3       |    |
|  | #EXT-X-TARGETDURATION:6|  | #EXT-X-TARGETDURATION:6| | #EXT-X-TARGETDURATION:6|     |
|  | #EXT-X-MEDIA-SEQUENCE:0|  | #EXT-X-MEDIA-SEQUENCE:0| | #EXT-X-MEDIA-SEQUENCE:0|     |
|  | #EXTINF:6.0,           |  | #EXTINF:6.0,           | | #EXTINF:6.0,           |     |
|  | data000.ts             |  | data000.ts             | | data000.ts             |     |
|  | #EXTINF:6.0,           |  | #EXTINF:6.0,           | | #EXTINF:6.0,           |     |
|  | data001.ts             |  | data001.ts             | | data001.ts             |     |
|  | ...                    |  | ...                    | | ...                    |     |
|  | #EXT-X-ENDLIST         |  | #EXT-X-ENDLIST         | | #EXT-X-ENDLIST         |     |
|  +------------------------+  +------------------------+ +--------------------+         |
|           |                              |                      |                      |
|           v                              v                      v                      |
|     +------------+                  +------------+        +------------+               |
|     | 高清片段     |                | 标清片段     |        | 低清片段     |             |
|     | data000.ts  |                | data000.ts  |        | data000.ts  |              |
|     | data001.ts  |                | data001.ts  |        | data001.ts  |              |
|     | ...         |                | ...         |        | ...         |              |
|     +------------+                 +------------+          +------------+              |
|                                                                                        |
+----------------------------------------------------------------------------------------+
- 
视频分段:将视频切分为多个小片段(通常为 .ts 文件)
- 每个片段通常为 6-10 秒
 - 片段时长影响延迟和带宽适应性
 - 较短片段利于快速切换,但会增加请求次数
 - 较长片段减少请求次数,但增加首次加载延迟
 
 - 
创建索引文件:生成 .m3u8 文件,包含所有片段的信息和播放顺序
- 主播放列表(master.m3u8):包含所有清晰度版本信息
 - 媒体播放列表(stream_N.m3u8):包含具体片段信息
 - 播放列表定期更新,支持直播场景
 
 - 
自适应比特率:为同一视频提供多种分辨率和比特率的版本
- 高清流(1080p):BANDWIDTH=5000000, RESOLUTION=1920x1080
 - 标清流(720p):BANDWIDTH=3000000, RESOLUTION=1280x720
 - 低清流(360p):BANDWIDTH=1000000, RESOLUTION=640x360
 - 播放器根据网络状况自动切换合适的清晰度
 
 - 
客户端请求:播放器先请求 .m3u8 文件,然后根据需要下载各个片段
- 首次请求 master.m3u8 获取可用清晰度列表
 - 根据当前网络状况选择合适的清晰度流
 - 请求对应的 stream_N.m3u8 获取片段列表
 - 按需下载 .ts 片段文件
 - 网络状况变化时自动切换清晰度
 
 
与 HTTP Range 的比较
| 对比维度 | HLS (M3U8) | HTTP Range | 
|---|---|---|
| 文件格式 | 将视频分割为多个 .ts 片段 | 使用单一 MP4 文件 | 
| 优点 | • 支持自适应码率 • 广泛兼容各种设备 • 原生支持直播场景 • 支持清晰度动态切换  | 
• 延迟低,精确请求 • 存储高效,单一文件 • 实现简单 • 支持精确定位 • 带宽利用率高  | 
| 缺点 | • 延迟较高(至少一个片段) • 存储开销大 • 实现复杂 • 存在带宽冗余  | 
• 不支持自适应码率 • 兼容性受限 • 缓存效率较低 • 不适合直播场景  | 
| 适用场景 | • 直播业务 • 多设备支持 • 不稳定网络环境 • 需要多码率支持  | 
• 点播业务 • 低延迟要求 • 存储受限场景 • 简单播放需求  | 
| 技术复杂度 | 高:需要完整的转码和分发系统 | 低:仅需支持 Range 请求 | 
| 运维成本 | 高:需要维护转码集群和存储系统 | 低:普通 Web 服务器即可 |