【问题标题】:PHP Run FFMPEG in background, and find out when it's done [duplicate]PHP在后台运行FFMPEG,并找出它何时完成[重复]
【发布时间】:2012-09-18 18:08:07
【问题描述】:

可能重复:
Run a ffmpeg process in the background

我想知道是否有任何简单的方法可以在后台运行和 ffmpeg 进程,以便人们可以离开页面。如果你这样做了,然后告诉 ffmpeg 进程是否正在运行,当它完成时,将数据库更新为“完成”。如果需要,我会发布我的代码。谢谢! 这是处理页面上的代码:

<?php
$name = $_FILES['upload_file']['name'];
$type = $_FILES['upload_file']['type'];
$size = $_FILES['upload_file']['size'];
$tmpname = $_FILES['upload_file']['tmp_name'];

if (!$title) {
    $title = $name;
}

if (!$description) {
    $description = "No description available.";
}

$string = substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',10)),0,10);
$videoname = "$string.mp4";
$date = date("F d, Y"); // October 09, 2010
$srcFile = $tmpname;
mkdir("users/$usercode/uploads/$string");
mkdir("users/$usercode/uploads/$string/HD");
mkdir("users/$usercode/uploads/$string/regular");
mkdir("users/$usercode/uploads/$string/mobile_upload");
mkdir("users/$usercode/uploads/$string/thumbnails");
$destFile1 = "/users/$usercode/uploads/$string/HD/$string.mp4";
$destFile2 = "/users/$usercode/uploads/$string/regular/$string.mp4";
$destFile3 = "/users/$usercode/uploads/$string/mobile_upload/$string.mp4";
$ffmpegPath = "/usr/local/bin/ffmpeg"; 
$flvtool2Path = "/usr/bin/flvtool2";
$yamdiPath = "/usr/bin/yamdi";
$mp4boxPath = "/usr/local/bin/MP4Box";
// Create our FFMPEG-PHP class 
$ffmpegObj = new ffmpeg_movie($srcFile); 
// Save our needed variables 
$srcWidth = $ffmpegObj->getFrameWidth(); 
$srcHeight = $ffmpegObj->getFrameHeight(); 
$srcFPS = $ffmpegObj->getFrameRate(); 
$srcAB = $ffmpegObj->getAudioBitRate();  
$srcAR = $ffmpegObj->getAudioSampleRate(); 
$res = $srcWidth . "x" . $srcHeight; 
// Call our convert using exec() 
$iphone1 = getcwd().$destFile1;
$iphone2 = getcwd().$destFile2;
$iphone3 = getcwd().$destFile3;
$low = "854x480";
$local_img = "/users/$usercode/uploads/$string/thumbnails/$string.jpg";
$img = getcwd().$local_img;
$img = preg_replace('/ /','\ ',$img); 
$thumb = "$string.jpg"; 
$cmd = "$ffmpegPath -i $tmpname 2>&1";  
if (preg_match('/Duration: ((\d+):(\d+):(\d+))/s', `$cmd`, $time)) {  
    $total = ($time[2] * 3600) + ($time[3] * 60) + $time[4];  
    $interval = rand(0, $total);  
}  

$img = shell_exec("$ffmpegPath -ss $interval -i $tmpname 2>&1 -s 120x90 -f mjpeg -vframes 1 $img");


