导读:在线教育平台最影响留存的功能之一,就是"上次看到哪了"。进度丢失一次,用户可能就再也不回来。断点续播看着简单,做起来全是细节:进度怎么上报才不重复、续播点怎么存才不冲突、学习时长怎么统计才不被刷。本文给出完整的进度追踪设计方案,含幂等上报、续播恢复与时长统计口径。
学习进度要拆成两个维度:续播点(用户下次从哪继续看)与学习状态(看完/未看完/看完一半)。常见模型是每用户每课程一条记录:
{
"userId": 10086,
"courseId": 202,
"lessonId": 38,
"positionSec": 1260,
"percent": 0.62,
"status": "learning",
"updatedAt": 1690000000
}要点:进度按视频维度存(lessonId + positionSec),而不是只存课程百分比——课程百分比可以由各视频进度汇总而来,单存一个数字无法恢复续播。
播放器每 5~10 秒上报一次播放位置。网络抖动会导致重复请求、乱序请求,若直接覆盖写入,旧数据可能把新数据盖掉。解决思路:上报带上时间戳与播放端偏移,服务端做最新优先合并:
// 播放端节流上报:5秒一次,带单调递增的播放序号
setInterval(() => {
report({ lessonId, positionSec, seq: ++seq, ts: Date.now() });
}, 5000);服务端处理规则:同一 lessonId 下,只接受 seq 或 ts 更新的上报,否则丢弃。这样乱序与重复请求都不会污染进度。
用户重新进入课程时,播放器拉取进度并 seek 到对应位置。两个细节容易翻车:
学习时长是运营考核的重要指标,口径不统一会导致数据打架。建议统一为"有效播放时长":仅统计播放器处于播放态(非暂停、非缓冲)且页面可见(非切后台)的时间,由客户端累计、服务端对账。
-- 每日学习时长汇总表(按用户+日期+课程)
CREATE TABLE study_daily (
user_id BIGINT NOT NULL,
course_id BIGINT NOT NULL,
study_date DATE NOT NULL,
valid_sec INT NOT NULL DEFAULT 0,
PRIMARY KEY (user_id, course_id, study_date)
);要点:防刷靠"播放心跳 + 页面可见性"双条件,靠服务端纯计算无法识别挂机,必须客户端配合采集信号。
用户可能手机看一半、电脑接着看。若两端的进度都往同一行写,后写的会覆盖先写的。方案:进度表按"用户+课程+端"拆行,或者服务端合并取最新;推荐前者——端维度独立存储,互不干扰,汇总时取各端最大值。
进度追踪要按「上报幂等 → 存储模型 → 续播恢复 → 时长统计」四层设计,每层独立校验。同类分层在乔拓云教育系统的学习进度模块中有对应实现,视频续播与时长统计各走各的链路,多端冲突在存储层直接隔离。
断点续播的难点不在"存一个数字",而在上报的幂等、恢复的防抖、统计的口径、多端的隔离。把这四件事做扎实,学习进度功能才算真正可用——用户从哪断开,就能从哪接上。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。