PHP无法直接检测浏览器支持的视频格式,因其运行在服务端,无权访问客户端的navigator或video元素;必须由JavaScript调用canPlayType()探测后通过AJAX将结果传给PHP处理。

PHP 无法直接检测浏览器支持的视频格式——因为这是客户端能力,PHP 运行在服务端,没有访问 navigator 或 HTMLMediaElement 的权限。
为什么不能用 PHP 直接检测 canPlayType()
常见的误解是想在 PHP 中调用 JavaScript 的 canPlayType() 方法。这不可能:该方法必须在浏览器环境中执行,依赖 video 元素实例和用户代理的实际解码器能力。PHP 没有 DOM、没有渲染引擎、不运行在用户设备上。
- PHP 收到的只是 HTTP 请求头(如
User-Agent),它只反映浏览器型号/版本,不反映编解码器启用状态(比如 Chrome 可能因版权策略禁用 H.264) - 同一浏览器在不同系统(Windows/macOS/Linux)、不同构建(Chromium vs. official Chrome)、不同插件环境下,支持的格式可能完全不同
- 现代浏览器还支持通过
MediaCapabilities.decodingInfo()动态探测,这更无法被 PHP 预知
可行方案:用 JavaScript 探测后回传给 PHP
真正可用的做法是让前端 JS 执行探测,再把结果以参数形式发给 PHP(例如 via AJAX 或表单提交)。PHP 负责接收、记录或做后续逻辑(如返回适配的视频 URL)。
典型流程:
立即学习“PHP免费学习笔记(深入)”;
- 页面加载时,JS 创建一个临时
video元素 - 对常见 MIME 类型调用
video.canPlayType(type),注意返回值可能是"probably"、"maybe"或空字符串 - 将结果拼成键值对(如
{"mp4": "probably", "webm": "maybe", "av1": "probably"}) - 通过
fetch()发送到 PHP 接口(如/api/video-capabilities.php)
const video = document.createElement('video');
const formats = {
'video/mp4': 'mp4',
'video/webm; codecs="vp9"': 'webm-vp9',
'video/webm; codecs="av1"': 'webm-av1',
'video/quicktime': 'mov'
};
const capabilities = {};
for (const [mime, key] of Object.entries(formats)) {
capabilities[key] = video.canPlayType(mime);
}
fetch('/api/video-capabilities.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(capabilities)
});
PHP 如何安全接收并使用探测结果
PHP 端只需处理 POST 数据,不做任何“猜测”,只信任前端传来的结果(前提是接口做了基础校验)。
- 检查
$_SERVER['CONTENT_TYPE'] === 'application/json',再用json_decode(file_get_contents('php://input'), true)解析 - 过滤键名(只允许预设的格式标识如
mp4、webm-vp9),避免恶意字段注入 - 不要把结果存进全局配置或缓存长期复用——用户下次访问可能换了设备或更新了浏览器
- 典型用途:根据探测结果,在响应 HTML 中选择性输出
标签,或重定向到对应编码的视频流地址
// api/video-capabilities.php
if ($_SERVER['REQUEST_METHOD'] !== 'POST' ||
$_SERVER['CONTENT_TYPE'] !== 'application/json') {
http_response_code(400);
exit;
}
$data = json_decode(file_get_contents('php://input'), true);
if (!is_array($data)) {
http_response_code(400);
exit;
}
$allowedKeys = ['mp4', 'webm-vp9', 'webm-av1', 'mov'];
$safeCaps = array_intersect_key($data, array_flip($allowedKeys));
// 示例:存入 session(仅本次会话有效)
session_start();
$_SESSION['video_capabilities'] = $safeCaps;
替代思路:服务端按 User-Agent 做粗略 fallback
如果完全无法引入前端探测(如纯服务端渲染且不允许加 JS),只能退而求其次,用 $_SERVER['HTTP_USER_AGENT'] 做极简判断——但准确率低,仅适用于兜底。
- iOS Safari(含所有 iPhone/iPad)几乎只可靠支持
video/mp4(H.264 + AAC) - Chrome / Edge / Firefox 在桌面端通常支持
video/webm(VP9)和video/mp4;但 Android WebView 行为不一 - 不要依赖正则匹配 “Chrome” 就认为支持 AV1——AV1 默认在 Chrome 109+ 启用,且需操作系统支持
- 这种判断只能用于设置默认格式,绝不能替代前端探测
最可靠的路径永远是:让浏览器自己说它能播什么,而不是你猜它能播什么。JS 探测 + PHP 接收是目前唯一实用闭环,其他全是妥协方案。