if ($srcWidth >= 1280 && $srcHeight >= 720) {
    $out1 = shell_exec("$ffmpegPath -i $tmpname -f mp4 -vcodec libx264 -vpre normal -ab $srcAB -ar $srcAR -b 5000k -r $srcFPS -s $res -acodec libfaac $iphone1");
    $out2 = shell_exec("$mp4boxPath -inter 0.5 $iphone1");
    $out3 = shell_exec("$ffmpegPath -i $tmpname -f mp4 -vcodec libx264 -vpre normal -ab $srcAB -ar $srcAR -b 2000k -r $srcFPS -s $low -acodec libfaac $iphone2");
    $out4 = shell_exec("$mp4boxPath -inter 0.5 $iphone2");
    $out5 = shell_exec("$ffmpegPath -i $tmpname -f mp4 -vcodec libx264 -vpre slow -ab 64k -ar 44100 -b 500k -r 30 -s $low -acodec libfaac $iphone3");
    $out6 = shell_exec("$mp4boxPath -inter 0.5 $iphone3");
    echo 1;
}
else {
    $out3 = shell_exec("$ffmpegPath -i $tmpname -f mp4 -vcodec libx264 -vpre normal -ab 64k -ar 44100 -b 500k -r 30 -s $low -acodec libfaac $iphone2");
    $out4 = shell_exec("$mp4boxPath -inter 0.5 $iphone2");
    $out5 = shell_exec("$ffmpegPath -i $tmpname -f mp4 -vcodec libx264 -vpre slow -ab 64k -ar 44100 -b 500k -r 30 -s $low -acodec libfaac $iphone3");
    $out6 = shell_exec("$mp4boxPath -inter 0.5 $iphone3");          
    echo 1;
}
function generate_random($number_of_characters)
{
        $characters = array();
        $randomchar = "";
        $x = 0;
        for($i = 48; $i < 123; $i++)
        {
                if(ctype_alnum(chr($i)))
                {
                        $characters[$x] = chr($i);
                        $x++;
                }
        }
        for($i = 0; $i < $number_of_characters; $i++)
        {
                $randomchar .= $characters[rand(0, count($characters) - 1)];
        }
        return $randomchar;
}
?>

【问题讨论】:

  • 发布代码通常总是一个好主意。 :)
  • 我想你的答案就在这里:stackoverflow.com/questions/1198052/…
  • 是的,我试着看了一下,但我不太明白如何在我现有的代码中实现它:/
  • 谢谢!我一直在努力解决这个问题哈哈。其他一切正常,只是这件小事! :)
  • 您的代码非常不安全。您对 SQL 注入完全开放,如果您还没有被黑客入侵,那么您将会被黑客入侵。学习使用 PDO 或等效的准备好的查询来避免这个问题。此外,尚不清楚$usercode 是什么,但您可能会遇到麻烦,人们可以在您的服务器上执行和做他们想做的任何事情。

标签: php process background ffmpeg


【解决方案1】:

首先,您的代码很容易受到 SQL 注入攻击和 shell 参数攻击。您需要将所有输入转义到 SQL 和 shell 命令!

我认为这将是解决此问题的标准方法:

  1. 将您的 ffmpeg“作业”写入数据库元组。请注意作业编号,这将是元组的主键。此时,“状态”需要不是“完成”。
  2. 将所有 ffmpeg 处理代码移动到辅助 PHP 脚本中。助手,我只是指另一个脚本。称之为“ffmpeg_job_processor.php”。
  3. 通过调用exec('php ffmpeg_job_processor.php '.escapeshellarg($jobNumber).' &gt; /dev/null &amp;');在后台运行该脚本该脚本将按ID从数据库加载作业,执行所有处理,完成后将更新数据库以“完成”。
  4. 基于 Web 的作业监控页面可以通过按 ID 查找相同的元组轻松显示作业状态。

诀窍是在后台执行第二个 PHP 脚本,这样它就会释放您的调用 PHP 脚本以继续运行而不会阻塞。您必须将stdout 传送到/dev/null(Linux 机器)并使用后台操作符&amp;

这里有更多好的信息:Run a ffmpeg process in the background

【讨论】:

  • 关于如何修补 SQL 的任何建议?这是我找到的一些旧代码,希望能再次运行。
  • 不推荐使用 mysql 扩展,但如果您想继续使用它,您必须使用 mysql_real_escape_string 引用所有 SQL 查询参数。
  • 看来我有一些修补工作要做!谢谢大家的反馈!
  • 没问题!并且不要忘记escapeshellarg 对于所有这些shell 命令,如果它们中的任何一个是从外部输入构建的。即使不是,这也是一种很好的做法。
猜你喜欢
  • 2018-02-23
  • 2021-06-15
  • 1970-01-01
  • 1970-01-01
  • 2013-05-07
  • 2013-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多