5

ffmpegを使用してビデオをphpで.flvに変換したいと思っています。現在、これは機能していますが、ファイルがアップロードされて終了するまでブラウザがハングします。返されたPIDを使用してプロセスを更新しながら、バックグラウンドでexec()プロセスを実行する方法についてのphpドキュメントを見てきました。これが私が見つけたものです:

//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);
}

これらの関数の1つを実行するためにphpcliから実行される別の.phpファイルを作成することを想定していますか?私はこれを機能させるために少し微調整する必要があり、それから私はそこからそれを取ることができます。

ありがとう!

4

2 に答える 2

10

これらの関数の1つを実行するためにphpcliから実行される別の.phpファイルを作成することを想定していますか?

これはおそらく私がそれをする方法です:

  • PHP Webページは、「このファイルを処理する必要がある」ことを示すレコードをデータベースに追加します
    • ユーザーへのメッセージを表示します; 「ファイルはまもなく処理されます」のようなもの
  • CLIで、新しく挿入されたファイルをバッチ処理します
    • まず、レコードを「処理中」としてマークします
    • ffmpegのことをする
    • ファイルを「処理済み」としてマークします
  • また、Webページで、ファイルがどの状態にあるかをユーザーに表示できます。
    • まだ処理されていない場合
    • 処理中の場合
    • または、処理されている場合は、新しいビデオファイルへのリンクを彼に与えることができます。

ここに他のいくつかの考えがあります:

  • アプリケーションが大きくなった日、次のことができます。
    • 1つの「Webサーバー」
    • 多くの「処理サーバー」; あなたのアプリケーションでは、ウェブページを提供するのではなく、多くのCPUを必要とするのはffmpegです。したがって、その部分をスケーリングできることは素晴らしいことです(これは、ファイルを「ロック」し、DBで「処理中」として示すこともできます。そうすれば、同じファイルを処理しようとする複数の処理サーバーがなくなります)
  • WebサーバーのPHPを使用して、Webページを生成するだけです。これはWebサーバーの仕事です。
    • 重い/長い処理はWebサーバーの仕事ではありません!
    • 「処理」の部分をPHP以外のものに切り替えたい日は、もっと簡単になります。

「処理スクリプト」は、数分ごとに起動する必要があります。Linuxのようなマシンを使用している場合は、cronを使用できます。


編集:コメントを見た後、もう少し情報

処理部分はApacheではなくCLIから実行されるため、「バックグラウンド」操作は必要ありません。を使用するだけshell_execで、コマンドの出力全体がジョブの実行が終了したときにPHPスクリプトに返されます。 。

「処理中」と言っているWebページを見ているユーザーにとっては、バックグラウンド処理のように見えます。そして、ある意味では、処理は別のプロセスによって(おそらく別のマシン上でも)行われるので、そうなるでしょう。

しかし、あなたにとって、それははるかに簡単になります:

  • 1つのWebページ(「背景」はありません)
  • 1つの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から定期的に起動されることだけです。


お役に立てれば :-)

于 2009-07-29T04:46:34.877 に答える
0

これを行うために別のphpスクリプトを作成する必要はありません(ただし、ある種のキューイングシステムを実装する場合は後で作成することもできます)。

もうすぐです。唯一の問題は、shell_exec()がブロックを呼び出して、シェルが返されるのを待つことです。シェル内のコマンドからのすべての出力をリダイレクトしてファイルまたは/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を取得する方法はないと思います。

于 2009-07-29T05:27:00.457 に答える