实现视频每秒更新观看时长并在完全看完后通过AJAX+PHP+MySQL自动更新数据库
实现视频每秒更新观看时长并在完全看完后通过AJAX+PHP+MySQL自动更新数据库
嘿,我懂你的需求了——现在的代码只有暂停时才更新观看时长,你想要它每秒实时更新,还要在用户完整看完视频后自动把状态同步到数据库对吧?我来帮你修改原代码,一步一步实现这些功能:
一、调整后的HTML代码
原HTML结构基本不用大改,只需要把时长更新的提示文字改一下,让用户知道现在是实时更新的:
<video id="video" class="video-js" controls preload="none" width="640" height="264" poster="../assets/img/poster-for-video.jpg" data-setup="{}"> <source src="<?php echo $video_url;?>" type="video/mp4"></source> <p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video</p> </video> <div id="status" class="incomplete"> <span>Play status: </span> <span class="status complete">COMPLETE</span> <span class="status incomplete">INCOMPLETE</span> <br /> </div> <div> <span id="played">0</span> seconds out of <span id="duration"></span> seconds. (每秒实时更新) </div>
二、修改后的JavaScript代码
核心改动点:
- 监听视频的
timeupdate事件(播放位置变化时自动触发,约每秒1-4次,完美实现实时更新) - 优化累计观看时长的计算逻辑,避免重复统计
- 新增视频完成时的AJAX请求,自动同步状态到后端数据库
<script src="js/jquery2.0.3.min.js"></script> <link href="src/plugins/video-js/video-js.css" rel="stylesheet"> <script src="src/plugins/video-js/video.js"></script> <script type="text/javascript" defer="defer"> $(document).ready(function() { var video = document.getElementById("video"); var timeStarted = -1; var timePlayed = 0; var duration = 0; // 获取视频总时长 if (video.readyState > 0) { getDuration.call(video); } else { video.addEventListener("loadedmetadata", getDuration); } // 记录视频开始播放的时间(避免重复触发) function videoStartedPlaying() { if (timeStarted < 0) { timeStarted = new Date().getTime() / 1000; } } // 处理视频暂停/结束的逻辑 function videoStoppedPlaying(event) { if (timeStarted > 0) { var playedFor = new Date().getTime() / 1000 - timeStarted; timePlayed += playedFor; timeStarted = -1; } // 检查是否播放完成 if (timePlayed >= duration && event.type == "ended") { document.getElementById("status").className = "complete"; // 视频完成时,自动同步到数据库 syncVideoStatusToDB(true, Math.round(timePlayed)); } } // 实时更新已播放时长(核心逻辑) function updatePlayedTime() { if (timeStarted > 0) { // 计算当前总播放时长:累计时长 + 本次播放的实时时长 var currentPlayed = timePlayed + (new Date().getTime() / 1000 - timeStarted); document.getElementById("played").innerHTML = Math.round(currentPlayed) + ""; } } function getDuration() { duration = video.duration; document.getElementById("duration").appendChild(new Text(Math.round(duration) + "")); console.log("Duration: ", duration); } // 绑定视频事件 video.addEventListener("play", videoStartedPlaying); video.addEventListener("playing", videoStartedPlaying); video.addEventListener("ended", videoStoppedPlaying); video.addEventListener("pause", videoStoppedPlaying); // 关键:添加timeupdate事件实现实时更新 video.addEventListener("timeupdate", updatePlayedTime); // 同步到数据库的AJAX函数 function syncVideoStatusToDB(isComplete, playedSeconds) { // 替换成你的用户ID和视频ID(从后端或session获取) var userId = <?php echo $_SESSION['user_id'] ?? 0; ?>; var videoId = <?php echo $video_id ?? 0; ?>; $.ajax({ url: "update_video_status.php", type: "POST", data: { user_id: userId, video_id: videoId, is_complete: isComplete ? 1 : 0, played_seconds: playedSeconds }, success: function(response) { console.log("观看状态已同步到数据库:", response); }, error: function(xhr, status, error) { console.error("同步失败:", error); } }); } }); </script>
三、后端PHP代码(update_video_status.php)
这个文件用来接收AJAX请求,把视频观看状态写入MySQL数据库:
<?php // 1. 连接数据库(替换成你的数据库信息) $servername = "localhost"; $username = "your_db_username"; $password = "your_db_password"; $dbname = "your_db_name"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("数据库连接失败: " . $conn->connect_error); } // 2. 过滤并获取参数,防止SQL注入 $userId = intval($_POST['user_id'] ?? 0); $videoId = intval($_POST['video_id'] ?? 0); $isComplete = intval($_POST['is_complete'] ?? 0); $playedSeconds = intval($_POST['played_seconds'] ?? 0); // 3. 插入或更新记录(用ON DUPLICATE KEY UPDATE避免重复数据) $sql = "INSERT INTO video_watch_records (user_id, video_id, is_complete, played_seconds, updated_at) VALUES (?, ?, ?, ?, NOW()) ON DUPLICATE KEY UPDATE is_complete = VALUES(is_complete), played_seconds = VALUES(played_seconds), updated_at = NOW()"; $stmt = $conn->prepare($sql); $stmt->bind_param("iiii", $userId, $videoId, $isComplete, $playedSeconds); if ($stmt->execute()) { echo "状态更新成功"; } else { echo "更新失败: " . $stmt->error; } $stmt->close(); $conn->close(); ?>
四、MySQL数据库表结构建议
先创建存储观看记录的表,确保每个用户每个视频只有一条记录:
CREATE TABLE IF NOT EXISTS video_watch_records ( id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL, video_id INT NOT NULL, is_complete TINYINT(1) DEFAULT 0 COMMENT '是否观看完成', played_seconds INT DEFAULT 0 COMMENT '累计观看时长', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY user_video_unique (user_id, video_id) -- 唯一约束避免重复 );
关键说明
- 实时更新原理:用HTML5原生的
timeupdate事件比定时器更稳妥,它会和视频播放进度同步触发,不会出现不同步的问题 - 数据安全:后端PHP用了预处理语句,能有效防止SQL注入,记得替换成你自己的数据库账号信息
- 状态判断:只有当视频真正播放完成(累计时长≥总时长且触发
ended事件)时才同步到数据库,避免频繁请求 - 用户/视频ID:要确保
userId和videoId的正确性,比如用户ID从session获取,视频ID从后端模板变量传入
内容来源于stack exchange
相关产品推荐
相关产品推荐

