文章目录
🌐 我的个人网站:乐乐主题创作室
视频断点续播功能实现方案
核心思路
实现视频断点续播需要前后端配合,主要包括:
- 前端记录播放进度
- 后端存储进度信息
- 视频请求支持范围请求(Range Request)
前端实现
HTML结构
<div class="video-container">
<video id="videoPlayer" controls>
<source src="/api/video/stream?videoId=123" type="video/mp4">
</video>
<div class="video-controls">
<span id="currentTime">00:00</span> / <span id="totalTime">00:00</span>
</div>
</div>
JavaScript实现
const videoPlayer = document.getElementById('videoPlayer');
const videoId = '123'; // 视频ID,实际应从URL或其他地方获取
// 页面加载时获取上次播放进度
window.addEventListener('DOMContentLoaded', async () => {
try {
const response = await fetch(`/api/video/progress?videoId=${
videoId}`);
const data = await response.json();
if (data.lastPosition) {
videoPlayer.currentTime = data.lastPosition;
}
} catch (error) {
console.error('获取播放进度失败:', error);
}
});
// 定期保存播放进度(每5秒)
let progressTimer = null;
videoPlayer.addEventListener('play', () => {
progressTimer = setInterval(() => {
saveVideoProgress(videoPlayer.currentTime);
}, 5000);
});
// 暂停和结束时保存进度
videoPlayer.addEventListener('pause', () => {
clearInterval(progressTimer);
saveVideoProgress(videoPlayer.currentTime);
});
videoPlayer.addEventListener('ended', () => {
clearInterval(progressTimer);
saveVideoProgress(0); // 播放结束,重置进度
});
// 保存播放进度到后端
async function saveVideoProgress(currentTime) {
try {
await fetch('/api/video/progress', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
videoId: videoId,
position: currentTime
})
});
} catch (error) {
console.error('保存播放进度失败:', error);
}
}
Spring Boot后端实现
1.依赖配置(pom.xml)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
2.实体类
@Entity
@Data
public class VideoProgress {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String userId;
private String videoId;
private Double position;
private LocalDateTime updatedAt;
@PrePersist
@PreUpdate
public void prePersist() {
updatedAt = LocalDateTime.now();
}
}
3.存储库接口
@Repository
public interface VideoProgressRepository extends JpaRepository<VideoProgress, Long> {
Optional<VideoProgress> findByUserIdAndVideoId(String userId, String videoId);
}
4.服务层
@Service
@RequiredArgsConstructor
public class VideoService {
private final VideoProgressRepository videoProgressRepository;
public VideoProgress getVideoProgress(String userId, String videoId) {
return videoProgressRepository.findByUserIdAndVideoId(userId, videoId)
.orElse(new VideoProgress()<