最近经常有朋友问我:明明是自己辛苦拍的视频,发在平台上却总被限流、被举报,申诉流程又长又慢,即使最后恢复了,流量和推荐也已经损失大半。与其被动等待平台审核,不如把内容放回自己手里。这篇文章就围绕“自建一个视频网站来承载自己的视频内容”这件事,讲清楚从视频转码、服务器配置到网页播放器的完整流程。
自建视频网站并不是一个特别复杂的事,核心只有几个环节:给视频做转码和切片、用 Nginx 托管视频目录、写一个支持 HLS 播放的网页播放器。这套方案适合个人作品集、课程视频、企业内部培训视频、小团队内容分发等场景。下面我按实际搭建顺序,把步骤完整拆开。
1. 为什么选择自建视频网站
1.1 视频被举报下架的痛点
在视频平台上传内容,本质上是在平台规则下获取流量。平台会对内容进行机器审核和人工审核,同时允许其他用户对视频发起举报。即使是原创且合规的内容,也可能因为误判、恶意举报或版权投诉被下架。
平台申诉机制虽然存在,但流程通常较慢:你需要提供原始素材、说明创作过程、等待人工复核。这期间视频已经无法播放,推荐权重也会受到影响。对以视频为作品展示的个人创作者来说,这种不确定性是难以接受的。
自建视频网站解决的核心问题不是“流量”,而是“控制权”。视频文件放在自己的服务器或对象存储中,页面、播放器、清晰度、封面都是自己控制。只要内容本身不违规,就不会有第三方因为举报直接下架你的内容。
但这里必须强调:自建网站不等于可以发布违规内容。版权同样是红线,盗用别人的视频、电影、电视剧、软件录制内容,放在自己网站上同样会面临侵权风险。自建视频网站适合承载的是原创内容、已获授权内容,或者企业内部培训资料。
1.2 自建视频网站的组成
一个最简单的视频网站由以下几个部分组成:
| 模块 | 作用 | 常用方案 |
|---|---|---|
| 域名 | 对外访问入口 | 阿里云、腾讯云、Cloudflare 等 |
| 服务器 | 运行 Web 服务、存放视频 | Linux 云服务器、本地 NAS |
| 视频处理 | 转码、切片、压缩 | FFmpeg |
| Web 服务 | 托管 HTML 和视频文件 | Nginx |
| 播放器 | 浏览器中播放视频 | hls.js、DPlayer、Plyr |
| 文件存储 | 存放转码后的视频文件 | 本地磁盘、对象存储 OSS |
以上每个环节都可以单独替换。个人快速起步时,一台低配云服务器加本地磁盘就够了;视频量大了,再把文件迁移到对象存储,配合 CDN 分发。
1.3 自建视频网站适合的场景
自建视频网站比较适合以下场景:
- 个人作品集网站,展示自己的原创视频作品。
- 课程网站,承载自己的付费或免费教程视频。
- 企业内部培训平台,存放内部培训录像。
- 小型团队的内容分发站点,不依赖第三方视频平台。
如果目标是做大型长视频平台,比如用户量几十万、视频时长几小时的高并发站点,则需要考虑转码集群、CDN 分发、弹幕评论、用户系统等复杂架构。但个人内容承载完全不需要一步到位,先用最小方案跑通,再逐步扩展即可。
2. 技术方案选型与环境准备
2.1 视频播放协议选型
浏览器播放视频,通常有两种思路:
一种是直接使用 HTML5 的video标签播放 MP4 文件。这种方式实现简单,适合小文件和短时长视频,但大文件拖动进度条时体验较差,而且不同浏览器对编码格式的支持不完全一致。
另一种是使用 HLS(HTTP Live Streaming)协议。HLS 会把视频切成一段一段的.ts文件,通过一个.m3u8索引文件来描述分段地址。播放时,播放器不断请求分段文件,实现边下边播。HLS 的优点是对服务端要求低,Nginx 就能支持;支持多码率切换;兼容性好,iOS 原生 Safari 可以直接播放.m3u8,Web 端通过 hls.js 也能兼容大多数浏览器。
本文采用 FFmpeg 转码切片 + Nginx 托管 + hls.js + DPlayer 播放器的方案。这也是目前个人视频网站中最稳妥、最省成本的一条路线。
2.2 环境准备
本文示例以 Ubuntu 22.04 为演示环境,Nginx 和 FFmpeg 使用 apt 安装。版本以你实际环境中 apt 源提供的为准,重点是掌握配置思路。
需要准备的软件:
| 软件 | 用途 |
|---|---|
| Nginx | Web 服务、视频文件托管 |
| FFmpeg | 视频转码、切片生成 HLS 文件 |
| hls.js | 浏览器端解析 HLS 协议 |
| DPlayer 或 Plyr | 视频播放器 UI |
在 Ubuntu 上安装基础软件:
sudo apt update sudo apt install -y nginx ffmpeg安装完成后,检查版本:
nginx -v ffmpeg -version这两个命令能正常输出版本信息,说明环境就绪。
2.3 项目目录结构
我建议把视频网站相关的文件统一放在一个目录下,方便维护。示例目录结构如下:
/data/video-site/ ├── html/ # 网站页面 │ ├── index.html # 播放页面 │ ├── css/ │ └── js/ └── videos/ # 转码后的视频文件 ├── lesson01/ │ ├── index.m3u8 │ ├── index0.ts │ ├── index1.ts │ └── ... └── lesson02/创建目录:
sudo mkdir -p /data/video-site/html sudo mkdir -p /data/video-site/videos之后,Nginx 的站点根目录指到/data/video-site/html,视频访问路径通过 location 单独指向/data/video-site/videos。
3. 视频处理:FFmpeg 转码与 HLS 切片
3.1 为什么要转码
手机、相机、录屏软件导出的视频,编码格式和参数往往五花八门。有的浏览器默认不支持某些编码,直接把原始视频放上去会导致黑屏或无法播放。另一个问题是文件体积:原始视频可能很大,直接在线播放会占用大量带宽。
转码有两个作用:
- 统一视频编码为 H.264 + AAC。H.264 是目前浏览器兼容性最好的视频编码,AAC 是最通用的音频编码。
- 进行 HLS 切片,把一个大文件拆成小分段,播放时按需加载,节省带宽和内存。
3.2 FFmpeg 转码命令
以/data/video-site/videos/source.mp4作为原始视频为例,转码并生成 HLS 文件:
ffmpeg -i /data/video-site/videos/source.mp4 \ -c:v libx264 \ -c:a aac \ -profile:v main \ -crf 23 \ -preset veryfast \ -hls_time 10 \ -hls_list_size 0 \ -hls_segment_filename "/data/video-site/videos/lesson01/index_%03d.ts" \ -f hls \ /data/video-site/videos/lesson01/index.m3u8参数含义:
| 参数 | 含义 |
|---|---|
-c:v libx264 | 视频编码使用 H.264 |
-c:a aac | 音频编码使用 AAC |
-profile:v main | H.264 编码等级,兼容性较好 |
-crf 23 | 视频质量参数,值越小质量越高,一般 18~28 之间 |
-preset veryfast | 编码速度预设,veryfast 速度快但体积略大 |
-hls_time 10 | 每个切片时长约 10 秒 |
-hls_list_size 0 | 生成的 m3u8 索引包含所有切片 |
-hls_segment_filename | 切片文件的命名规则 |
执行后,lesson01目录下会生成index.m3u8和若干.ts文件。
注意:-crf和-preset可以根据服务器性能调整。如果服务器 CPU 较强,可以改用-preset medium,在相同质量下体积更小;如果只是个人学习使用,veryfast更节省时间。
3.3 生成多清晰度 HLS(可选)
如果希望播放器支持清晰度切换,可以分别生成 1080p、720p、480p 的分辨率文件,再写一个主索引文件。
生成 720p 示例:
ffmpeg -i /data/video-site/videos/source.mp4 \ -vf scale=-2:720 \ -c:v libx264 \ -c:a aac \ -crf 23 \ -preset veryfast \ -hls_time 10 \ -hls_list_size 0 \ -hls_segment_filename "/data/video-site/videos/lesson01/720p_%03d.ts" \ -f hls \ /data/video-site/videos/lesson01/720p.m3u8主索引文件master.m3u8内容参考:
#EXTM3U #EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1280x720 720p.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=854x480 480p.m3u8主索引文件可以手动创建,也可以用 FFmpeg 配合脚本生成。手动创建时注意结尾要有空行,否则部分播放器可能解析失败。
3.4 转码后的产物说明
转码完成后,目录中会出现:
index.m3u8:播放索引文件,记录切片地址和时长信息。.ts文件:实际视频内容,每个切片通常几 MB 到十几 MB 不等。
上传或迁移视频时,m3u8文件和对应的ts文件需要放在同一个目录下,否则播放器找不到切片。实际部署时,一般保留一份原始视频备份,线上只保留转码后的 HLS 文件。
4. 搭建 Nginx 视频服务
4.1 安装与启动 Nginx
如果上面已经通过 apt 安装了 Nginx,直接启动服务:
sudo systemctl enable nginx sudo systemctl start nginx查看运行状态:
sudo systemctl status nginx出现active (running)表示服务正常运行。此时浏览器访问服务器 IP,如果看到 Nginx 默认欢迎页,说明 Web 服务已经可用。
4.2 配置站点与视频目录
Nginx 的站点配置文件通常放在/etc/nginx/conf.d/目录下。下面创建一个视频站点配置:
# /etc/nginx/conf.d/video-site.conf server { listen 80; server_name video.example.com; root /data/video-site/html; index index.html; # 视频文件访问路径 location /videos/ { alias /data/video-site/videos/; add_header Cache-Control "public, max-age=86400"; add_header Access-Control-Allow-Origin *; types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; } } }这里有几个关键点:
location /videos/把外部访问路径映射到本地视频目录。add_header Cache-Control让浏览器缓存切片,减少重复请求。add_header Access-Control-Allow-Origin *允许跨域请求,避免 hls.js 在部分场景下因为跨域报错。types添加m3u8和ts的 MIME 类型,防止浏览器把文件当作普通文本下载。
配置完成后,重载 Nginx:
sudo nginx -t sudo systemctl reload nginx浏览器访问http://服务器IP/videos/lesson01/index.m3u8,如果返回文件内容而不是 404,说明视频目录配置成功。
4.3 HTTPS 配置
HTTPS 是必须的。原因有两个:
一是浏览器安全策略越来越严格,非 HTTPS 页面里播放视频可能被拦截,而且很多功能需要安全上下文才能使用。
二是 HLS 播放器在 HTTPS 页面中请求http://视频地址时,会被当作混合内容拦截。
个人站点申请免费证书最方便的方式是使用 Let’s Encrypt。这里不粘贴具体命令,因为不同服务器和 DNS 服务商的操作方式不同。可以安装certbot后执行:
sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d video.example.comcertbot 会自动修改 Nginx 配置并配置证书续期。如果你的域名解析还没做好,会提示验证失败,需要先完成 DNS 解析。
4.4 防盗链配置
视频文件放在公网后,别人可能会直接盗用你的视频地址。最简单的防护是检查Referer请求头:
location /videos/ { alias /data/video-site/videos/; # 只允许本站引用 valid_referers none blocked server_names *.example.com; if ($invalid_referer) { return 403; } }但Referer可以被伪造,所以这个方案适合基础防护。更严格的做法是使用 Nginx 的secure_link模块,为视频 URL 生成带时效的签名地址。反向代理、防盗链、访问控制的话题比较深,建议在网站跑通后再逐步加强。
5. 编写视频播放页面
5.1 播放器选型
Web 端播放 HLS 视频,最常用的方案是 hls.js 配合 DPlayer 或 Plyr。
- hls.js 负责把
.m3u8解析成浏览器能播放的 Media Source Extensions 数据。 - DPlayer 提供播放按钮、进度条、倍速、弹幕等 UI 能力。
- Plyr 则更简洁,适合追求轻量界面的站点。
我习惯用 DPlayer + hls.js,因为 DPlayer 的 UI 更适合中文用户,API 也比较简单。
5.2 完整 HTML 播放页面
下面是一个可以直接使用的index.html:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>我的视频站</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.css"> </head> <body> <h1>我的视频站</h1> <div id="player"></div> <script src="https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.js"></script> <script> var dp = new DPlayer({ container: document.getElementById('player'), autoplay: false, theme: '#b7daff', video: { url: '/videos/lesson01/index.m3u8', type: 'customHLS' } }); </script> </body> </html>如果你不想引入 DPlayer,只想用原生video标签,可以这样写:
<video id="video" controls></video> <script src="https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js"></script> <script> var video = document.getElementById('video'); if (hls.isSupported()) { var hls = new Hls(); hls.loadSource('/videos/lesson01/index.m3u8'); hls.attachMedia(video); } else if (video.canPlayType('application/vnd.apple.mpegurl')) { video.src = '/videos/lesson01/index.m3u8'; } </script>原生写法更适合简单页面,DPlayer 则更适合需要界面美化和交互功能的情况。
5.3 播放列表与页面简单美化
视频数量少的时候,直接在页面里写死播放列表即可。数量多的时候,建议用一个 JSON 文件维护视频列表,再用 JavaScript 动态渲染。
<div class="playlist"> <a href="#" onclick="loadVideo('lesson01/index.m3u8', '第一课:环境搭建')">第一课:环境搭建</a> <a href="#" onclick="loadVideo('lesson02/index.m3u8', '第二课:FFmpeg转码')">第二课:FFmpeg转码</a> </div>function loadVideo(url, title) { dp.switchVideo({ url: url, type: 'customHLS' }); document.title = title; }页面美化方面,给正文设置合适的max-width,让播放器居中显示即可。重点不是把页面做得多花哨,而是保证功能稳定。
6. 部署上线与整体验证
6.1 本地验证流程
在访问公网之前,先在本机或服务器本地验证:
- 确认
m3u8和ts文件生成完整。 - 确认 Nginx 配置语法正确。
- 用
curl测试视频索引文件是否可访问:
curl -I http://127.0.0.1/videos/lesson01/index.m3u8返回200 OK且Content-Type为application/vnd.apple.mpegurl,说明服务正常。
6.2 域名解析与上线
在 DNS 服务商处添加一条 A 记录,将video.example.com解析到服务器公网 IP,然后执行 certbot 配置 HTTPS。
完成后访问https://video.example.com,打开播放页面。点击播放按钮,如果视频能正常播放,说明整套链路已经跑通。
6.3 验证视频清晰度和切片加载
浏览器按 F12 打开开发者工具,切到 Network 面板,可以看到播放器会每隔 10 秒左右请求一个.ts文件。这说明 HLS 切片生效,内容是按需加载的,而不是一次性请求整个视频文件。
如果看到 404 或 403 报错,重点检查:
- 切片文件路径是否正确。
- Nginx 的 alias 配置是否写对。
- 防盗链规则是否误伤本站请求。
7. 常见问题与排查思路
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 访问 m3u8 返回 404 | 视频文件未生成或路径错误 | 检查 FFmpeg 输出目录,检查 Nginx alias 路径 |
| 访问 m3u8 变成下载文件 | MIME 类型未配置 | 在 Nginx location 中添加 m3u8 的 types 配置 |
| 播放器黑屏无法播放 | 视频编码不受支持 | 确认转码参数使用了libx264和aac |
| 跨域报错 | hls.js 请求被 CORS 拦截 | 为视频目录添加Access-Control-Allow-Origin |
| 播放卡顿、缓冲慢 | 视频码率太高或服务器带宽不足 | 降低-crf值或转出多清晰度版本 |
| 拖动进度条慢 | 切片太长或服务器无缓存 | 缩短-hls_time,配置 Nginx 缓存 |
| HTTPS 页面视频无法播放 | 页面和视频协议不一致 | 将视频地址改为 HTTPS,配置证书 |
8. 工程建议与安全边界
8.1 版权边界要明确
这是我必须反复强调的一点。自建视频网站只是换了一个内容分发渠道,不改变内容本身的法律属性。你可以把自建网站理解为一个“私有展厅”,但展厅里摆放的物品仍然必须是你有权利展示的物品。
发布到公网的视频,无论放在哪个平台,都要注意以下原则:
- 不使用未授权的电影、电视剧、综艺、体育赛事片段。
- 不盗录他人付费课程、音乐、软件。
- 自己录制的视频如果包含他人肖像,需确认对方同意发布。
简单判断标准:如果视频内容本身没有版权问题,自建网站才是安全的;如果内容有问题,自建网站同样会面临侵权投诉和相应的法律责任。
8.2 服务器安全加固
自建网站暴露在公网,服务器安全不能忽略。最低限度做到以下几点:
- 修改 SSH 默认端口,或至少使用强密码 / 密钥登录。
- 关闭不必要的端口,只对外开放 80、443 和 SSH。
- 定期执行系统更新:
sudo apt update && sudo apt upgrade -y- Nginx 配置中关闭服务器版本号显示,减少信息泄露。
8.3 视频文件备份
视频文件是核心资产。服务器磁盘故障、误删除都可能导致内容丢失。建议:
- 本地保留一份原始视频。
- 转码后的 HLS 文件也做异地备份。
- 使用对象存储时,开启版本控制或跨区域复制。
备份策略不需要复杂,关键是“定期执行”和“恢复演练”。不要等到文件丢失了才发现备份不可用。
8.4 成本控制
个人视频网站的成本主要有三块:服务器费用、存储费用、流量费用。
视频文件大的话,云服务器硬盘可能不够用,这种情况下可以把视频放到对象存储。Nginx 不需要存储实际文件,只负责反向代理对象存储地址或重定向到 CDN。对象存储的费用按存储量和外网流量计费,用量不大时每月成本很低。
我见过不少个人项目,视频总时长只有几十小时,一个月流量费用只有几块钱。等到流量真的大了,说明网站已经有一定访问量,那时候再考虑 CDN 和商业化也来得及。
9. 总结与实践建议
从“视频总被举报下架”到“自己搭了个网站”,整个流程回顾下来其实只有四步:用 FFmpeg 转码切片、用 Nginx 托管文件、用 DPlayer 渲染播放、用 HTTPS 保证安全访问。这四步跑通后,一个能承载个人视频内容的网站就上线了。
接下来可以继续学习的方向还有不少:Nginx 反向代理与负载均衡、对象存储接入、CDN 加速、多码率切换、用户权限体系、后台管理界面、视频转码队列、统计埋点等。每一个方向都可以根据实际需求逐步扩展。
但最优先的实践建议是:先跑通最小可用版本,再谈优化。没有必要第一天就搞一整套分布式转码集群。先用一台小服务器跑起来,确认视频能稳定播放、页面访问正常、备份策略到位,然后根据线上访问情况逐步迭代。
自建网站不会立刻给你带来流量,但它能给你一个完全自主的内容空间。对长期做内容的人来说,这份自主权是值得投入的。希望这篇教程能帮你把第一个线上版本顺利搭起来。如果中间遇到视频转码、Nginx 配置或播放器兼容性的问题,可以对照上面的排查思路逐项检查。