使用MongoDB实现视频播放进度的保存与恢复(断点续播)

 更新时间:2026年02月03日 09:11:17   作者:Knight_AL  
在视频类业务中,断点续播 是最基础、也是最核心的能力之一,本文将介绍如何 仅使用 MongoDB 实现视频播放进度的保存与恢复,适用于在线视频、课程学习、长视频播放等场景,需要的朋友可以参考下

一、业务场景说明

视频播放过程中通常存在以下需求:

  • 用户播放视频过程中可能随时退出页面
  • 再次进入视频页面时,需要从上次播放位置继续播放
  • 播放器会 每隔一段时间(如 10 秒)自动保存播放进度
  • 后端需要支持 高频写入 + 快速查询

二、为什么选择 MongoDB 存储播放进度

原因说明
写入频繁每 5~10 秒保存一次进度
数据结构简单用户 + 视频 + 秒数
不需要事务单条数据即可
扩展性好适合大用户量

MongoDB 的 文档模型 + 高并发写入能力,非常适合播放进度这类数据。

三、MongoDB 数据模型设计

1、播放进度实体类

@Data
@Document(collection = "user_video_play_process")
public class UserVideoPlayProcess {

    @Id
    private String id;

    /** 用户ID */
    private Long userId;

    /** 视频ID */
    private Long videoId;

    /** 当前播放到的秒数 */
    private BigDecimal playSecond;

    /** 视频总时长(秒) */
    private BigDecimal duration;

    /** 是否播放完成:0-未完成,1-已完成 */
    private Integer isFinished;

    /** 创建时间 */
    private Date createTime;

    /** 更新时间 */
    private Date updateTime;
}

2、索引设计

db.user_video_play_process.createIndex(
  { userId: 1, videoId: 1 },
  { unique: true }
)

保证:

  • 一个用户 + 一个视频 只有一条播放进度
  • 查询和更新都非常快

四、获取视频播放进度(断点续播)

接口说明

  • 用途:进入视频页面时,获取上次播放位置
  • 返回值:秒数(用于前端 seek)

Controller

@GetMapping("/getPlaySecond/{videoId}")
public Result<BigDecimal> getPlaySecond(@PathVariable Long videoId) {
    Long userId = AuthContextHolder.getUserId();
    return Result.ok(
        videoPlayProcessService.getPlaySecond(userId, videoId)
    );
}

Service 实现

@Override
public BigDecimal getPlaySecond(Long userId, Long videoId) {

    Query query = Query.query(
        Criteria.where("userId").is(userId)
                .and("videoId").is(videoId)
    );

    UserVideoPlayProcess process =
        mongoTemplate.findOne(query, UserVideoPlayProcess.class);

    return process == null ? BigDecimal.ZERO : process.getPlaySecond();
}

五、更新视频播放进度

前端上报规则

  • 播放过程中每 10 秒 上报一次
  • 视频暂停 / 页面关闭 / 切换视频时强制上报
  • 拖动进度条结束后上报

接收参数 VO

@Data
public class VideoPlayProcessVo {

    private Long videoId;

    private BigDecimal playSecond;

    private BigDecimal duration;
}

Controller

@PostMapping("/updatePlayProcess")
public Result updatePlayProcess(
        @RequestBody VideoPlayProcessVo vo) {

    Long userId = AuthContextHolder.getUserId();
    videoPlayProcessService.updatePlayProcess(userId, vo);
    return Result.ok();
}

Service 核心实现(Upsert 思想)

@Override
public void updatePlayProcess(Long userId, VideoPlayProcessVo vo) {

    Query query = Query.query(
        Criteria.where("userId").is(userId)
                .and("videoId").is(vo.getVideoId())
    );

    boolean finished = vo.getPlaySecond().compareTo(
        vo.getDuration().multiply(new BigDecimal("0.95"))
    ) >= 0;

    Update update = new Update()
            .set("playSecond", vo.getPlaySecond())
            .set("duration", vo.getDuration())
            .set("isFinished", finished ? 1 : 0)
            .set("updateTime", new Date())
            .setOnInsert("userId", userId)
            .setOnInsert("videoId", vo.getVideoId())
            .setOnInsert("createTime", new Date());

    mongoTemplate.upsert(
        query,
        update,
        UserVideoPlayProcess.class
    );
}

