ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

自建视频网站:FFmpeg转码+Nginx+HLS播放全流程

自建视频网站:FFmpeg转码+Nginx+HLS播放全流程 最近经常有朋友问我明明是自己辛苦拍的视频发在平台上却总被限流、被举报申诉流程又长又慢即使最后恢复了流量和推荐也已经损失大半。与其被动等待平台审核不如把内容放回自己手里。这篇文章就围绕“自建一个视频网站来承载自己的视频内容”这件事讲清楚从视频转码、服务器配置到网页播放器的完整流程。自建视频网站并不是一个特别复杂的事核心只有几个环节给视频做转码和切片、用 Nginx 托管视频目录、写一个支持 HLS 播放的网页播放器。这套方案适合个人作品集、课程视频、企业内部培训视频、小团队内容分发等场景。下面我按实际搭建顺序把步骤完整拆开。1. 为什么选择自建视频网站1.1 视频被举报下架的痛点在视频平台上传内容本质上是在平台规则下获取流量。平台会对内容进行机器审核和人工审核同时允许其他用户对视频发起举报。即使是原创且合规的内容也可能因为误判、恶意举报或版权投诉被下架。平台申诉机制虽然存在但流程通常较慢你需要提供原始素材、说明创作过程、等待人工复核。这期间视频已经无法播放推荐权重也会受到影响。对以视频为作品展示的个人创作者来说这种不确定性是难以接受的。自建视频网站解决的核心问题不是“流量”而是“控制权”。视频文件放在自己的服务器或对象存储中页面、播放器、清晰度、封面都是自己控制。只要内容本身不违规就不会有第三方因为举报直接下架你的内容。但这里必须强调自建网站不等于可以发布违规内容。版权同样是红线盗用别人的视频、电影、电视剧、软件录制内容放在自己网站上同样会面临侵权风险。自建视频网站适合承载的是原创内容、已获授权内容或者企业内部培训资料。1.2 自建视频网站的组成一个最简单的视频网站由以下几个部分组成模块作用常用方案域名对外访问入口阿里云、腾讯云、Cloudflare 等服务器运行 Web 服务、存放视频Linux 云服务器、本地 NAS视频处理转码、切片、压缩FFmpegWeb 服务托管 HTML 和视频文件Nginx播放器浏览器中播放视频hls.js、DPlayer、Plyr文件存储存放转码后的视频文件本地磁盘、对象存储 OSS以上每个环节都可以单独替换。个人快速起步时一台低配云服务器加本地磁盘就够了视频量大了再把文件迁移到对象存储配合 CDN 分发。1.3 自建视频网站适合的场景自建视频网站比较适合以下场景个人作品集网站展示自己的原创视频作品。课程网站承载自己的付费或免费教程视频。企业内部培训平台存放内部培训录像。小型团队的内容分发站点不依赖第三方视频平台。如果目标是做大型长视频平台比如用户量几十万、视频时长几小时的高并发站点则需要考虑转码集群、CDN 分发、弹幕评论、用户系统等复杂架构。但个人内容承载完全不需要一步到位先用最小方案跑通再逐步扩展即可。2. 技术方案选型与环境准备2.1 视频播放协议选型浏览器播放视频通常有两种思路一种是直接使用 HTML5 的video标签播放 MP4 文件。这种方式实现简单适合小文件和短时长视频但大文件拖动进度条时体验较差而且不同浏览器对编码格式的支持不完全一致。另一种是使用 HLSHTTP Live Streaming协议。HLS 会把视频切成一段一段的.ts文件通过一个.m3u8索引文件来描述分段地址。播放时播放器不断请求分段文件实现边下边播。HLS 的优点是对服务端要求低Nginx 就能支持支持多码率切换兼容性好iOS 原生 Safari 可以直接播放.m3u8Web 端通过 hls.js 也能兼容大多数浏览器。本文采用 FFmpeg 转码切片 Nginx 托管 hls.js DPlayer 播放器的方案。这也是目前个人视频网站中最稳妥、最省成本的一条路线。2.2 环境准备本文示例以 Ubuntu 22.04 为演示环境Nginx 和 FFmpeg 使用 apt 安装。版本以你实际环境中 apt 源提供的为准重点是掌握配置思路。需要准备的软件软件用途NginxWeb 服务、视频文件托管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 mainH.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:BANDWIDTH2500000,RESOLUTION1280x720 720p.m3u8 #EXT-X-STREAM-INF:BANDWIDTH800000,RESOLUTION854x480 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-age86400; 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 类型防止浏览器把文件当作普通文本下载。配置完成后重载 Nginxsudo 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 langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title我的视频站/title link relstylesheet hrefhttps://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.css /head body h1我的视频站/h1 div idplayer/div script srchttps://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js/script script srchttps://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 idvideo controls/video script srchttps://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 classplaylist a href# onclickloadVideo(lesson01/index.m3u8, 第一课环境搭建)第一课环境搭建/a a href# onclickloadVideo(lesson02/index.m3u8, 第二课FFmpeg转码)第二课FFmpeg转码/a /divfunction 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 -yNginx 配置中关闭服务器版本号显示减少信息泄露。8.3 视频文件备份视频文件是核心资产。服务器磁盘故障、误删除都可能导致内容丢失。建议本地保留一份原始视频。转码后的 HLS 文件也做异地备份。使用对象存储时开启版本控制或跨区域复制。备份策略不需要复杂关键是“定期执行”和“恢复演练”。不要等到文件丢失了才发现备份不可用。8.4 成本控制个人视频网站的成本主要有三块服务器费用、存储费用、流量费用。视频文件大的话云服务器硬盘可能不够用这种情况下可以把视频放到对象存储。Nginx 不需要存储实际文件只负责反向代理对象存储地址或重定向到 CDN。对象存储的费用按存储量和外网流量计费用量不大时每月成本很低。我见过不少个人项目视频总时长只有几十小时一个月流量费用只有几块钱。等到流量真的大了说明网站已经有一定访问量那时候再考虑 CDN 和商业化也来得及。9. 总结与实践建议从“视频总被举报下架”到“自己搭了个网站”整个流程回顾下来其实只有四步用 FFmpeg 转码切片、用 Nginx 托管文件、用 DPlayer 渲染播放、用 HTTPS 保证安全访问。这四步跑通后一个能承载个人视频内容的网站就上线了。接下来可以继续学习的方向还有不少Nginx 反向代理与负载均衡、对象存储接入、CDN 加速、多码率切换、用户权限体系、后台管理界面、视频转码队列、统计埋点等。每一个方向都可以根据实际需求逐步扩展。但最优先的实践建议是先跑通最小可用版本再谈优化。没有必要第一天就搞一整套分布式转码集群。先用一台小服务器跑起来确认视频能稳定播放、页面访问正常、备份策略到位然后根据线上访问情况逐步迭代。自建网站不会立刻给你带来流量但它能给你一个完全自主的内容空间。对长期做内容的人来说这份自主权是值得投入的。希望这篇教程能帮你把第一个线上版本顺利搭起来。如果中间遇到视频转码、Nginx 配置或播放器兼容性的问题可以对照上面的排查思路逐项检查。
返回列表