Php 如何配置proc“U open”;管道;对于Windows上的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”的部分将重定向标准输出 (

首先,我花了一周的时间在谷歌上搜索并尝试了几十种Unix答案的变体,但这是一个彻底的失败,我需要一个针对Windows的答案,所以这不是一个重复的Unix等价问题

我们正在尝试创建一个调度任务,该任务将在PHP中处理一个任务队列,并一次维护最多10个ffmpeg实例的数组。我试过
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);