从数据库到播放器: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缓存播放进度,降低数据库压力并提高响应速度。

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

相关推荐
你是狒狒吗9 小时前
为什么mysql要有主从复制,主库,从库这种东西
数据库·mysql
MongoVIP10 小时前
音频类AI工具扩展
人工智能·音视频·ai工具使用
倔强的石头10612 小时前
【金仓数据库】ksql 指南(一) 连接本地 KingbaseES 数据库与基础交互
数据库·oracle·kingbasees·金仓数据库·ksql
代码萌新知14 小时前
设计模式学习(五)装饰者模式、桥接模式、外观模式
java·学习·设计模式·桥接模式·装饰器模式·外观模式
iナナ17 小时前
Spring Web MVC入门
java·前端·网络·后端·spring·mvc
驱动探索者17 小时前
find 命令使用介绍
java·linux·运维·服务器·前端·学习·microsoft
卷Java17 小时前
违规通知功能修改说明
java·数据库·微信小程序·uni-app
CoderYanger17 小时前
优选算法-双指针:2.复写零
java·后端·算法·leetcode·职场和发展
小雨凉如水17 小时前
k8s学习-pod的生命周期
java·学习·kubernetes
李宥小哥17 小时前
C#基础10-结构体和枚举
java·开发语言·c#