PHP无法直接监控浏览器视频播放异常,需前端捕获video元素的error等事件并通过AJAX上报,PHP后端校验、过滤并写入日志文件。

PHP 本身无法直接监控浏览器端的视频播放异常(比如卡顿、解码失败、网络中断),因为视频播放发生在前端,PHP 是服务端语言,不接触 DOM 或媒体事件。真正可行的做法是:前端捕获 video 元素的错误和状态事件,通过 AJAX 主动上报异常,PHP 接收并记录日志或触发告警。
前端如何捕获 video 播放异常并上报
浏览器 video 元素会抛出 error、stalled、abort、emptied 等事件,其中 error 是最核心的异常信号。注意:video.error 是只读对象,需检查其 code 和 message 属性。
常见错误码含义:
-
1:MEDIA_ERR_ABORTED(用户取消请求) -
2:MEDIA_ERR_NETWORK(网络错误,如 404、超时) -
3:MEDIA_ERR_DECODE(解码失败,常见于格式/编码不兼容) -
4:MEDIA_ERR_SRC_NOT_SUPPORTED(src不被支持,如缺少 codec)
上报示例(使用 fetch):
立即学习“PHP免费学习笔记(深入)”;
const video = document.getElementById('myVideo');
video.addEventListener('error', function() {
const errCode = video.error?.code || 0;
const src = video.src;
const currentTime = video.currentTime.toFixed(2);
fetch('/log-video-error.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
code: errCode,
src,
time: currentTime,
userAgent: navigator.userAgent,
referrer: document.referrer
})
});
});
PHP 后端接收并记录异常日志
/log-video-error.php 需做基础校验和结构化落库/写文件,避免被刷或注入。不要直接 file_put_contents 原始 POST 数据,要解析、过滤、限流。
- 用
json_decode(file_get_contents('php://input'), true)获取 JSON 数据 - 校验
code是否为整数且在 1–4 范围内 - 对
src做filter_var($src, FILTER_SANITIZE_URL)过滤 - 建议写入专用日志文件(如
/var/log/video-errors.log),而非数据库——高并发播放页可能瞬间涌来大量错误上报
简略示例:
4) {
http_response_code(400);
exit;
}
$line = sprintf(
"[%s] CODE:%d SRC:%s TIME:%s UA:%s\n",
date('Y-m-d H:i:s'),
$data['code'],
filter_var($data['src'], FILTER_SANITIZE_URL),
$data['time'] ?? '0.00',
substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 128)
);
file_put_contents('/var/log/video-errors.log', $line, FILE_APPEND | LOCK_EX);
为什么不能用 PHP 的 get_headers 或 curl 检查视频 URL 是否有效
能返回 200 并不代表视频能正常播放。常见陷阱:
- CDN 缓存了 200 响应,但源站视频文件已损坏
- HTTP Range 请求未支持(
Accept-Ranges: bytes缺失),导致拖拽失败,但curl -I仍显示 200 - 视频容器格式(如 MP4)头部损坏,
get_headers无感知,但浏览器解码时抛MEDIA_ERR_DECODE - 跨域策略(CORS)允许加载,但不允许多媒体解码(某些安卓 WebView 表现异常)
所以服务端预检只能作为辅助手段,不能替代前端真实播放上下文中的异常捕获。
真正有用的监控,必须依赖前端真实的播放行为数据;PHP 的角色只是可靠接收、轻量清洗、持久化存储。漏掉 stalled 或 waiting 状态的上报,就可能错过缓冲瓶颈问题;而把所有上报不经限流直写数据库,容易拖垮服务。这两点最容易被忽略。











