Php 如何配置proc“U open”;管道;对于Windows上的ffmpeg标准输入/标准输出?
首先,我花了一周的时间在谷歌上搜索并尝试了几十种Unix答案的变体,但这是一个彻底的失败,我需要一个针对Windows的答案,所以这不是一个重复的Unix等价问题 我们正在尝试创建一个调度任务,该任务将在PHP中处理一个任务队列,并一次维护最多10个ffmpeg实例的数组。我试过Php 如何配置proc“U open”;管道;对于Windows上的ffmpeg标准输入/标准输出?,php,ffmpeg,window,proc-open,Php,Ffmpeg,Window,Proc Open,首先,我花了一周的时间在谷歌上搜索并尝试了几十种Unix答案的变体,但这是一个彻底的失败,我需要一个针对Windows的答案,所以这不是一个重复的Unix等价问题 我们正在尝试创建一个调度任务,该任务将在PHP中处理一个任务队列,并一次维护最多10个ffmpeg实例的数组。我试过exec,shell\u exec,加上/不加start/B,但没有任何“完全”的运气。 我也很确定这与设置描述符spec和管道有关(我完全不熟悉),原因如下: 每 标有“>/dev/null”的部分将重定向标准输出 (
exec
,shell\u exec
,加上/不加start/B
,但没有任何“完全”的运气。
我也很确定这与设置描述符spec和管道有关(我完全不熟悉),原因如下:
每
标有“>/dev/null”的部分将重定向标准输出
(stdout)将ffmpeg实例的
输出)和“2>/dev/null”将标准错误(stderr)重定向到
/dev/null(有效地忽略任何错误日志消息)。这两个可以
可以组合成一个较短的表示形式:“>/dev/null 2>&1”。如果你
您可以阅读更多关于I/O重定向的信息
这里应该提到一个重要的注意事项。ffmpeg命令行
工具使用stderr输出错误日志消息,stdout是
保留供可能使用的管道(用于重定向输出介质
从ffmpeg生成的流到其他命令行工具)。那个
也就是说,如果您在后台运行ffmpeg,您将
可能希望将stderr重定向到日志文件,以便能够
待会再查
还要注意的是标准输入(stdin)。
命令行ffmpeg工具被设计为一个交互式实用程序
接受用户输入(通常来自键盘)并报告错误日志
在用户的当前屏幕/终端上。当我们在
背景,我们想告诉ffmpeg,不应接受任何输入
(也没有等待)从标准输入。我们可以使用I/O将其告知ffmpeg
“再次重定向”
此外,如以下文件所述:
在标准输入上启用交互。默认情况下启用,除非是标准输入
输入用作输入。要显式禁用交互,需要
指定-nosdin
-nostdin
选项似乎表明它解决了我的问题,但没有明显的影响。在我找到的所有Unix解决方案中,它似乎仍然需要某种形式的此Unix添加:&1
那么,在这篇有点详尽的开场白中,有人能解释一下如何正确配置proc_open
函数,以满足ffmpeg.exe
如何与I/O交互吗?如果有更好或更合适的方法,我很乐意这样做,但重要的是能够循环通过一系列进程来检查我们已经完成了,因此其他更快的流程可以同时完成
更新
在进行了详尽的研发之后,似乎I/O并不是实现这一点的关键(nostdin的-nostdin
选项似乎与广告中的一样有效)。我设计的前提是使用proc\u get\u status()
以确定ffmpeg
何时完成。该方法的缺陷在于,它显然没有返回ffmpeg进程的实际PID…它返回父PID。因此,当proc\u get\u status()时
返回视频转换已完成,事实上它仍在运行,未挂起。在更大的视频文件上进行测试会使问题更加复杂。视频越大,“剩余”越长“实际完成需要时间——I/O不是问题——问题在于监视父PID而不是子PID。因此,如果不深入了解Windows较低级别的系统内部,直接使用PHP似乎不可能做到这一点。我决定放弃这种方法,但希望这个发现能为其他人节省一些时间和麻烦
echo "Starting ffmpeg...\n\n";
echo shell_exec("ffmpeg -y -i input.avi output.avi </dev/null >/dev/null 2>/var/log/ffmpeg.log &");
echo "Done.\n";
$descriptorspec = array(
array('pipe', 'r'),
array('pipe', 'w'),
array('pipe', 'w'),
);
$pipes = null;
$cwd = null;
$env = null;
$process = proc_open('start /B ffmpeg.exe -i input.mov output.mp4 -nostdin', $descriptorspec, $pipes, $cwd, $env);
$status = proc_get_status($process);
while($status['running']) {
sleep (60);
$status = proc_get_status($process);
}
proc_terminate($process);