一、模块原理
-
Moov Atom
MP4 文件中,moov
原子(atom)存储了全文件的索引信息(时间戳与文件偏移映射),用于快速寻址。理想状态下,moov
应位于文件开头;若位于末尾,模块需先读取整个文件、重新组装并将moov
放前才能响应客户端,带来额外 CPU、内存和 I/O 开销。 -
伪流式请求
客户端在 URL 中添加start=秒数
(可选end=秒数
)参数,例如:http://example.com/video.mp4?start=120.5&end=300
start
:跳转到视频的该秒数处开始播放end
(1.5.13 起):在该秒数处结束播放
-
关键帧对齐
如果start
秒数对应非关键帧,视频画面可能损坏。1.21.4 起,可开启mp4_start_key_frame on
,模块会在start
前自动插入最近关键帧并使用 edit list 隐藏多余帧,保证播放器兼容性。 -
无查询参数直接发送
如果请求 URL 中无start
/end
参数,模块不做任何额外处理,直接当作静态文件返回,若客户端发出字节范围请求(Range),同样可正常处理,但无需本模块。
二、示例配置
http {
server {
listen 80;
server_name video.example.com;
location /video/ {
mp4; # 启用 MP4 伪流式模块
mp4_buffer_size 1m; # 首次读入 moov 区域的初始缓冲
mp4_max_buffer_size 5m; # 最大缓冲区,防止过大 moov atom 导致 OOM
mp4_limit_rate on; # (商用版)按视频平均码率限速,factor=1.1
mp4_limit_rate_after 30s; # (商用版)前 30s 不限速,之后限速
mp4_start_key_frame on; # (1.21.4)强制从关键帧开始
}
}
}
-
普通播放
GET /video/movie.mp4
→ 直接返回文件头到尾。
-
跳转播放
GET /video/movie.mp4?start=120
→ 读取 moov atom,定位到 120s,对应文件偏移后,从该处开始发送。
-
区间播放
GET /video/movie.mp4?start=120&end=300
→ 只返回 120s–300s 间的数据流。
三、指令详解
1. mp4
Syntax: mp4;
Default: —
Context: location
- 功能:在当前
location
块开启 MP4 伪流式支持。 - 说明:必须放在处理静态 MP4 的
location
中,无参数。
2. mp4_buffer_size
Syntax: mp4_buffer_size <size>;
Default: mp4_buffer_size 512K;
Context: http, server, location
- 功能:首次读入并解析
moov
atom 时使用的缓冲区大小。 - 建议:根据普通
moov
大小设置,避免过小导致多次 I/O。
3. mp4_max_buffer_size
Syntax: mp4_max_buffer_size <size>;
Default: mp4_max_buffer_size 10M;
Context: http, server, location
-
功能:解析过程中允许的最大缓冲区尺寸,防止异常文件导致内存暴涨。
-
超限处理:若遇到大于此值的
moov
atom,返回 500 Internal Server Error,日志示例:"/some/movie.mp4" mp4 moov atom is too large: 12583268, you may want to increase mp4_max_buffer_size
4. mp4_limit_rate
(商业版)
Syntax: mp4_limit_rate on | off | <factor>;
Default: mp4_limit_rate off;
Context: http, server, location
-
功能:基于视频平均码率限速输出。
-
参数:
off
:不限速(默认)on
:限速因子 = 1.1 × 平均码率<factor>
:自定义倍数,如1.5
表示 1.5× 平均码率
-
注意:每个请求单独限速,多个并行连接可累加带宽。
5. mp4_limit_rate_after
(商业版)
Syntax: mp4_limit_rate_after <time>;
Default: mp4_limit_rate_after 60s;
Context: http, server, location
- 功能:在传输了指定播放时长后才开始限速(配合
mp4_limit_rate
)。 - 示例:
mp4_limit_rate_after 30s;
→ 前 30 秒按最大带宽发送,之后按限速值发送。
6. mp4_start_key_frame
Syntax: mp4_start_key_frame on | off;
Default: mp4_start_key_frame off;
Context: http, server, location
- 功能(1.21.4 起):确保视频从关键帧开始显示。
- 原理:若
start
秒数对应非关键帧,模块会截取前一个关键帧之间的所有帧,并通过 MP4 edit list 隐藏不必要帧,保证播放流畅且兼容主流播放器(Chrome、Safari、QuickTime、FFmpeg;Firefox 部分支持)。
四、使用建议
-
提前优化文件
- 最佳实践是将
moov
atom 移至文件开头(可用qtfaststart
、MP4Box
等工具),避免运行时重组开销; - 若无法事先处理,确保
mp4_max_buffer_size
足够,且服务器具备相应内存与 I/O 性能。
- 最佳实践是将
-
缓冲与并发
- 并发跳转请求可能同时占用较大缓冲;
- 配合 Nginx 全局
sendfile
、aio
、output_buffers
优化大文件传输。
-
限速策略
- 商业版可用
mp4_limit_rate
+mp4_limit_rate_after
平滑流量高峰; - 对 CDN 前端或带宽受限场景尤为有效。
- 商业版可用
-
兼容性测试
- 若使用
mp4_start_key_frame on
,务必验证目标播放器(Web、移动端)是否支持 MP4 edit list; - 对于不支持的客户端,可在配置中根据
User-Agent
或map
指令选择性开启。
- 若使用
-
监控与日志
- 在高并发或重组失败场景,可在 error log 中捕获 “moov atom is too large” 警告,及时调整
mp4_max_buffer_size
或优化源文件。
- 在高并发或重组失败场景,可在 error log 中捕获 “moov atom is too large” 警告,及时调整
通过 ngx_http_mp4_module
,您可以在无需专用流媒体服务器的前提下,为静态 MP4 文件提供高效、可控的伪流式播放与随机 seek 支持,提升用户体验并有效利用现有 Nginx 基础架构。