PHP上传视频自动转码多清晰度文件实现方法咨询
嗨,我来帮你搞定视频自动转码适配VideoJS清晰度切换的问题!这事儿核心靠FFmpeg(业界标准的视频处理工具)+ PHP的命令执行能力,下面一步步给你拆解:
一、先搞定服务器环境:安装FFmpeg
首先你的服务器必须装FFmpeg,不然没法转码。不同系统安装方式不一样:
- Ubuntu/Debian:直接在终端跑
sudo apt update && sudo apt install ffmpeg - CentOS/RHEL:先装EPEL源,再装
sudo yum install epel-release && sudo yum install ffmpeg - Windows服务器:去FFmpeg官网下载二进制包,解压后把
ffmpeg.exe所在路径加到系统环境变量里,然后在命令行测试ffmpeg -version能正常输出就行。
二、PHP处理上传+自动转码的核心逻辑
1. 接收并验证上传文件
先写基础的上传接收代码,记得验证文件类型(只允许视频格式,比如mp4、mov、avi),把上传的临时文件移到一个临时处理目录:
<?php // 上传目录(确保www-data用户有读写权限) $uploadDir = './temp_uploads/'; $processedDir = './videos/'; // 创建目录(如果不存在) if (!file_exists($uploadDir)) mkdir($uploadDir, 0755, true); if (!file_exists($processedDir)) mkdir($processedDir, 0755, true); // 处理上传 if ($_FILES['video']['error'] === UPLOAD_ERR_OK) { $originalFileName = $_FILES['video']['name']; $tempFilePath = $uploadDir . uniqid('video_') . '.' . pathinfo($originalFileName, PATHINFO_EXTENSION); // 移到临时目录 move_uploaded_file($_FILES['video']['tmp_name'], $tempFilePath); // 调用转码函数 $transcodedFiles = transcodeVideo($tempFilePath, $processedDir); // 转码完成后可以删除原临时文件 unlink($tempFilePath); } function transcodeVideo($inputPath, $outputDir) { // 定义需要转码的分辨率集合(对应VideoJS的4个清晰度) $resolutions = [ '2160p' => '3840x2160', '1080p' => '1920x1080', '720p' => '1280x720', '480p' => '854x480' ]; $outputFiles = []; $baseName = pathinfo($inputPath, PATHINFO_FILENAME); foreach ($resolutions as $label => $res) { $outputPath = $outputDir . $baseName . '_' . $label . '.mp4'; // FFmpeg转码命令(核心参数) $command = "ffmpeg -i \"$inputPath\" -s $res -c:v libx264 -crf 23 -c:a aac -b:a 128k \"$outputPath\" -y"; // 执行命令并捕获输出 exec($command, $output, $returnCode); if ($returnCode === 0) { $outputFiles[$label] = $outputPath; } else { // 转码失败,记录日志或者处理错误 error_log("转码$label失败:" . implode("\n", $output)); } } return $outputFiles; } ?>
2. FFmpeg命令参数解释
上面的命令里几个关键参数:
-i "$inputPath":指定输入视频文件-s $res:设置输出分辨率(比如1280x720对应720p)-c:v libx264:用H.264编码(VideoJS完美支持)-crf 23:视频质量参数,值越小质量越高(18-28是合理范围)-c:a aac -b:a 128k:音频用AAC编码,比特率128k(平衡音质和体积)-y:如果输出文件已存在,直接覆盖
三、适配VideoJS的清晰度切换
转码完成后,你需要把不同清晰度的文件路径传给VideoJS。如果你的VideoJS已经带切换功能,直接生成对应的<source>标签就行:
<video id="my-video" class="video-js" controls preload="auto" width="1280" height="720" data-setup='{}'> <?php foreach ($transcodedFiles as $label => $path): ?> <source src="<?php echo $path; ?>" type='video/mp4' label='<?php echo $label; ?>' res='<?php echo str_replace('p', '', $label); ?>'> <?php endforeach; ?> </video>
这里的label和res属性是给VideoJS的清晰度切换插件识别用的,确保和你购买的播放器代码逻辑匹配就行。
四、进阶优化建议
- 异步转码:大视频转码会很耗时,别让用户等着!可以把转码任务放到队列(比如用Redis+PHP脚本),后台异步执行,转码完成后给用户发通知。
- 硬件加速:如果服务器有NVIDIA显卡,FFmpeg支持NVENC硬件加速,把命令里的
-c:v libx264换成-c:v h264_nvenc,转码速度能提升好几倍。 - 文件管理:给每个视频生成唯一ID(比如UUID),用ID作为文件名前缀,避免重名问题;定期清理过期的未处理视频文件。
- 错误监控:把转码的错误日志存到文件或者监控系统里,方便排查问题。
内容的提问来源于stack exchange,提问作者40oz
相关产品推荐
相关产品推荐

