【问题标题】:Continue php after page closed exec() ffmpeg页面关闭后继续 php exec() ffmpeg
【发布时间】:2019-02-20 12:58:22
【问题描述】:

我想知道在exec() (ffmpeg) 之后如何继续一个 php 页面并且页面已关闭。

我有一个表单,允许人们使用 ffmpeg 转换他们的视频文件,但如果用户点击离开页面,exec() 会继续运行,但不会执行此 exec 之后的任何内容。

<?php
   if (!empty($_POST) && $imgDir) {
      exec('"/dir/to/ffmpeg" -f image2 -i "' . $imgDir . '" -r 12 -s 610x489 /dir/to/out.avi', $out);

      /* INSERT statement (Not being executed) */
      $sql = "INSERT INTO requests (userID,image) VALUES (?,?)";
      $stmt= $pdo->prepare($sql);
      $stmt->execute([$user_id, $imgDir]);
   }
?>

我希望用户能够点击离开页面,这样他们就不必等待,以后可以下载他们的文件。

【问题讨论】:

  • 您可能希望将转换过程卸载到后台脚本(例如,由 cron 定期触发的作业)。网页只会将请求放入队列(例如,在 db 表中)并保存文件。然后后台服务会从队列中挑选下一个项目,对其进行处理,并将其标记为完成。然后你必须考虑如何通知用户。您可以向他们发送电子邮件,或者有一个状态页面,他们可以在其中检查他们的工作并下载任何准备好的文件,或两者兼而有之,或您选择的其他一些过程。也许您可以允许用户指定他们希望如何被告知。
  • P.S.你确定 INSERT 查询没有被执行吗?可能只是 SQL 查询失败……您是否设置了 PDO 以在发生这种情况时抛出异常?你在记录异常吗?我还注意到 SQL 块不在 if (!empty($_POST)... 块内,因此即使用户没有提交任何数据也会执行......我怀疑这是可取的。
  • @ADyson 你是对的,我认为在后台运行它会更好。当多人想要同时转换时,队列非常适合。 (我复制代码的方式错误,查询在实际代码中的 if 语句中。)

标签: php html post ffmpeg


【解决方案1】:

在这种情况下,一个常见的解决方案是将转换过程卸载到后台脚本(例如,由 cron 定期触发的作业)。这样可以避免长时间运行的进程超时或外部命令行进程无法正确返回的问题。

网页只会将请求放入队列(例如,在 db 表中)并保存文件。

然后后台服务会从队列中挑选下一个项目,对其进行处理,并将其标记为完成。

然后你必须考虑如何通知用户。您可以向他们发送电子邮件,或者有一个状态页面,他们可以在其中检查他们的工作并下载任何准备好的文件,或两者兼而有之,或您选择的其他一些过程。也许您可以允许用户指定他们希望如何被告知。

【讨论】:

    【解决方案2】:

    如果你想在后台从 PHP 启动这个命令,你可以通过这个模式运行非阻塞进程:

    if(is_resource($proc = proc_open($cmd, [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipes)))
    {
        stream_set_blocking($pipes[1], false);
        stream_set_blocking($pipes[2], false);
    

    在 Linux 系统上,您可以启动带有前缀 nohup 的命令,例如

    $cmd = 'nohup "/dir/to/ffmpeg" -f image2 -i "' . $imgDir . '" -r 12 -s 610x489 /dir/to/out.avi'
    

    使用nohup 后,您甚至可以退出启动新进程的进程。它将与父进程分离。

    【讨论】:

    • 这是在后台运行ffmpeg还是整个php文件/进程?
    • @Tygo proc_open 启动一个新的系统进程,类似于exec 和其他系统函数,但使用管道而不是通过引用返回函数值/参数。 stream_set_blocking 从流中读取时不等待 EOF。但是,当父进程完成而不等待子进程完成时,子进程仍然会被杀死,除非您使用nohup linux 命令分离子进程。简而言之:子进程,即ffmpeg 在后台运行。
    • @Tygo 如果您不想从孩子的 STDOUT/STDERR 接收输出数据(运行并忘记),您甚至不需要使用管道并设置非阻塞模式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多