为什么用 upsert

  • 存在即更新
  • 不存在即插入
  • 一条语句完成,避免并发问题
  • 性能优于 find + save

六、前端播放流程说明(配合后端)

1. 进入视频页面
2. 调用 getPlaySecond(videoId)
3. 播放器 seek 到返回的秒数
4. 播放过程中每 10 秒调用 updatePlayProcess
5. 页面关闭 / 切视频时最后一次保存

七、常见问题与优化点

是否需要保存毫秒级?

❌ 不需要
✔ 秒级即可,节省存储 & 减少写入

如何降低 MongoDB 写压力?

  • 秒数变化 < 3 秒不更新
  • 播放暂停时不上报
  • 拖动结束才上报

是否需要按用户分集合?

❌ 不推荐
✔ 单集合 + 复合索引更稳妥

八、方案总结

使用 MongoDB 存储视频播放进度,
通过 userId + videoId 唯一索引保证幂等,
利用 upsert 实现高效的断点续播功能。

该方案:

  • 实现简单
  • 性能稳定
  • 易于扩展(学习进度、是否看完)

视频播放进度使用 MongoDB 存储,
通过 upsert 保证高并发下的数据一致性,
实现视频的断点续播功能。

以上就是使用MongoDB实现视频播放进度的保存与恢复(断点续播)的详细内容,更多关于MongoDB视频播放进度保存与恢复的资料请关注脚本之家其它相关文章!

相关文章

  • MongoDB  数据模型的设计模式及优缺点

    MongoDB  数据模型的设计模式及优缺点

    这篇文章主要介绍了MongoDB  数据模型的设计模式,在实际开发中,大多数性能问题都可以追溯到糟糕的模型设计,官方也提供分享过文档模型设计的进阶技巧,这里简单翻译记录一下,需要的朋友可以参考下
    2022-12-12
  • Mac中mongoDB的安装与卸载步骤详解

    Mac中mongoDB的安装与卸载步骤详解

    mongoDB是一个非常不错的数据库,最近也正在学习mongoDB,在使用一个数据库前必不可少的就是安装和卸载,所以下面这篇文章主要给大家介绍了关于Mac系统中mongoDB安装与卸载的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-10-10
  • MongoDB进阶之动态字段设计详解

    MongoDB进阶之动态字段设计详解

    这篇文章主要给大家介绍了MongoDB进阶之动态字段设计的相关资料,文中介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面跟着小编一起来学习学习吧。
    2017-06-06
  • Mongodb副本集和分片示例详解

    Mongodb副本集和分片示例详解

    这篇文章主要给大家介绍了关于Mongodb副本集和分片的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Mongodb具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-08-08
  • Mongoose 在egg中的使用详解

    Mongoose 在egg中的使用详解

    这篇文章主要介绍了Mongoose 在egg中的使用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • 阿里云服务器部署mongodb的详细过程

    阿里云服务器部署mongodb的详细过程

    这篇文章主要介绍了阿里云服务器部署mongodb的过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • mongodb数据库迁移变更的解决方案

    mongodb数据库迁移变更的解决方案

    众所周知mongodb数据库是一个非关系类型的数据,有着非常灵活和高性能的特点得到了开发者的喜爱,这篇文章主要给大家介绍了关于mongodb数据库迁移变更的相关资料,需要的朋友可以参考下
    2021-09-09
  • Mongodb启动命令参数中文说明

    Mongodb启动命令参数中文说明

    这篇文章主要介绍了Mongodb启动命令参数中文说明,本文包括基本配置、主/从参数、Sharding(分片)选项等内容,需要的朋友可以参考下
    2014-10-10
  • MongoDB批量将时间戳转为通用日期格式示例代码

    MongoDB批量将时间戳转为通用日期格式示例代码

    这篇文章主要给大家介绍了关于MongoDB批量将时间戳转为通用日期格式的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用MongoDB具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-07-07
  • Centos 7下Mongodb开机无法自启动的解决方法

    Centos 7下Mongodb开机无法自启动的解决方法

    这篇文章主要介绍了Centos 7下Mongodb开机无法自启动的解决方法,文中介绍的非常详细,对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。
    2017-03-03

最新评论