从数据库到播放器:Java视频续播功能完整实现解析

在Java中实现视频续播功能,通常需要结合后端存储(如数据库)和前端播放器配合。以下是关键步骤和代码示例:


实现思路

  1. 记录播放进度:播放时定期保存当前播放位置

  2. 存储进度数据:将进度关联用户/设备ID和视频ID存储

  3. 恢复播放:再次打开视频时读取上次保存的位置

  4. 前端配合:播放器跳转到指定时间点


后端实现(Spring Boot示例)

1. 实体类 - 播放记录
java 复制代码
@Entity
public class VideoProgress {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String userId;    // 用户标识(可用设备ID替代)
    private String videoId;   // 视频唯一标识
    private double lastPosition; // 最后播放位置(秒)
    private Date updateTime;
    
    // getters/setters
}
2. Repository接口
java 复制代码
public interface VideoProgressRepository extends JpaRepository<VideoProgress, Long> {
    VideoProgress findByUserIdAndVideoId(String userId, String videoId);
}
3. Service层
java 复制代码
@Service
public class VideoService {
    
    @Autowired
    private VideoProgressRepository progressRepo;

    // 保存播放进度
    public void savePlaybackPosition(String userId, String videoId, double position) {
        VideoProgress progress = progressRepo.findByUserIdAndVideoId(userId, videoId);
        
        if (progress == null) {
            progress = new VideoProgress();
            progress.setUserId(userId);
            progress.setVideoId(videoId);
        }
        
        progress.setLastPosition(position);
        progress.setUpdateTime(new Date());
        progressRepo.save(progress);
    }

    // 获取播放进度
    public double getLastPosition(String userId, String videoId) {
        VideoProgress progress = progressRepo.findByUserIdAndVideoId(userId, videoId);
        return (progress != null) ? progress.getLastPosition() : 0;
    }
}
4. Controller层
java 复制代码
@RestController
@RequestMapping("/api/video")
public class VideoController {
    
    @Autowired
    private VideoService videoService;

    // 更新进度接口
    @PostMapping("/progress")
    public ResponseEntity<Void> updateProgress(
            @RequestParam String userId,
            @RequestParam String videoId,
            @RequestParam double position) {
        
        videoService.savePlaybackPosition(userId, videoId, position);
        return ResponseEntity.ok().build();
    }

    // 获取进度接口
    @GetMapping("/progress")
    public ResponseEntity<Double> getProgress(
            @RequestParam String userId,
            @RequestParam String videoId) {
        
        double position = videoService.getLastPosition(userId, videoId);
        return ResponseEntity.ok(position);
    }
}

前端实现(JavaScript示例)

使用HTML5 video标签配合AJAX请求:

html 复制代码
<video id="myPlayer" controls>
  <source src="/videos/sample.mp4" type="video/mp4">
</video>

<script>
const player = document.getElementById('myPlayer');
const userId = "device123"; // 实际中从登录信息获取
const videoId = "video456";

// 1. 尝试获取历史进度
fetch(`/api/video/progress?userId=${userId}&videoId=${videoId}`)
  .then(res => res.json())
  .then(position => {
    if(position > 0) {
      player.currentTime = position; // 跳转到续播位置
    }
  });

// 2. 定时保存播放进度(每5秒)
setInterval(() => {
  if(!player.paused) {
    const position = player.currentTime;
    fetch(`/api/video/progress?userId=${userId}&videoId=${videoId}&position=${position}`, {
      method: 'POST'
    });
  }
}, 5000); // 5秒保存一次

// 3. 视频结束时重置进度(可选)
player.addEventListener('ended', () => {
  fetch(`/api/video/progress?userId=${userId}&videoId=${videoId}&position=0`, {
    method: 'POST'
  });
});
</script>

关键优化点

  1. 节流控制 :使用setTimeout替代setInterval避免并发问题

  2. 本地缓存:可先用localStorage暂存进度,网络恢复后同步到服务器

  3. 进度验证:后端校验position不超过视频总时长

  4. 过期策略:超过30天的进度自动清除

  5. 并发处理:使用@Transactional保证数据一致性


数据库表结构(MySQL示例)

sql 复制代码
CREATE TABLE video_progress (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  user_id VARCHAR(64) NOT NULL,
  video_id VARCHAR(64) NOT NULL,
  last_position DOUBLE NOT NULL DEFAULT 0,
  update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY (user_id, video_id)
);

扩展场景

  1. 多端同步:用户在不同设备续播

  2. 断点续传:结合视频分片技术(HLS/DASH)

  3. 历史记录:展示所有观看过的视频进度

  4. 智能续播:超过95%进度视为已完成

提示:实际生产环境中建议使用Redis缓存播放进度,降低数据库压力并提高响应速度。

通过此实现,用户再次观看视频时将自动从上次停止位置播放,大幅提升用户体验。

相关推荐
焦虑的二狗8 分钟前
Mac下载mysql
数据库·mysql·macos
即将进化成人机13 分钟前
Spring-----MVC配置和基本原理
java·spring·mvc
老神在在00117 分钟前
SpringMVC2
java·前端·学习·spring·java-ee
老神在在00117 分钟前
SpringMVC3
java·前端·学习·spring·java-ee
iam_leeqing22 分钟前
Java线程
java·开发语言
Maybyy35 分钟前
力扣454.四数相加Ⅱ
java·算法·leetcode
Java中文社群38 分钟前
面试官:谈谈你AI项目的具体实现?
java·后端·面试
weixin_456904271 小时前
控制台打开mysql服务报错解决办法
数据库·mysql
小云数据库服务专线1 小时前
GaussDB与Druid连接池常见问题
数据库·gaussdb
哪里不会点哪里.1 小时前
适配器模式:兼容不兼容接口
java·开发语言