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

如何将ESP32CAM视频流嵌入PHP网站实现车位状态管理

ESP32CAM停车场监控嵌入+状态更新实现方案

视频流嵌入与浮层实现

ESP32CAM默认输出MJPEG格式视频流,无需引入第三方播放器,直接用<img>标签即可拉流播放。通过CSS定位就能实现操作表格浮在视频上层的效果,参考代码如下:

<!-- 视频与浮层外层容器,用相对定位做定位上下文 -->
<div style="position: relative; width: 100%; max-width: 1280px; margin: 0 auto;">
  <!-- 替换成你自己的ESP32CAM实际IP,默认流路径为/stream -->
  <img src="http://192.168.x.x/stream" alt="停车场实时监控" style="width: 100%; display: block;">
  <!-- 浮层操作区,绝对定位叠在视频上方 -->
  <div style="position: absolute; top: 20px; right: 20px; background: rgba(255,255,255,0.92); padding: 16px; border-radius: 6px; box-shadow: 0 2px 8px rgba(0,0,0,0.15);">
    <table style="border-collapse: collapse;">
      <thead>
        <tr>
          <th style="padding: 6px 12px; text-align: left; border-bottom: 1px solid #eee;">车位编号</th>
          <th style="padding: 6px 12px; text-align: left; border-bottom: 1px solid #eee;">状态操作</th>
        </tr>
      </thead>
      <tbody>
        <?php
        // 从数据库读取全量车位信息,循环生成表格行
        // 以下为示例逻辑,替换成你自己的数据库查询代码即可
        $db = mysqli_connect('你的数据库地址', '数据库账号', '数据库密码', '停车场库名');
        $res = mysqli_query($db, "SELECT id, status FROM parking_spots ORDER BY id ASC");
        while ($spot = mysqli_fetch_assoc($res)) {
          $currentStatus = $spot['status'] ? '占用' : '空闲';
          $btnText = $spot['status'] ? '标记为空闲' : '标记为占用';
          echo "<tr>
                  <td style='padding: 8px 12px; border-bottom: 1px solid #f5f5f5;'>车位{$spot['id']}({$currentStatus})</td>
                  <td style='padding: 8px 12px; border-bottom: 1px solid #f5f5f5;'>
                    <button class='status-btn' data-spot-id='{$spot['id']}' style='padding: 4px 10px; cursor: pointer;'>{$btnText}</button>
                  </td>
                </tr>";
        }
        mysqli_close($db);
        ?>
      </tbody>
    </table>
  </div>
</div>

浮层的位置、透明度、大小可以根据摄像头实际取景范围调整,不要遮挡车位线、车牌等关键监控区域即可。

按钮点击更新车位状态逻辑

用异步请求实现无刷新更新,避免打断视频流播放,分前端交互和后端接口两部分实现:

前端交互逻辑

在页面底部加如下JS代码,绑定按钮点击事件,向后端接口传对应车位ID:

document.querySelectorAll('.status-btn').forEach(btn => {
  btn.addEventListener('click', async function() {
    const spotId = this.dataset.spotId;
    // 临时禁用按钮防止重复提交
    this.disabled = true;
    try {
      const resp = await fetch('update_spot_status.php', {
        method: 'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        body: `spot_id=${spotId}`
      });
      const result = await resp.json();
      if (result.code === 0) {
        // 更新成功后重载页面同步状态,也可以改成局部更新按钮文字减少刷新
        window.location.reload();
      } else {
        alert(`操作失败:${result.msg}`);
        this.disabled = false;
      }
    } catch (err) {
      alert('网络异常,请重试');
      this.disabled = false;
    }
  })
})

后端更新接口

新建update_spot_status.php文件,处理状态更新逻辑,必须加权限校验和SQL注入防护:

<?php
session_start();
// 替换成你自己的管理员登录态校验逻辑,未登录直接拒绝请求
if (empty($_SESSION['admin_login']) || $_SESSION['admin_login'] !== true) {
  echo json_encode(['code' => 403, 'msg' => '无操作权限']);
  exit;
}

$spotId = isset($_POST['spot_id']) ? intval($_POST['spot_id']) : 0;
if ($spotId <= 0) {
  echo json_encode(['code' => 1, 'msg' => '参数非法']);
  exit;
}

// 连接数据库
$conn = mysqli_connect('你的数据库地址', '数据库账号', '数据库密码', '停车场库名');
if (!$conn) {
  echo json_encode(['code' => 2, 'msg' => '数据库连接失败']);
  exit;
}

// 查询当前状态做翻转,不需要前端传状态值,避免篡改
$stmt = mysqli_prepare($conn, "SELECT status FROM parking_spots WHERE id = ?");
mysqli_stmt_bind_param($stmt, "i", $spotId);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $currentStatus);
mysqli_stmt_fetch($stmt);
mysqli_stmt_close($stmt);

$newStatus = $currentStatus ? 0 : 1;
// 预处理语句更新,避免SQL注入
$stmt = mysqli_prepare($conn, "UPDATE parking_spots SET status = ?, update_time = NOW() WHERE id = ?");
mysqli_stmt_bind_param($stmt, "ii", $newStatus, $spotId);
$updateResult = mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
mysqli_close($conn);

if ($updateResult) {
  echo json_encode(['code' => 0, 'msg' => '更新成功']);
} else {
  echo json_encode(['code' => 3, 'msg' => '数据库更新失败']);
}
exit;
?>

常见问题注意点

  • 如果你的PHP站部署在HTTPS协议下,直接嵌入HTTP的ESP32CAM流会被浏览器拦截混合内容,可在服务器端做一层流代理转发,或者内部场景直接用HTTP协议部署站点
  • ESP32CAM性能有限,如果出现流卡顿,可适当降低摄像头分辨率、帧率,停车场监控场景800*600分辨率、10帧即可满足需求
  • 不要把ESP32CAM的流地址直接暴露在公网,如果需要远程访问,务必给摄像头配置访问密码,同时做好端口访问控制
  • 浮层可根据需求扩展,比如加实时车位占用统计、异常事件上报按钮等功能

内容的提问来源于stack exchange,提问作者RaccoonFromHell

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:09:16