html video timeupdate监听用户观看视频时长

HTML视频时长监听实现

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>
                    &nbsp;&nbsp;<span class="comment">// 获取当前播放时间</span><br>
                    &nbsp;&nbsp;<span style="color: #f92672;">const</span> currentTime = video.<span style="color: #a6e22e;">currentTime</span>;<br>
                    &nbsp;&nbsp;<span style="color: #f92672;">const</span> duration = video.<span style="color: #a6e22e;">duration</span>;<br><br>
                    
                    &nbsp;&nbsp;<span class="comment">// 计算观看百分比</span><br>
                    &nbsp;&nbsp;<span style="color: #f92672;">const</span> percent = (currentTime / duration * 100).<span style="color: #a6e22e;">toFixed</span>(1);<br><br>
                    
                    &nbsp;&nbsp;<span class="comment">// 更新UI显示</span><br>
                    &nbsp;&nbsp;<span style="color: #a6e22e;">updateProgress</span>(currentTime, duration, percent);<br>
                    &nbsp;&nbsp;<span style="color: #a6e22e;">trackActualWatching</span>(currentTime);<br>
                    });
                </div>
                
                <p>timeupdate事件在视频播放位置发生变化时触发,通常每秒触发4-66次(取决于系统负载和浏览器实现)。</p>
            </div>
        </div>
    </div>
    
    <div class="footer">
        <p>视频观看时长监控系统 &copy; 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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值