📌 从 CDN 到 TS 文件 —— 腾讯视频点播系统的幕后逻辑
腾讯视频的“秒开+高清+不卡顿”体验背后,隐藏着极致的工程优化:M3U8 切片协议、CDN 缓存、HLS 点播、预加载与降级兜底机制。本篇我们将从 0 实现一个本地 视频点播系统原型,理解TS 分片播放、索引加载与 CDN 配合机制。
🧠 一、VOD 系统的核心链路
[前端播放器] ← M3U8 索引
↓
[CDN 节点] ← TS 分片资源
↓
[后端 VOD 服务](备份/转码/鉴权)
- M3U8:播放索引文件(列出每段 ts 地址)
- TS 文件:短视频片段(2~10s)
- CDN:缓存热点分片,优化就近加载
✅ 效果演示目标
我们将搭建一个本地小型点播系统:
- 支持上传视频自动切片(生成 TS + M3U8)
- 使用前端 video 标签加载 M3U8 播放
- 模拟 CDN 返回 TS 片段
- 展示运行效果与控制台日志
⚙️ 二、代码实战:Node.js + FFmpeg + Express 搭建本地 VOD 系统
1. 环境准备
- 安装 FFmpeg(切片使用)
- 安装依赖:
npm install express multer
2. 后端:上传视频并切片生成 M3U8
const express = require('express');
const multer = require('multer');
const { exec } = require('child_process');
const app = express();
const upload = multer({ dest: 'uploads/' });
app.post('/upload', upload.single('video'), (req, res) => {
const input = req.file.path;
const outputDir = `vod/${req.file.filename}`;
const cmd = `mkdir -p ${outputDir} && ffmpeg -i ${input} -codec copy -start_number 0 -hls_time 5 -hls_list_size 0 -f hls ${outputDir}/index.m3u8`;
exec(cmd, (err) => {
if (err) return res.status(500).send('切片失败');
res.send({ url: `/vod/${req.file.filename}/index.m3u8` });
});
});
app.use('/vod', express.static('vod'));
app.listen(3000, () => console.log('VOD 服务启动:http://localhost:3000'));
✅ 运行结果展示
- 上传完成后,浏览器访问
http://localhost:3000/vod/<file_id>/index.m3u8 - Chrome 控制台 Network 面板可看到请求多个
.ts文件,如:
✔ index.m3u8
✔ segment0.ts
✔ segment1.ts
...
播放器控制台日志:
[HLS.js] manifest loaded
[HLS.js] fragment loaded: segment0.ts
[HLS.js] buffer appended
3. 前端播放器页面(index.html)
<video id="player" controls width="600"></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script>
const video = document.getElementById('player');
const m3u8Url = 'http://localhost:3000/vod/xxxx/index.m3u8'; // 替换为实际路径
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(m3u8Url);
hls.attachMedia(video);
}
</script>
❗ 易错点 & 排错提示
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 播放器加载不到视频 | TS 文件 404 | 确保 /vod/ 路径正确暴露;TS 文件名与 M3U8 中一致 |
| FFmpeg 切片失败 | 未安装/未在 PATH 中 | 终端执行 ffmpeg -version 验证 |
| TS 播放卡顿 | TS 过大 | 调整 -hls_time 5 为更小值,如 2s |
| MIME 错误 | TS 文件未设置 MIME 类型 | 使用 Express static 自动配置或手动设置响应头 |
✍️ 四、总结与思考
- 腾讯 VOD 系统通过 M3U8 索引 + TS 分片的方式实现 低延迟加载 + 分段缓存
- CDN 作为中间层扮演“就近分发 + 熔断降级 + 热点缓存”的关键角色
- 本地 Demo 帮你理解播放前发生了什么,也能用于企业私有视频平台快速搭建