如何在FFmpeg命令中使用PHP动态生成的图片?
解决方法
你的问题核心是FFmpeg的-i参数需要的是文件路径或标准输入流,而非直接传入图片二进制数据,之前的写法把二进制内容当成文件名传入,自然无法执行。下面提供两种可行方案:
方案一:临时文件中转(简单易调试)
先把PHP生成的图片保存为临时文件,再让FFmpeg读取这个文件:
// 捕获generateImg.php输出的图片二进制数据 ob_start(); require_once('generateImg.php'); $imgData = ob_get_clean(); // 创建临时PNG文件 $tempFile = tempnam(sys_get_temp_dir(), 'temp_img_') . '.png'; file_put_contents($tempFile, $imgData); // 执行FFmpeg命令,使用临时文件作为输入 exec("ffmpeg -loop 1 -t 1 -i '$tempFile' -i audio.mp3 -f flv -vf scale=640:ih*640/iw -shortest output.mp4"); // 生成视频后删除临时文件 unlink($tempFile);
如果想更优雅,可以修改generateImg.php,让它直接返回图片数据而非输出:
// 修改后的generateImg.php <?php function getGeneratedImage() { $image = imagecreate(500, 300); $background_color = imagecolorallocate($image, 0, 153, 0); $text_color = imagecolorallocate($image, 255, 255, 255); imagestring($image, 5, 180, 100, "GeeksforGeeks", $text_color); imagestring($image, 3, 160, 120, "A computer science portal", $text_color); ob_start(); imagepng($image); $imgData = ob_get_clean(); imagedestroy($image); return $imgData; } // 直接访问该文件时仍输出图片 if (basename($_SERVER['PHP_SELF']) === basename(__FILE__)) { header("Content-Type: image/png"); echo getGeneratedImage(); }
调用时就无需ob_start,直接获取数据:
require_once('generateImg.php'); $imgData = getGeneratedImage(); // 后续临时文件逻辑同上
方案二:管道直接传输(无临时文件,效率更高)
利用FFmpeg支持从标准输入读取数据的特性,直接把图片二进制流通过管道传给FFmpeg:
require_once('generateImg.php'); $imgData = getGeneratedImage(); // 使用修改后的generateImg.php // 构建FFmpeg命令,-f png指定输入格式,-i -表示读取标准输入 $cmd = "ffmpeg -loop 1 -t 1 -f png -i - -i audio.mp3 -f flv -vf scale=640:ih*640/iw -shortest output.mp4"; // 使用proc_open处理管道输入 $descriptorspec = [ 0 => ["pipe", "r"], // 标准输入(写) 1 => ["pipe", "w"], // 标准输出(读) 2 => ["pipe", "w"] // 错误输出(读) ]; $process = proc_open($cmd, $descriptorspec, $pipes); if (is_resource($process)) { // 将图片数据写入FFmpeg的标准输入 fwrite($pipes[0], $imgData); fclose($pipes[0]); // 可选:读取FFmpeg的输出和错误信息用于调试 $output = stream_get_contents($pipes[1]); $error = stream_get_contents($pipes[2]); fclose($pipes[1]); fclose($pipes[2]); // 等待命令执行完成 proc_close($process); }
注意事项
- 确保服务器安装了FFmpeg,且PHP的
exec/proc_open函数未被禁用 - 临时文件方案需要服务器的临时目录(
sys_get_temp_dir()返回的路径)有写入权限 - 若生成的视频仍有问题,可以打印FFmpeg的错误输出(方案二中的
$error变量)排查具体问题
内容的提问来源于stack exchange,提问作者amirhosein hadi
相关产品推荐
相关产品推荐

