在后台运行 ffmpeg 进程

发布于 2024-07-29 16:30:20 字数 827 浏览 6 评论 0原文

我想在 php 中使用 ffmpeg 将视频转换为 .flv。 目前我可以正常工作,但它会挂起浏览器,直到文件上传并完成。 我一直在查看 php 文档,了解如何在后台运行 exec() 进程,同时使用返回的 PID 更新进程。 这是我发现的:

//Run linux command in background and return the PID created by the OS
function run_in_background($Command, $Priority = 0)
{
    if($Priority)
        $PID = shell_exec("nohup nice -n $Priority $Command > /dev/null & echo $!");
    else
        $PID = shell_exec("nohup $Command > /dev/null & echo $!");
    return($PID);
}

我还使用一个技巧来跟踪后台任务是否正在使用返回的 PID 运行:

//Verifies if a process is running in linux
function is_process_running($PID)
{
    exec("ps $PID", $ProcessState);
    return(count($ProcessState) >= 2);
}

我是否想创建一个单独的 .php 文件,然后从 php cli 运行该文件来执行这些函数之一? 我只需要一点点推动就可以让它工作,然后我就可以从那里开始。

谢谢!

I am wanting to use ffmpeg to convert video to .flv in php. Currently I have this working, but it hangs the browser until the file is uploaded and is finished. I have been looking at the php docs on how to run an exec() process in the background, while updating the process using the returned PID. Here is what I found:

//Run linux command in background and return the PID created by the OS
function run_in_background($Command, $Priority = 0)
{
    if($Priority)
        $PID = shell_exec("nohup nice -n $Priority $Command > /dev/null & echo $!");
    else
        $PID = shell_exec("nohup $Command > /dev/null & echo $!");
    return($PID);
}

There is also a trick which I use to track if the background task is running using the returned PID :

//Verifies if a process is running in linux
function is_process_running($PID)
{
    exec("ps $PID", $ProcessState);
    return(count($ProcessState) >= 2);
}

Am I suppose to create a separate .php file which then runs from the php cli to execute one of these functions? I just need a little nudge in getting this working and then I can take it from there.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

離人涙 2024-08-05 16:30:20

我应该创建一个单独的 .php
然后从 php cli 运行的文件
执行这些函数之一?

这可能是我会这样做的方式:

  • PHP 网页在数据库中添加一条记录以指示“必须处理此文件”
    • 并向用户显示一条消息; 类似“您的文件将很快得到处理”
  • 在 CLI 中,对新插入的文件进行批处理
    • 首先,将一条记录标记为“正在处理”
    • 做 ffmpeg 的事情
    • 将文件标记为“已处理”
  • 并且,在网页上,您可以向用户显示他的文件处于哪种状态:
    • 如果尚未处理
    • 如果正在处理
    • 或者如果它已被处理 - 您可以向他提供新视频文件的链接。

这里有一些其他的想法:

  • 当你的应用程序变得更大的时候,你可以拥有:
    • 一个“网络服务器”
    • 许多“处理服务器”; 在您的应用程序中,ffmpeg 需要大量 CPU,而不是提供网页; 因此,能够扩展该部分是很好的(这是“锁定”文件的另一个方法,将它们指示为数据库中的“处理”:这样,您将不会有多个处理服务器尝试处理同一文件)
  • 您只使用 PHP Web服务器生成网页,这是Web服务器的工作
    • 繁重/长时间的处理不是网络服务器的工作!
    • 有一天,您想要切换到 PHP 以外的其他语言来执行“处理”部分,这会更容易。

您的“处理脚本”必须每隔几分钟启动一次; 如果你使用的是类似 Linux 的机器,你可以使用 cron 来实现。


编辑:看到评论后,请提供更多信息

由于处理部分是从 CLI 完成的,而不是从 Apache 完成的,因此您不需要任何类型的“后台”操作:您可以只使用 shell_exec,当它完成时,它将把命令的整个输出返回给你的 PHP 脚本工作。

对于观看网页的用户来说,说“正在处理”,这看起来像是后台处理; 并且,在某种程度上,它会是的,因为处理将由另一个进程(甚至可能在另一台机器上)完成。

但是,对您来说,它会简单得多:

  • 一个网页(没有“背景”)
  • 一个 CLI 脚本,也没有背景内容。

我想您的处理脚本可能看起来像这样:

// Fetch informations from DB about one file to process
// and mark it as "processing"

// Those would be fetched / determined from the data you just fetched from DB
$in_file = 'in-file.avi';
$out_file = 'out-file.avi';

