html video timeupdate监听用户观看视频时长
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>视频观看时长监控系统</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
color: #333;
min-height: 100vh;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
}
.container {
width: 100%;
max-width: 1000px;
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
overflow: hidden;
margin-top: 30px;
}
header {
background: linear-gradient(to right, #4a69bd, #6a89cc);
color: white;
padding: 25px;
text-align: center;
}
h1 {
font-size: 2.5rem;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}
.subtitle {
font-size: 1.1rem;
opacity: 0.9;
}
.video-container {
padding: 30px;
display: flex;
flex-direction: column;
align-items: center;
}
.video-wrapper {
width: 100%;
max-width: 800px;
position: relative;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
video {
width: 100%;
display: block;
background: #000;
}
.controls {
display: flex;
justify-content: space-between;
width: 100%;
max-width: 800px;
margin-top: 20px;
gap: 15px;
}
.control-btn {
flex: 1;
background: #4a69bd;
color: white;
border: none;
padding: 12px;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
font-weight: 500;
transition: all 0.3s;
}
.control-btn:hover {
background: #3d56a0;
transform: translateY(-2px);
}
.control-btn:active {
transform: translateY(0);
}
.stats-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-top: 30px;
width: 100%;
max-width: 800px;
}
.stat-card {
flex: 1;
min-width: 200px;
background: #f8f9fa;
border-radius: 12px;
padding: 20px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.stat-title {
color: #4a69bd;
font-size: 1.1rem;
margin-bottom: 15px;
font-weight: 600;
}
.stat-value {
font-size: 2rem;
font-weight: 700;
color: #333;
}
.progress-container {
width: 100%;
max-width: 800px;
margin-top: 20px;
}
.progress-title {
margin-bottom: 10px;
font-weight: 600;
color: #4a69bd;
}
.progress-bar {
height: 12px;
background: #e9ecef;
border-radius: 6px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(to right, #4a69bd, #6a89cc);
border-radius: 6px;
transition: width 0.5s ease;
}
.time-display {
display: flex;
justify-content: space-between;
margin-top: 8px;
font-size: 0.9rem;
color: #6c757d;
}
.events-container {
width: 100%;
max-width: 800px;
margin-top: 30px;
background: #f8f9fa;
border-radius: 12px;
padding: 20px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.events-title {
color: #4a69bd;
font-size: 1.2rem;
margin-bottom: 15px;
font-weight: 600;
}
.events-list {
max-height: 200px;
overflow-y: auto;
}
.event-item {
padding: 10px;
border-bottom: 1px solid #e9ecef;
display: flex;
justify-content: space-between;
}
.event-time {
font-weight: 600;
color: #4a69bd;
}
.event-desc {
color: #495057;
}
.explanation {
width: 100%;
max-width: 800px;
margin-top: 30px;
background: #f8f9fa;
border-radius: 12px;
padding: 20px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.explanation-title {
color: #4a69bd;
font-size: 1.2rem;
margin-bottom: 15px;
font-weight: 600;
}
.code-block {
background: #2d2d2d;
color: #f8f8f2;
border-radius: 8px;
padding: 20px;
margin-top: 15px;
font-family: 'Courier New', monospace;
font-size: 0.95rem;
overflow-x: auto;
}
.comment {
color: #75715e;
}
.footer {
text-align: center;
padding: 30px;
color: rgba(255, 255, 255, 0.8);
font-size: 1rem;
margin-top: 20px;
}
@media (max-width: 768px) {
.controls {
flex-direction: column;
}
h1 {
font-size: 2rem;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>视频观看时长监控系统</h1>
<p class="subtitle">使用timeupdate事件精确跟踪用户观看行为</p>
</header>
<div class="video-container">
<div class="video-wrapper">
<video id="videoPlayer" controls>
<source src="https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4">
您的浏览器不支持HTML5视频播放
</video>
</div>
<div class="controls">
<button class="control-btn" id="playBtn">播放</button>
<button class="control-btn" id="pauseBtn">暂停</button>
<button class="control-btn" id="resetBtn">重置</button>
</div>
<div class="stats-container">
<div class="stat-card">
<div class="stat-title">当前播放时间</div>
<div class="stat-value" id="currentTime">0:00</div>
</div>
<div class="stat-card">
<div class="stat-title">视频总时长</div>
<div class="stat-value" id="duration">0:00</div>
</div>
<div class="stat-card">
<div class="stat-title">观看百分比</div>
<div class="stat-value" id="percentWatched">0%</div>
</div>
<div class="stat-card">
<div class="stat-title">实际观看时长</div>
<div class="stat-value" id="timeWatched">0秒</div>
</div>
</div>
<div class="progress-container">
<div class="progress-title">播放进度</div>
<div class="progress-bar">
<div class="progress-fill" id="playProgress" style="width: 0%"></div>
</div>
<div class="time-display">
<span id="currentTimeLabel">0:00</span>
<span id="durationLabel">0:00</span>
</div>
</div>
<div class="progress-container">
<div class="progress-title">观看进度(实际观看时长)</div>
<div class="progress-bar">
<div class="progress-fill" id="watchProgress" style="width: 0%"></div>
</div>
<div class="time-display">
<span>0秒</span>
<span id="totalDurationLabel">0秒</span>
</div>
</div>
<div class="events-container">
<div class="events-title">观看事件记录</div>
<div class="events-list" id="eventsList">
<div class="event-item">
<span class="event-time">0:00</span>
<span class="event-desc">视频已加载</span>
</div>
</div>
</div>
<div class="explanation">
<div class="explanation-title">技术实现说明</div>
<p>本系统使用HTML5 video元素的timeupdate事件来监控用户观看行为:</p>
<div class="code-block">
<span class="comment">// 获取video元素</span><br>
<span style="color: #f92672;">const</span> video = <span style="color: #a6e22e;">document</span>.<span style="color: #a6e22e;">getElementById</span>(<span style="color: #e6db74;">'videoPlayer'</span>);<br><br>
<span class="comment">// 添加timeupdate事件监听</span><br>
video.<span style="color: #a6e22e;">addEventListener</span>(<span style="color: #e6db74;">'timeupdate'</span>, <span style="color: #f92672;">function</span>() {<br>
<span class="comment">// 获取当前播放时间</span><br>
<span style="color: #f92672;">const</span> currentTime = video.<span style="color: #a6e22e;">currentTime</span>;<br>
<span style="color: #f92672;">const</span> duration = video.<span style="color: #a6e22e;">duration</span>;<br><br>
<span class="comment">// 计算观看百分比</span><br>
<span style="color: #f92672;">const</span> percent = (currentTime / duration * 100).<span style="color: #a6e22e;">toFixed</span>(1);<br><br>
<span class="comment">// 更新UI显示</span><br>
<span style="color: #a6e22e;">updateProgress</span>(currentTime, duration, percent);<br>
<span style="color: #a6e22e;">trackActualWatching</span>(currentTime);<br>
});
</div>
<p>timeupdate事件在视频播放位置发生变化时触发,通常每秒触发4-66次(取决于系统负载和浏览器实现)。</p>
</div>
</div>
</div>
<div class="footer">
<p>视频观看时长监控系统 © 2023 | HTML5视频技术演示</p>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const video = document.getElementById('videoPlayer');
const playBtn = document.getElementById('playBtn');
const pauseBtn = document.getElementById('pauseBtn');
const resetBtn = document.getElementById('resetBtn');
const currentTimeEl = document.getElementById('currentTime');
const durationEl = document.getElementById('duration');
const percentWatchedEl = document.getElementById('percentWatched');
const timeWatchedEl = document.getElementById('timeWatched');
const playProgress = document.getElementById('playProgress');
const watchProgress = document.getElementById('watchProgress');
const currentTimeLabel = document.getElementById('currentTimeLabel');
const durationLabel = document.getElementById('durationLabel');
const totalDurationLabel = document.getElementById('totalDurationLabel');
const eventsList = document.getElementById('eventsList');
// 状态变量
let actualWatchTime = 0;
let lastUpdateTime = 0;
let isPlaying = false;
let totalDuration = 0;
// 格式化时间为 MM:SS
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs < 10 ? '0' : ''}${secs}`;
}
// 添加事件记录
function addEvent(time, description) {
const eventItem = document.createElement('div');
eventItem.className = 'event-item';
eventItem.innerHTML = `
<span class="event-time">${formatTime(time)}</span>
<span class="event-desc">${description}</span>
`;
eventsList.appendChild(eventItem);
eventsList.scrollTop = eventsList.scrollHeight;
}
// 更新播放进度
function updatePlayProgress(currentTime, duration) {
const percent = (currentTime / duration * 100).toFixed(1);
playProgress.style.width = `${percent}%`;
currentTimeLabel.textContent = formatTime(currentTime);
if (duration) {
durationLabel.textContent = formatTime(duration);
}
}
// 更新观看进度
function updateWatchProgress() {
const percent = (actualWatchTime / totalDuration * 100).toFixed(1);
watchProgress.style.width = `${percent}%`;
timeWatchedEl.textContent = `${actualWatchTime.toFixed(1)}秒`;
}
// 初始化视频
video.addEventListener('loadedmetadata', function() {
durationEl.textContent = formatTime(video.duration);
totalDuration = video.duration;
totalDurationLabel.textContent = `${totalDuration.toFixed(1)}秒`;
addEvent(0, '视频已加载');
});
// timeupdate事件处理
video.addEventListener('timeupdate', function() {
const currentTime = video.currentTime;
const duration = video.duration;
// 更新播放时间显示
currentTimeEl.textContent = formatTime(currentTime);
// 更新播放进度
updatePlayProgress(currentTime, duration);
// 计算观看百分比
const percent = duration ? (currentTime / duration * 100).toFixed(1) : 0;
percentWatchedEl.textContent = `${percent}%`;
// 跟踪实际观看时间
if (isPlaying) {
const now = Date.now() / 1000;
if (lastUpdateTime > 0) {
const delta = now - lastUpdateTime;
actualWatchTime += delta;
updateWatchProgress();
}
lastUpdateTime = now;
}
});
// 播放事件
video.addEventListener('play', function() {
isPlaying = true;
lastUpdateTime = Date.now() / 1000;
addEvent(video.currentTime, '开始播放');
});
// 暂停事件
video.addEventListener('pause', function() {
isPlaying = false;
addEvent(video.currentTime, '暂停播放');
});
// 结束事件
video.addEventListener('ended', function() {
isPlaying = false;
addEvent(video.currentTime, '播放结束');
});
// 按钮事件
playBtn.addEventListener('click', function() {
video.play();
});
pauseBtn.addEventListener('click', function() {
video.pause();
});
resetBtn.addEventListener('click', function() {
video.currentTime = 0;
actualWatchTime = 0;
updateWatchProgress();
timeWatchedEl.textContent = '0秒';
eventsList.innerHTML = '<div class="event-item"><span class="event-time">0:00</span><span class="event-desc">视频已重置</span></div>';
});
});
</script>
</body>
</html>