1. 项目概述
这个基于SpringBoot+Vue的在线视频播放器项目,本质上是一个轻量级的流媒体服务平台。它解决了传统视频网站架构臃肿、开发成本高的问题,采用前后端分离架构实现了一套可快速部署的视频播放解决方案。
我在实际开发中发现,这类系统最核心的挑战在于如何平衡视频传输效率与播放体验。传统方案要么过度依赖第三方SDK导致定制困难,要么自行开发又面临编解码兼容性问题。我们这个方案通过合理的架构设计,在保证基础功能完整性的同时,保持了足够的灵活性。
2. 技术架构解析
2.1 后端技术选型
SpringBoot 2.7.x作为后端框架,主要基于以下考虑:
- 内嵌Tomcat简化部署
- 自动配置减少XML配置
- 丰富的Starter依赖
视频处理模块采用FFmpeg进行转码,关键配置参数:
bash复制ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k output.mp4
这里CRF值控制在23-28之间,在画质和文件大小间取得平衡。
数据库使用MySQL 8.0,视频元数据表设计要点:
sql复制CREATE TABLE `video` (
`id` bigint NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`cover_url` varchar(512) DEFAULT NULL,
`video_url` varchar(512) NOT NULL,
`duration` int DEFAULT NULL COMMENT '秒数',
`resolution` varchar(20) DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.2 前端技术栈
Vue 3 + Element Plus的组合提供了良好的开发体验:
- 使用vue-video-player处理视频播放
- axios封装了带Token的请求拦截
- 路由懒加载优化首屏性能
播放器核心配置示例:
javascript复制const playerOptions = {
autoplay: false,
controls: true,
sources: [{
type: 'video/mp4',
src: 'https://example.com/video.mp4'
}],
poster: 'https://example.com/poster.jpg'
}
3. 核心功能实现
3.1 视频上传与处理
文件上传采用分片上传策略:
- 前端将文件切分为2MB的块
- 使用SparkMD5计算文件指纹
- 后端通过Redis记录上传进度
- 最后合并分片并触发转码任务
关键的上传接口实现:
java复制@PostMapping("/upload")
public ResponseEntity<String> uploadChunk(
@RequestParam("file") MultipartFile file,
@RequestParam("chunkNumber") int chunkNumber,
@RequestParam("totalChunks") int totalChunks,
@RequestParam("identifier") String identifier) {
// 存储分片到临时目录
String tempDir = "/tmp/uploads/" + identifier;
File chunkFile = new File(tempDir, chunkNumber + ".part");
file.transferTo(chunkFile);
// 更新Redis进度
redisTemplate.opsForValue().increment("upload:" + identifier);
return ResponseEntity.ok("Chunk uploaded");
}
3.2 自适应码率播放
实现HLS自适应码率需要:
- 使用FFmpeg生成多码率版本
bash复制ffmpeg -i input.mp4 \
-map 0:v:0 -map 0:a:0 -c:v libx264 -crf 22 -preset fast -c:a copy -f hls -hls_time 10 -hls_list_size 0 -hls_segment_filename "output_480p_%03d.ts" -s 854x480 output_480p.m3u8 \
-map 0:v:0 -map 0:a:0 -c:v libx264 -crf 24 -preset fast -c:a copy -f hls -hls_time 10 -hls_list_size 0 -hls_segment_filename "output_720p_%03d.ts" -s 1280x720 output_720p.m3u8
- 创建主m3u8播放列表:
code复制#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=854x480
480p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1500000,RESOLUTION=1280x720
720p.m3u8
4. 性能优化实践
4.1 前端加载优化
- 视频预加载策略:
- 首屏只加载480P版本
- 根据网络质量动态切换
- 使用Intersection Observer实现懒加载
- 关键性能指标:
javascript复制// 监控缓冲进度
player.on('progress', function() {
const buffered = player.bufferedPercent();
if (buffered < 20 && !loading) {
showLoadingIndicator();
}
});
4.2 后端缓存策略
采用多级缓存架构:
- Nginx静态资源缓存
nginx复制location ~* \.(m3u8|ts)$ {
expires 7d;
add_header Cache-Control "public";
}
- Redis热点视频缓存
- MySQL查询缓存
实测数据显示,引入缓存后API响应时间从平均120ms降至35ms。
5. 安全防护方案
5.1 防盗链措施
- Nginx配置Referer检查:
nginx复制valid_referers none blocked server_names ~\.example\.com;
if ($invalid_referer) {
return 403;
}
- 动态生成临时播放URL:
java复制public String generateSignedUrl(String videoPath) {
long expiry = System.currentTimeMillis() + 3600000; // 1小时有效
String signature = HmacSHA256(secretKey, videoPath + expiry);
return String.format("%s?expiry=%d&sign=%s",
videoPath, expiry, signature);
}
5.2 内容安全策略
- 文件上传安全检查:
- 校验真实文件类型(非扩展名)
- 病毒扫描
- 内容敏感度检测
- 视频内容审核流程:
mermaid复制graph TD
A[上传] --> B[自动审核]
B -->|通过| C[发布]
B -->|可疑| D[人工审核]
D -->|通过| C
D -->|拒绝| E[删除]
6. 部署与运维
6.1 容器化部署
Docker Compose编排示例:
yaml复制version: '3'
services:
app:
build: .
ports:
- "8080:8080"
depends_on:
- redis
- mysql
redis:
image: redis:alpine
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
6.2 监控方案
- Prometheus监控指标:
- 视频请求成功率
- 转码任务队列长度
- 平均响应时间
- 关键告警规则:
yaml复制groups:
- name: video.rules
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.1
for: 10m
7. 踩坑实录
- 跨域问题解决方案:
- 精确配置CORS白名单
- 预检请求缓存
- 带凭证的请求处理
- iOS兼容性问题:
- 必须使用HTTPS
- 需要正确配置MIME类型
- 注意autoplay策略限制
- 内存泄漏排查:
- 使用VisualVM监控
- 发现未关闭的FFmpeg进程
- 增加进程超时回收机制
这个项目最让我意外的是移动端适配的复杂性。不同设备、不同浏览器对视频播放的实现差异巨大,我们最终不得不为iOS单独实现了一套播放逻辑。另外,转码任务的管理也是个难点,特别是当并发量上升时,如何平衡转码质量和系统负载需要反复调优。