我的个人网站:乐乐主题创作室
实现视频断点续播需要前后端配合,主要包括:
<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:00span> / <span id="totalTime">00:00span>
div>
div>
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);
}
}
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-jpaartifactId>
dependency>
<dependency>
<groupId>com.h2databasegroupId>
<artifactId>h2artifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
dependencies>
@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();
}
}
@Repository
public interface VideoProgressRepository extends JpaRepository<VideoProgress, Long> {
Optional<VideoProgress> findByUserIdAndVideoId(String userId, String videoId);
}
@Service
@RequiredArgsConstructor
public class VideoService {
private final VideoProgressRepository videoProgressRepository;
public VideoProgress getVideoProgress(String userId, String videoId) {
return videoProgressRepository.findByUserIdAndVideoId(userId, videoId)
.orElse(new VideoProgress()<