上传失败或$_files为空,90%是php配置或表单问题:先查php.ini中upload_max_filesize和post_max_size是否≥512m、表单是否含enctype="multipart/form-data"且method="post"、$_files'video'是否为upload_err_ok;若var_dump($_files)为空,则必为表单或配置错误。

上传失败或 $_FILES 为空?先查这三处
PHP 接收不到视频文件,90% 是基础配置或表单问题。别急着改代码,先确认:
-
php.ini中upload_max_filesize和post_max_size是否设为至少512M(注意单位大小写) - 表单是否漏了
enctype="multipart/form-data",且method="POST" -
$_FILES['video']['error']返回值不是UPLOAD_ERR_OK(即 0),而是UPLOAD_ERR_NO_FILE(4)或UPLOAD_ERR_INI_SIZE(1)——前者说明前端根本没传,后者说明超了 php.ini 限制
临时加一行 var_dump($_FILES) 能立刻暴露是哪一环断了。如果输出为空数组,基本就是表单或 PHP 配置问题。
finfo_open() 校验 MIME 类型为什么比 $_FILES['type'] 更可靠
$_FILES['video']['type'] 完全由浏览器提交,可被轻易伪造;而 finfo_open() 读取文件头二进制内容,真实反映媒体类型。不校验就存文件,等于给恶意脚本开后门。
实操建议:
- 必须用
finfo_open(FILEINFO_MIME_TYPE)获取真实类型,白名单只允许video/mp4、video/webm、video/quicktime等 - 不要只检查扩展名,
.mp4文件可能是 PHP shell,finfo能识别出text/x-php - 调用完记得
finfo_close($finfo),避免资源泄漏
示例片段:$finfo = finfo_open(FILEINFO_MIME_TYPE); $real_mime = finfo_file($finfo, $_FILES['video']['tmp_name']);
为什么不能在 HTTP 请求里直接 exec('ffmpeg')?
FFmpeg 转码动辄几十秒,PHP 默认 max_execution_time 是 30 秒,超时直接中断,且阻塞整个请求线程,用户看到空白页或 504。更糟的是,如果并发上传多条视频,服务器 CPU 和磁盘 I/O 会瞬间打满。
正确做法是「解耦」:
- 上传成功后,只把原始路径、用户 ID、任务参数写入数据库,状态设为
'pending' - 用
think-queue或原生 Redis 队列推一条消息,Worker 进程后台拉取并执行shell_exec("ffmpeg -i {$input} -c:v libx264 ... {$output} 2>&1") - Worker 执行时加
set_time_limit(0),并捕获2>&1错误输出写入日志,方便排查Permission denied或No such file类错误
切记:exec() 的路径必须用绝对路径,比如 /usr/bin/ffmpeg,不能依赖 $PATH。
生成多版本时,-vf scale=1280:-2 是什么含义
这个参数控制缩放逻辑:-vf "scale=1280:-2" 表示宽度固定为 1280 像素,高度自动按原始宽高比计算(-2 表示保持比例且对齐偶数像素,避免 FFmpeg 报错)。它比写死 1280x720 更安全,尤其对竖屏视频。
其他关键参数影响:
-
-preset medium:平衡速度与压缩率,slow更小但耗时翻倍,fast可能画质损失明显 -
-b:v 1200k:视频码率,太低(如 500k)导致模糊,太高(如 3000k)浪费带宽 -
-ss 00:00:01 -vframes 1提取封面图时,加-ss在解码前跳帧,比-ss放后面快 10 倍以上
真正容易被忽略的是权限和路径:Worker 进程运行用户(如 www-data)必须对输入目录、输出目录、临时文件夹都有读写权限,且 output.mp4 路径不能含中文或空格。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