// Launch the ffmpeg processing command (will probably require more options ^^ )
// The PHP script will wait until it's finished : 
//   No background work
//   No need for any kind of polling
$output = shell_exec('ffmpeg ' . escapeshellarg($in_file) . ' ' . escapeshellarg($out_file));

// File has been processed
// Store the "output name" to DB
// Mark the record in DB as "processed"

真的比您最初想象的要容易,不是吗? ;-)

不用再担心后台的事情了:唯一重要的是处理脚本会从 crontab 定期启动。

希望这可以帮助 :-)

Am I suppose to create a separate .php
file which then runs from the php cli
to execute one of these functions?

This is probably the way I would do it :

  • the PHP webpage adds a record in database to indicate "this file has to be processed"
    • and displays a message to the user ; something like "your file will be processed soon"
  • In CLI, have a batch process the new inserted files
    • first, mark a record as "processing"
    • do the ffmpeg thing
    • mark the file as "processed"
  • And, on the webpage, you can show to the user in which state his file is :
    • if it has not been processed yet
    • if it's being processed
    • or if it's been processed -- you can then give him the link to the new video file.

Here's a couple of other thoughts :

  • The day your application becomes bigger, you can have :
    • one "web server"
    • many "processing servers" ; in your application, it's the ffmpeg thing that will require lots of CPU, not serving web pages ; so, being able to scale that part is nice (that's another to "lock" files, indicating them as "processing" in DB : that way, you will not have several processing servers trying to process the same file)
  • You only use PHP from the web server to generate web pages, which is je job of a web server
    • Heavy / long processing is not the job of a web server !
    • The day you'll want to switch to something else than PHP for the "processing" part, it'll be easier.

Your "processing script" would have to be launch every couple of minutes ; you can use cron for that, if you are on a Linux-like machine.


Edit : a bit more informations, after seeing the comment

As the processing part is done from CLI, and not from Apache, you don't need anykind of "background" manipulations : you can just use shell_exec, which will return the whole ouput of the command to your PHP script when it's finished doing it's job.

For the user watching the web page saying "processing", it will seem like background processing ; and, in a way, it'll be, as the processing will be done by another processus (maybe even on another machine).

But, for you, it'll be much simpler :

  • one webpage (nothing "background")
  • one CLI script, with no background stuff either.

Your processing script could look like something like this, I suppose :

// Fetch informations from DB about one file to process
// and mark it as "processing"

// Those would be fetched / determined from the data you just fetched from DB
$in_file = 'in-file.avi';
$out_file = 'out-file.avi';

// Launch the ffmpeg processing command (will probably require more options ^^ )
// The PHP script will wait until it's finished : 
//   No background work
//   No need for any kind of polling
$output = shell_exec('ffmpeg ' . escapeshellarg($in_file) . ' ' . escapeshellarg($out_file));

// File has been processed
// Store the "output name" to DB
// Mark the record in DB as "processed"

Really easier than what you first thought, isn't it ? ;-)

Just don't worry about the background stuff anymore : only thing important is that the processing script is launched regularly, from crontab.

Hope this helps :-)

愁以何悠 2024-08-05 16:30:20

您不需要编写单独的 php 脚本来执行此操作(尽管如果您实现某种排队系统,您可能需要稍后编写)。

你快到了。 唯一的问题是,shell_exec() 调用会阻塞以等待 shell 的返回。 如果您将 shell 中命令的所有输出重定向到删除文件或 /dev/null 并将任务置于后台(使用 & 运算符),则可以避免这种情况。
所以你的代码将变成:

//Run linux command in background and return the PID created by the OS
function run_in_background($Command, $Priority = 0)
{
    if($Priority) {
        shell_exec("nohup nice -n $Priority $Command 2> /dev/null > /dev/null &");
    } else {
        shell_exec("nohup $Command 2> /dev/null > /dev/null &");
    }
}

不幸的是,我认为没有任何方法可以检索 PID。

You don't need to write a separate php script to do this (Though you may want to later if you implement some sort of queuing system).

You're almost there. The only problem is, the shell_exec() call blocks to wait for the return of the shell. You can avoid this if you redirect all output from the command in the shell to wither a file or /dev/null and background the task (with the & operator).
So your code would become:

//Run linux command in background and return the PID created by the OS
function run_in_background($Command, $Priority = 0)
{
    if($Priority) {
        shell_exec("nohup nice -n $Priority $Command 2> /dev/null > /dev/null &");
    } else {
        shell_exec("nohup $Command 2> /dev/null > /dev/null &");
    }
}

I don't think there is any way to retrieve the PID, unfortunately.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文