Nginx 伺服 mp4 视频流的配置参考
Category(分类): Backend Status: 已读
原文:Nginx configuration for serving mp4 videos(GitHub Gist,CSRaghunandan)。 本文为整理版本:Gist 原文只有一份完整的 nginx.conf,此处保留配置并补充逐段注释,便于理解每部分的作用。
配置总览
这是一份用于 WebRTC 直播 + mp4 点播的混合配置(janus 信令反代、flv 直播、mp4 点播缓存),其中与 mp4 视频伺服直接相关的是最后一个 location ~/.mp4 块。
#user nobody;
worker_processes 4;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
access_log off;
sendfile_max_chunk 512k;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
gzip on;
server {
# 代理缓存路径:缓存 70MB,命名 mycache
proxy_cache_path /tmp/mycache keys_zone=mycache:70m;
listen *:9000;
root /usr/local/nginx/html;
index index.html index.htm;
server_name _;
# —— WebRTC 信令(janus)反向代理 ——
location /rtc {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:8088/janus;
}
# —— rtcapp WebSocket 升级代理 ——
location /rtcapp {
# 为直播启用线程池
aio threads=default;
proxy_pass http://localhost:8188;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
# —— flv 直播流 ——
location ~ \.flv$ {
aio threads=default;
flv;
}
# —— mp4 点播(核心部分)——
location ~/.mp4 {
root /media;
mp4;
mp4_buffer_size 1M;
mp4_max_buffer_size 3M;
# 启用线程池,避免阻塞 worker
aio threads=default;
# 为 mp4 启用代理缓存
proxy_cache mycache;
proxy_cache_valid 200 300s;
proxy_cache_lock on;
# 启用 nginx 分片缓存
slice 1m;
proxy_cache_key $host$uri$is_args$args$slice_range;
proxy_set_header Range $slice_range;
proxy_http_version 1.1;
# 回填缓存期间立即回源
proxy_cache_lock_timeout 0s;
# 将 age 设为大于预期回填时间的值
proxy_cache_lock_age 200s;
proxy_cache_use_stale updating;
}
}
}
关键配置解读
mp4 模块
mp4;
mp4_buffer_size 1M;
mp4_max_buffer_size 3M;
mp4指令启用 ngx_http_mp4_module,支持"伪流媒体"(pseudo-streaming):浏览器通过?start=查询参数即可从任意位置开始播放,无需下载整个文件;mp4_buffer_size是处理 mp4 元数据(moov atom)的初始缓冲区,mp4_max_buffer_size是上限。注意保持合理值,过大(例如有人设到 300M)会显著增加内存压力。
aio threads(线程池)
aio threads=default;
将阻塞的磁盘读取操作交给独立线程池处理,避免慢速 I/O 阻塞事件循环。官方博客的测试中,线程池可将大文件传输性能提升数倍(见下一篇《Nginx 伺服大体积 mp4 文件效率问题排查》)。
sendfile 与分片
sendfile on;
sendfile_max_chunk 512k;
sendfile让数据在内核态直接从文件描述符传输到 socket,避免用户态拷贝;sendfile_max_chunk限制单次 sendfile 传输量(512k),防止单个连接长时间独占 worker。
slice 分片缓存 + Range 请求
slice 1m;
proxy_cache_key $host$uri$is_args$args$slice_range;
proxy_set_header Range $slice_range;
proxy_http_version 1.1;
slice 模块将大响应切成固定大小(1m)的子请求,每个分片独立缓存。配合 Range 请求头,同一个大 mp4 文件的不同分片可以被分别缓存和复用,非常适合按需拖动进度条的场景。
缓存行为控制
proxy_cache_lock on;
proxy_cache_lock_timeout 0s;
proxy_cache_lock_age 200s;
proxy_cache_use_stale updating;
proxy_cache_lock on:同一分片回填期间,后续请求等待而不是重复回源;proxy_cache_lock_timeout 0s+proxy_cache_lock_age 200s:等待超时后直接回源;proxy_cache_use_stale updating:缓存刷新期间可以返回旧缓存,避免用户请求被卡住。
适用场景
- 视频文件较大、用户会频繁拖动进度条(Range 请求多);
- 同一批视频会被反复观看(缓存命中收益高);
- 服务器磁盘 I/O 较慢(线程池 + aio 避免阻塞)。