PHP exec - 在进行过程中逐行回显输出

时间:2014-03-31 15:59:23

标签: php ffmpeg exec echo outputstream

我试图找到一种方法,在其中我可以回显exec调用的输出,然后在进程运行时将其刷新到屏幕。我编写了一个简单的PHP脚本,它接受文件上传,然后使用FFMPEG将文件转换为不合适的文件类型。我在Windows机器上这样做。目前我的命令如下:

$cmd = "ffmpeg.exe -i ..\..\uploads\\".$filename." ..\..\uploads\\".$filename.".m4v 2>&1";
exec( $cmd, $output);

我需要这样的东西:

while( $output ) {
    print_r( $output);
    ob_flush();  flush();  
}  

我已经读过使用ob_flush()flush()来清除输出缓冲区,但是只有在进程完成后才会输出。该命令工作正常,它只是在转换时不更新页面。我希望有一些输出,以便该人知道发生了什么。

我已经设定了时间

set_time_limit( 10 * 60 ); //5 minute time out
如果有人能让我朝着正确的方向前进,我会非常感激。我已经看过一些Stackoverflow附近的解决方案,但似乎都没有。

3 个答案:

答案 0 :(得分:1)

由于exec调用是阻塞调用,因此无法使用缓冲区来获取状态。

相反,您可以将系统调用中的输出重定向到日志文件。让客户端查询服务器以获取进度更新,在这种情况下,服务器可以解析日志文件的最后几行以获取有关当前进度的信息并将其发送回客户端。

答案 1 :(得分:0)

exec()阻塞调用,在外部程序终止之前不会将控制权返回给PHP。这意味着你不能做任何事情来逐行转储输出,因为PHP在外部应用程序运行时被暂停。

对于你想要的,你需要使用proc_open,它返回一个你可以在循环中读取的文件句柄。 e.g。

$fh = proc_open('.....');
while($line = fgets($fh)) {
    print($line);
    flush();
}

答案 2 :(得分:0)

这种方法存在两个问题:

首先,正如@Marc B所指出的那样,exec将阻止直到它完成为止。你必须设计一些衡量进展的方法。

第二个是以这种方式使用ob_flush()相当于保持服务器和服务器之间的连接。客户打开并一次一点地输出数据。这不是HTTP协议的设计目标,虽然它有时可能有效,但它不能始终如一地工作 - 不同的浏览器和不同的服务器会以不同的方式超时。更好的方法是通过AJAX调用:使用Javascript的setTimeout()函数(或setInterval()),定期调用服务器并让服务器发回进度报告。