You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现视频每秒更新观看时长并在完全看完后通过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代码

核心改动点:

  1. 监听视频的timeupdate事件(播放位置变化时自动触发,约每秒1-4次,完美实现实时更新)
  2. 优化累计观看时长的计算逻辑,避免重复统计
  3. 新增视频完成时的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) -- 唯一约束避免重复
);

关键说明

  1. 实时更新原理:用HTML5原生的timeupdate事件比定时器更稳妥,它会和视频播放进度同步触发,不会出现不同步的问题
  2. 数据安全:后端PHP用了预处理语句,能有效防止SQL注入,记得替换成你自己的数据库账号信息
  3. 状态判断:只有当视频真正播放完成(累计时长≥总时长且触发ended事件)时才同步到数据库,避免频繁请求
  4. 用户/视频ID:要确保userId和videoId的正确性,比如用户ID从session获取,视频ID从后端模板变量传入

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 08:45:28