PHP调用FFMPEG处理音频时如何实现实时流式返回处理结果
实现方案
你当前使用的shell_exec会等待进程完全结束后才返回全部输出,天然无法满足实时返回的需求,换成popen读取FFMPEG的标准输出流,边读边输出到前端即可实现效果。
可直接使用的代码
<?php // 输入安全校验,避免路径遍历漏洞,禁止删除 $fileName = basename($_GET['file']); $filePath = __DIR__ . "/../data/" . $fileName; if (!file_exists($filePath)) { http_response_code(404); exit; } // 关闭PHP默认输出缓冲 if (ob_get_level()) ob_end_clean(); // 输出音频头 header("Content-Type: audio/wav"); // Nginx环境下加下面这行关闭Nginx代理缓冲,Apache环境可以删掉 header('X-Accel-Buffering: no'); // 打开FFMPEG进程的只读管道,加-flush_packets 1强制FFMPEG不缓存输出,2>/dev/null丢弃日志避免污染音频流 $ffmpegHandle = popen("ffmpeg -i " . escapeshellarg($filePath) . " -f wav -flush_packets 1 pipe:1 2>/dev/null", "r"); // 逐块读取FFMPEG输出并推给前端,每次读取8192字节可根据需求调整 while (!feof($ffmpegHandle)) { echo fread($ffmpegHandle, 8192); // 刷新缓冲区直接输出内容 ob_flush(); flush(); } // 关闭管道 pclose($ffmpegHandle); ?>
额外注意事项
- 代码中
escapeshellarg用于避免命令注入漏洞,basename用于避免路径遍历漏洞,不要删除 - 如果需要捕获FFMPEG的错误信息做异常处理,可以把
popen换成功能更丰富的proc_open,可以同时接管标准输入、标准输出、错误输出三个流 - 部分云服务商的WAF/CDN默认会开启响应缓冲,遇到缓冲不生效的情况可以检查对应服务的配置关闭缓冲
内容的提问来源于stack exchange,提问作者Xwilarg
相关产品推荐
相关产品推荐

