转换为MP4的视频经PHP上传后无法在HTML5 video标签显示问题求助
问题核心原因
你当前的代码根本没有执行实际的视频转码操作,仅仅是把上传文件的后缀名强制改成了.mp4,源文件的容器格式、编码规则完全没有变化,而HTML5的video标签仅支持H.264视频编码+AAC音频编码的MP4格式文件,自然无法正常播放。
其他需要修复的错误
- 格式校验逻辑存在漏洞:使用
preg_match匹配后缀容易出现误判,比如后缀为mo也能匹配到mov格式,同时格式列表中混入了纯音频格式wav,不符合视频上传的业务逻辑。 - 存在严重的SQL注入风险:直接将用户可控的参数拼接进SQL语句,未做任何过滤,极易被恶意攻击导致数据泄露、数据库被销毁。
- 文件名生成逻辑错误:
$targetvid . basename($_FILES["post_photo"] . ".mp4")中$_FILES["post_photo"]是数组,直接拼接会得到Array.mp4的错误结果,当前文件名能对应仅为巧合。 - HTML的video标签配置冗余:同一个文件同时配置了
video/mp4和video/ogg两种类型的source,转码后仅存在MP4格式文件,多余配置会导致浏览器解析异常。
解决方法
- 服务器端提前安装FFmpeg工具并配置环境变量,保证PHP可调用,添加实际的转码逻辑,强制输出HTML5兼容的MP4格式,修复现有代码的各类漏洞:
<?php include "includes/dbh.inc.php"; session_start(); if (isset($_SESSION['user_name'])){ if (isset($_POST['submit'])) { $author = $_SESSION['user_name']; $post_photo = time() . '-' . $_FILES["post_photo"]["name"]; if (file_exists($_FILES['post_photo']['tmp_name']) && is_uploaded_file($_FILES['post_photo']['tmp_name'])) { $targetvid = md5(time() . rand(1000,9999)); // 加随机数避免重名 $target_dirvid = "post_video/"; $videotype = strtolower(pathinfo($post_photo, PATHINFO_EXTENSION)); $uploadOk = 0; $video_formats = [ "mpeg", "mp4", "mov", "avi", "dat", "flv", "3gp" ]; // 直接用in_array校验后缀,不需要循环 if(in_array($videotype, $video_formats)){ $uploadOk = 1; } if ($uploadOk == 0) { echo "不支持的视频格式"; } else { // 先保存原始上传文件 $original_file = $target_dirvid . $targetvid . '_original.' . $videotype; move_uploaded_file($_FILES["post_photo"]["tmp_name"], $original_file); // 最终输出的mp4文件名 $target_filevid = $targetvid . '.mp4'; $output_path = $target_dirvid . $target_filevid; // FFmpeg转码命令:强制H264视频编码、AAC音频编码,moov原子前置方便流式播放 $ffmpeg_cmd = "ffmpeg -i ".escapeshellarg($original_file)." -vcodec libx264 -acodec aac -movflags +faststart ".escapeshellarg($output_path)." 2>&1"; exec($ffmpeg_cmd, $output, $return_var); // 转码成功才写入数据库 if($return_var === 0){ // 删除原始文件节省空间 unlink($original_file); // 用预处理语句避免SQL注入 $stmt = $conn->prepare("INSERT INTO video_posts (author, video_post) VALUES (?, ?)"); $stmt->bind_param("ss", $author, $target_filevid); if($stmt->execute()){ echo "上传转码成功"; }else{ echo "数据库写入失败:". $stmt->error; } $stmt->close(); }else{ echo "视频转码失败,错误信息:".implode("\n",$output); // 清理无效文件 unlink($original_file); if(file_exists($output_path)) unlink($output_path); } } } } } ?>
- 修复HTML的video标签代码,删除冗余的ogg source配置,同时输出文件名时做转义避免XSS漏洞:
<video id="myVideo" controls playsinline> <source src="../post_video/<?php echo htmlspecialchars($user_post['video_post']); ?>" type="video/mp4"> </video>
- 检查
post_video文件夹的权限,设置为755,保证web服务器进程有读取权限。
内容的提问来源于stack exchange,提问作者popov
相关产品推荐
相关产品推荐

