
本文介绍如何通过监听 HTML5 视频元素的 timeupdate 事件,实时计算并显示用户已观看视频时长占总时长的百分比,适用于强制完播、学习进度追踪等场景。
本文介绍如何通过监听 html5 视频元素的 `timeupdate` 事件,实时计算并显示用户已观看视频时长占总时长的百分比,适用于强制完播、学习进度追踪等场景。
在构建教育平台、在线课程系统或内容付费网站时,准确衡量用户视频观看完成度至关重要。一个常见且有效的做法是动态展示“已观看 X%”的提示,既提升用户体验透明度,也便于后续逻辑判断(例如:仅当观看率达100%才解锁下一章节)。
实现该功能的核心在于利用原生 <video></video> 元素提供的 DOM API:
-
video.currentTime:返回当前播放位置(秒数,浮点型); -
video.duration:返回视频总时长(秒数,浮点型;注意:需确保元数据已加载完成,否则可能为NaN); -
timeupdate事件:在播放过程中频繁触发(通常每200–250ms一次),适合用于实时更新进度百分比。
以下为完整、健壮的实现代码:
<video id="myVideo" controls width="640" height="360">
<source src="episode.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
<div id="percentageWatched">You've viewed 0.00% of this episode.</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const video = document.getElementById('myVideo');
const percentageWatched = document.getElementById('percentageWatched');
// 防止 duration 未就绪时计算出 NaN
video.addEventListener('loadedmetadata', () => {
// 初始化显示(可选)
const initPercent = (video.currentTime / video.duration) * 100;
percentageWatched.textContent = `You've viewed ${initPercent.toFixed(2)}% of this episode.`;
});
video.addEventListener('timeupdate', () => {
// 安全计算:避免 duration 为 Infinity 或 NaN
if (!isFinite(video.duration) || video.duration <= 0) return;
const watchedPercentage = (video.currentTime / video.duration) * 100;
// 限制在 0–100 范围内(防止因 seeking 导致短暂超限)
const clampedPercent = Math.min(100, Math.max(0, watchedPercentage));
percentageWatched.textContent = `You've viewed ${clampedPercent.toFixed(2)}% of this episode.`;
});
});
</script>⚠️ 关键注意事项:
- 必须等待
loadedmetadata事件后再访问video.duration,否则可能读取到NaN; -
timeupdate事件频率高,避免在其中执行耗时操作(如 DOM 批量重排、网络请求); - 若需支持后台播放(如页面失焦后继续计时),需结合
visibilitychange和play/pause事件做状态同步; - 对于流媒体(HLS/DASH),
duration可能动态变化,建议使用播放器 SDK(如 Video.js、hls.js)提供的更稳定进度接口; - 如需持久化观看进度(如刷新后恢复),应配合
localStorage或服务端记录currentTime。
此方案轻量、兼容性好(支持所有现代浏览器),无需第三方库即可投入生产使用。结合业务逻辑,你还可以进一步扩展为:自动暂停未达阈值的用户、统计平均观看率、生成观看热力图等。


















