自建视频服务器:用 Nginx 搭建 HLS 流媒体服务
你下载了一堆视频,想在局域网里自建一个"私人 B 站"——浏览器打开就能播、支持进度条拖拽、手机电脑都能看。其实不需要什么复杂的媒体服务器软件,Nginx + 一个配置模块就能搭出生产级的 HLS 流媒体服务。本文手把手带你从零搭建。
TL;DR:Nginx 加上
nginx-rtmp-module(或直接用nginx-http-flv-module)就能推流 + 切片 + 分发一条龙。核心流程:ffmpeg 把 MP4 转成 HLS(.m3u8+.ts),Nginx 做静态文件服务器,前端用 video.js / hls.js 播放。全链路不依赖第三方服务,数据和流量都留在你手里。
目录
- 一、为什么选 Nginx
- 二、安装带 RTMP 模块的 Nginx
- 三、用 ffmpeg 把 MP4 转成 HLS 分片
- 四、Nginx 配置 HLS 分发
- 五、前端播放:video.js 一行接入
- 六、进阶:实时推流 + 转 HLS
- 七、常见坑与排障
- 八、合规与温馨提示
一、为什么选 Nginx
做流媒体服务器的可选项很多:SRS、Node-Media-Server、Wowza……但 Nginx 有几个独特优势:
| 方案 | 优势 | 劣势 |
|---|---|---|
| Nginx + RTMP 模块 | 轻量、高性能、和 Web 服务一体 | 配置稍繁琐 |
| SRS | 专为流媒体设计,开箱即用 | 单独进程,资源占用较高 |
| ffmpeg + Python HTTP | 最简单 | 性能差,不适合多人并发 |
对于"局域网内自用"的场景,Nginx 是最平衡的选择:既轻量,又能复用你已有的 Web 服务基础设施。
二、安装带 RTMP 模块的 Nginx
Windows 用户推荐直接下载带模块的预编译版,Linux 用户从源码编译。
Ubuntu/Debian:
# 安装依赖
sudo apt update && sudo apt install -y build-essential libpcre3-dev libssl-dev zlib1g-dev
# 下载 nginx 和 rtmp 模块源码
wget http://nginx.org/download/nginx-1.24.0.tar.gz
git clone https://github.com/arut/nginx-rtmp-module.git
# 编译(关键:--add-module)
cd nginx-1.24.0
./configure --add-module=../nginx-rtmp-module --with-http_ssl_module
make && sudo make install
Windows: 下载 nginx Windows 版 + 替换已编译好 RTMP 模块的 nginx.exe(社区有现成的),或者直接使用 Docker:
docker run -d -p 80:80 -p 1935:1935 \
-v /your/videos:/opt/videos \
tiangolo/nginx-rtmp
安装完成后,nginx -V 如果看到 nginx-rtmp-module,就说明成功了。
三、用 ffmpeg 把 MP4 转成 HLS 分片
HLS 播放需要两个东西:一个 .m3u8 索引文件 + 一堆 .ts 分片文件。
# 把单个 MP4 转成 HLS(分片 10 秒一个)
ffmpeg -i video.mp4 \
-c:v libx264 -c:a aac \
-hls_time 10 \
-hls_list_size 0 \
-hls_segment_filename "ts/video_%03d.ts" \
video.m3u8
参数解释:
- -hls_time 10:每个 .ts 分片 10 秒
- -hls_list_size 0:m3u8 里列出所有分片(不限制数量)
- -hls_segment_filename:分片文件的命名模板
如果想保留原始编码不重压(更快):
ffmpeg -i video.mp4 -c copy -hls_time 10 -hls_list_size 0 video.m3u8
更多 ffmpeg 与 m3u8 的技巧,见 用 ffmpeg 把 m3u8 合并成 mp4:音视频分离与 TS 拼接的坑。
四、Nginx 配置 HLS 分发
在 nginx.conf 中添加:
http {
server {
listen 80;
server_name localhost;
# HLS 静态文件服务
location /hls/ {
alias /opt/videos/hls/;
add_header Cache-Control no-cache;
add_header Access-Control-Allow-Origin *; # 允许跨域
}
}
}
# 可选:RTMP 推流模块
rtmp {
server {
listen 1935;
application live {
live on;
# 推上来的流自动转 HLS
hls on;
hls_path /opt/videos/hls/;
hls_fragment 5s;
}
}
}
重启 Nginx 后,把第三步生成的 video.m3u8 和 ts/ 目录放到 /opt/videos/hls/ 下,浏览器访问 http://localhost/hls/video.m3u8 就能播了。
五、前端播放:video.js 一行接入
纯 HTML 页面引入 hls.js 或 video.js 即可:
<!DOCTYPE html>
<html>
<head>
<link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
</head>
<body>
<video id="player" class="video-js vjs-default-skin" controls width="800">
<source src="http://localhost/hls/video.m3u8" type="application/x-mpegURL">
</video>
<script src="https://unpkg.com/video.js/dist/video.min.js"></script>
<script>
videojs('player');
</script>
</body>
</html>
手机、平板、电脑,只要能打开这个页面就能播——这就是你的"私人视频站"。
六、进阶:实时推流 + 转 HLS
如果你不只是播放本地文件,还想把摄像头画面实时推上去:
# 用 ffmpeg 推摄像头画面到 Nginx RTMP
ffmpeg -f dshow -i video="USB Camera" -c:v libx264 -preset veryfast \
-f flv rtmp://localhost/live/streamkey
Nginx 的 RTMP 模块会自动把推上来的流转成 HLS,你直接用 http://localhost/hls/streamkey.m3u8 就能看直播画面。延迟大概 5-10 秒(RTMP 推流 + HLS 切片缓冲),对家庭监控、局域网直播完全够用。
七、常见坑与排障
| 问题 | 原因 | 解决 |
|---|---|---|
| 浏览器播不了 | 跨域限制 | 加 Access-Control-Allow-Origin: * |
| 播放卡顿、缓冲频繁 | 分片太大或网络慢 | 减小 -hls_time 到 5 秒 |
| m3u8 404 | 路径不对 | 确认 alias 路径与文件实际位置一致 |
| 手机 Safari 不播 | HTTPS 要求 | 自签证书或用 HTTP 测试 |
| ffmpeg 转 HLS 报错 | 编码器不兼容 | 加 -c:v libx264 -c:a aac 明确编码器 |
八、合规与温馨提示
技术是中性的,用法见人心。我们强烈建议:
- 仅下载你自己拥有版权或平台明确允许保存的内容;
- 自建服务器仅用于个人学习、家庭共享,不用于公开盗版传播;
- 尊重创作者与平台服务条款。
用 Nginx 搭建 HLS 流媒体服务,本质就是把"文件服务"升级成"视频服务"。如果你已经有 NAS 或一台闲置电脑,花半小时配好这套,就能拥有一个完全自主可控的私人视频库——不依赖任何云服务,所有数据都留在你手里。
本文由 VidDown 技术博客原创发布。VidDown 是一个免费、本地优先的在线视频解析与开发者工具站,支持多平台视频下载、格式转换、m3u8 合并等实用功能,所有数据处理均在本地完成,保护你的隐私。欢迎访问 www.viddown.cn 体验。