1. 项目概述
这个基于SpringBoot+Vue的在线视频播放器项目,本质上是一个具备完整前后端分离架构的流媒体应用。我花了三个月时间从零搭建这个系统,期间踩过不少坑,也积累了一些值得分享的经验。
从技术架构来看,前端采用Vue生态(Vue3+Element Plus+Vite),后端基于SpringBoot 2.7.x构建,视频存储使用MinIO对象存储,数据库选用MySQL 8.0。整个系统实现了视频上传、转码、分类管理、用户认证、播放记录等核心功能模块。
2. 核心需求解析
2.1 视频处理流水线设计
视频上传后的处理流程是系统的核心链路,我设计的处理步骤如下:
- 前端分片上传(每片5MB)
- 后端接收分片并暂存临时目录
- 合并分片并生成唯一文件ID
- 调用FFmpeg进行转码(H.264编码,分辨率自适应)
- 生成视频封面(截取第10秒画面)
- 元数据入库(视频时长、大小、格式等)
关键代码片段(SpringBoot):
java复制// 分片合并逻辑
public String mergeChunks(String fileKey, int totalChunks) {
File outputFile = new File(tempDir, fileKey);
try (FileChannel outChannel = new FileOutputStream(outputFile).getChannel()) {
for (int i = 1; i <= totalChunks; i++) {
File chunkFile = new File(tempDir, fileKey + ".part" + i);
try (FileChannel inChannel = new FileInputStream(chunkFile).getChannel()) {
inChannel.transferTo(0, inChannel.size(), outChannel);
}
chunkFile.delete();
}
return fileKey;
} catch (IOException e) {
throw new RuntimeException("合并分片失败", e);
}
}
2.2 播放器核心功能实现
前端播放器采用Video.js + HLS.js方案,主要考虑因素:
- 兼容性:支持MP4、HLS、DASH等多种格式
- 自适应:根据网络状况自动切换清晰度
- 扩展性:易于集成字幕、弹幕等功能
播放器初始化配置:
javascript复制const player = videojs('my-video', {
controls: true,
autoplay: false,
responsive: true,
html5: {
vhs: {
overrideNative: true,
enableLowInitialPlaylist: true
}
}
});
3. 关键技术实现细节
3.1 视频转码方案选型
经过对比测试,最终选择FFmpeg作为转码工具,关键参数配置:
bash复制ffmpeg -i input.mp4 \
-c:v libx264 -profile:v high -preset slower -crf 23 \
-c:a aac -b:a 128k \
-vf "scale=w='if(gt(iw,ih),min(1280,iw),-2)':'if(gt(iw,ih),-2,min(720,ih))'" \
-movflags +faststart \
output.mp4
参数说明:
-preset slower:平衡编码速度和质量-crf 23:推荐的质量范围(18-28)scale滤镜:实现分辨率自适应-movflags +faststart:优化流式播放
3.2 权限控制设计
采用RBAC模型实现细粒度权限控制:
mermaid复制classDiagram
class User {
+Long id
+String username
+String password
}
class Role {
+Long id
+String name
}
class Permission {
+Long id
+String code
+String description
}
User "n" -- "m" Role
Role "n" -- "m" Permission
Spring Security配置核心:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/video/upload").authenticated()
.anyRequest().permitAll()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()));
}
}
4. 性能优化实践
4.1 前端加载优化
- 视频列表懒加载:Intersection Observer API实现
- 封面图延迟加载:使用loading="lazy"
- 路由懒加载:Vue异步组件
- 关键CSS内联:提高首屏渲染速度
优化前后对比(Lighthouse评分):
| 指标 | 优化前 | 优化后 |
|---|---|---|
| FCP | 2.8s | 1.2s |
| LCP | 4.5s | 2.1s |
| TTI | 3.2s | 1.8s |
4.2 后端缓存策略
采用多级缓存架构:
- 本地缓存(Caffeine):高频访问的元数据
- Redis缓存:热门视频信息
- CDN缓存:静态资源和视频流
缓存配置示例:
java复制@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.initialCapacity(100)
.maximumSize(1000)
.expireAfterWrite(30, TimeUnit.MINUTES));
return cacheManager;
}
}
5. 部署与监控
5.1 Docker化部署
完整的docker-compose.yml配置:
yaml复制version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:6.2
ports:
- "6379:6379"
minio:
image: minio/minio
ports:
- "9000:9000"
volumes:
- minio_data:/data
command: server /data
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
- minio
frontend:
build: ./frontend
ports:
- "3000:3000"
volumes:
mysql_data:
minio_data:
5.2 监控方案
- Prometheus + Grafana监控体系
- Spring Boot Actuator暴露指标
- ELK日志收集系统
- 前端埋点监控(使用Sentry)
关键监控指标:
- 视频播放成功率
- API响应时间P99
- 转码任务队列积压
- 存储空间使用率
6. 踩坑经验分享
- 跨域问题:开发环境要配置Vite代理,生产环境需要Nginx正确处理CORS头
- 视频卡顿:HLS分片大小建议2-4秒,太大会影响起播速度
- 内存泄漏:Video.js实例需要手动dispose,否则SPA路由切换会积累
- 移动端适配:iOS对自动播放策略严格,需要用户交互才能触发
- 字幕同步:WebVTT时间轴必须严格对齐视频,误差超过0.5秒就会不同步
7. 项目扩展方向
- 弹幕功能实现:WebSocket实时通信
- 智能推荐系统:基于用户行为的协同过滤
- 多语言支持:i18n国际化方案
- 直播功能扩展:RTMP推流+FLV播放
- DRM内容保护:Widevine集成
这个项目从技术选型到最终上线,让我对流媒体领域有了更深入的理解。最大的收获是认识到视频处理各个环节的性能瓶颈都需要针对性优化,任何一个环节处理不当都会影响最终用户体验。