PHP不能直接播放视频,其作用是安全提供视频路径或代理流式传输,需正确设置Content-Type、处理Range请求并分块输出,或生成带签名的限时URL以实现权限控制与防盗链。

PHP 本身不能直接“播放”视频,它只是服务器端脚本语言,负责生成 HTML、处理请求、控制权限或拼接路径。真正播放视频的是浏览器的 标签,PHP 的作用是安全地提供视频文件路径或代理流式传输。
用 PHP 输出视频文件流(避免直接暴露真实路径)
直接把视频放在 web 目录下并用 引用,会导致文件路径泄露、无法做权限校验、容易被批量下载。用 PHP 脚本中转,可以控制谁能看到、限制 Referer、记录访问日志。
- 必须设置正确的
Content-Type(如video/mp4),否则浏览器可能拒绝播放或触发下载 - 需手动处理 HTTP 范围请求(
Range头),否则拖动进度条会失效 —— 浏览器发GET带Range: bytes=1024-,PHP 必须响应206 Partial Content并只输出对应字节段 - 大文件务必用
readfile()+ob_flush()/flush()分块输出,避免内存溢出
header('Content-Type: video/mp4');
header('Accept-Ranges: bytes');
if (isset($_SERVER['HTTP_RANGE'])) {
$range = $_SERVER['HTTP_RANGE'];
list($type, $range) = explode('=', $range, 2);
list($start, $end) = explode('-', $range, 2);
$size = filesize($video_path);
$length = $size - $start;
if (!empty($end)) {
$length = $end - $start + 1;
}
header('HTTP/1.1 206 Partial Content');
header("Content-Range: bytes $start-$end/$size");
header("Content-Length: $length");
$fp = fopen($video_path, 'rb');
fseek($fp, $start);
while ($length > 0 && !feof($fp)) {
$chunk = min(8192, $length);
echo fread($fp, $chunk);
$length -= $chunk;
ob_flush();
flush();
}
fclose($fp);
} else {
header('Content-Length: ' . filesize($video_path));
readfile($video_path);
}
用 PHP 动态生成带签名的视频 URL(防盗链+限时访问)
适合需要控制访问时效、用户身份或防止链接被转发的场景。核心是生成一个带哈希签名和过期时间的 URL,PHP 在接收时验证签名与时间戳是否合法。
- 签名密钥(
$secret)必须保密,不可硬编码在前端或公开配置中 - 时间戳建议用
time(),过期时间(如 300 秒)参与签名计算,服务端验证时若time() - $ts > 300则拒绝 - URL 示例:
/play.php?v=test.mp4&t=1715823400&s=abc123def456,其中s是md5($v.$t.$secret) - 注意:该方案不阻止已获取有效链接的用户反复使用,仅提升盗链门槛
PHP 配合前端
不要试图用 PHP 渲染视频帧或解码 —— 这既低效又不可能。PHP 只需确保最终 HTML 中的 src 指向一个能正确返回视频流的地址(比如上面两个方案中的 play.php)。
立即学习“PHP免费学习笔记(深入)”;
-
的controls、preload、poster等属性全由前端控制,PHP 不参与 - 若需多格式兼容(如 Safari 要
.mov,Chrome 偏好.mp4),PHP 可根据$_SERVER['HTTP_USER_AGENT']或用户偏好动态选源,但更推荐前端用标签声明多个src -
跨域问题(CORS)由 PHP 响应头解决:
header('Access-Control-Allow-Origin: *')(生产环境请限制具体域名)
最常被忽略的一点:Nginx/Apache 默认对 .php 后缀走 PHP-FPM,但对视频文件(.mp4)直接静态返回 —— 如果你把视频 URL 写成 video.php?file=xxx.mp4 却没在 PHP 里处理 Range 请求,拖动就会卡死。这个逻辑不是“可选优化”,而是现代浏览器视频播放的硬性要求。











