donglu9743 2013-10-03 14:03
浏览 185
已采纳

什么是PHP处理ffmpeg和进度条的好函数[重复]

This question already has an answer here:

I ask about ffmpeg and progressbar

I used exec function with ffmpeg and output the result to txt file

and using some of code I found here to

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="es">
<title>AudioXtractor</title>
<body>
<center>



    <?php 

    define('RAPIDLEECH', 'yes');
    define('CONFIG_DIR', 'configs/');
    require_once('configs/config.php');
    define ( 'TEMPLATE_DIR', 'templates/'.$options['template_used'].'/' );
    // Include other useful functions
    require_once('classes/other.php');
    error_reporting(0);

    login_check();

    include(TEMPLATE_DIR.'header.php');

    echo ('<br><br><br><b>AudioXtractor</b>, un complemento <br> que te permite extraer el audio de tus videos.<br><br><br>');

    putenv('GDFONTPATH=' . realpath('.')); ?>

    <br />

    <FORM method="post"><center>
    <TABLE>
      <td>Movie:
    <select name="video">

    <?php
    $exts=array(".ac3", ".avi", ".f4v", ".flv", ".mkv", ".mov", ".mp4", ".mpg", ".mpeg", ".rmvb", ".srt", ".swf", ".wav", ".wmv");
    $ext="";
    function vidlist($dir) 
    {
    $results = array();
    $handler = opendir($dir);
    while ($file = readdir($handler)) 
    {
    if (strrchr($file,'.')!="")
    {
    $ext=strtolower(strrchr($file,'.'));
    }
    if ($file != '.' && $file != '..' && in_array($ext,$GLOBALS["exts"]))
    {
    $results[] = $file;
    }
    }
    closedir($handler);
    sort($results);
    return $results;
    }
    function Output($command) {
    $output = array($command);
    exec($command.' 2>&1', $output);
    return ($output);
    }
    $files = vidlist("./files/");
    foreach($files as $file)
    {
        echo '<option value="'.$file.'">'.$file.'</option>';
    }

    ?>


    </TABLE>

    <br/ >
    New MP3's name: 
    <input type="text" name="nvdo" value="nuevoaudio"> 
    <br/ >
    <br />
    <br />

    <td colspan=2><center><input type=submit style="font-size:16px; font-weight:bold; cursor:pointer;" name="analize" value=Extract /></td>
    <tr>

    </FORM>


    <?php
    if ($_POST['video']!="")

        $video = 'files/';
        $video=array();     
        $video[0] = $_POST['video'];

    if ($_POST['nvdo']!="")

        $nvdo = 'files/';
        $nvdo=array();      
        $nvdo[0] = $_POST['nvdo'];



    foreach ($video as $vdo)
    foreach ($nvdo as $nvd)

    if (isset($_POST["analize"])) {

        exec("ffmpeg -i files/$vdo -ab 192k files/$nvd.mp3 -y 2> files/$nvd.txt");

        $ext=strtolower(strrchr($vdo,'.'));

    /////////////////////////////////////////////////////my code //////////////////////////////////////////

    $content = @file_get_contents("files/$nvd.txt");


        //get duration of source
        preg_match("/Duration: (.*?), start:/", $content, $matches);

        $rawDuration = $matches[1];

        //rawDuration is in 00:00:00.00 format. This converts it to seconds.
        $ar = array_reverse(explode(":", $rawDuration));
        $duration = floatval($ar[0]);
        if (!empty($ar[1])) $duration += intval($ar[1]) * 60;
        if (!empty($ar[2])) $duration += intval($ar[2]) * 60 * 60;

        //get the time in the file that is already encoded
        preg_match_all("/time=(.*?) bitrate/", $content, $matches);

        $rawTime = array_pop($matches);

        //this is needed if there is more than one match
        if (is_array($rawTime)){$rawTime = array_pop($rawTime);}

        //rawTime is in 00:00:00.00 format. This converts it to seconds.
        $ar = array_reverse(explode(":", $rawTime));
        $time = floatval($ar[0]);
        if (!empty($ar[1])) $time += intval($ar[1]) * 60;
        if (!empty($ar[2])) $time += intval($ar[2]) * 60 * 60;

        //calculate the progress
        $progress = round(($time/$duration) * 100);




        echo '<BR><BR>¡Su video fue convertido correctamente! <BR><BR>Link al archivo:';

        echo ' <a href="files/'.$nvd.'.mp3">'.$nvd.'.mp3</a><BR />' . "<br>";
        echo "Duration: " . $duration . "<br>";
        echo "Current Time: " . $time . "<br>";
        echo "Progress: " . $progress . "%" . "<br>";

    //////////////////////////////////////my coed //////////////////////////////////////////////
    }

    ?>
    <br><br><a href="index.php">Volver al RapidLeech</a>

    <br><br><br>Formatos Aceptados: <br><b>.ac3, .avi, .f4v, .flv, .mkv, .mov, .mp3,<br> .mp4, .mpg, .mpeg, .rmvb, .srt, .swf, .wav, .wmv</b>
    <br><br>
    </center></body></html>

    <?php



    ?>

so i ask some one he told me the exec stop php script and never give me

You can't get the progress directly if you are using exec, because the php script is stopped until ffmpeg closes. (Because exec returns the whole execution output)

You should use popen, for being able to get the output from the process in real time (without reading any file) for parse and show the progressbar

Here is a example for get the output: 

When you get the progress info from ffmpeg, you can use your code for parse it and show your progressbar

this is my popen script

<?php 

$handle = popen ("ffmpeg.exe -i files/fz.mp4 -ab 192k files/vdf.mp3 2>&1 ", 'r');
$handles = (string)$handle;
$line = "";

while (false !== ($char = fgetc($handle)))
{
  if ($char == "")
  {
    // You could now parse the $line for status information.
    echo "$line
";
    $line = "";
  } else {
    $line .= $char;
  }
  ob_flush();
  flush();
}
pclose ($handle);


    //get duration of source
    preg_match("/Duration: (.*?), start:/", $handles, $matches);

    $rawDuration = $matches[1];

    //rawDuration is in 00:00:00.00 format. This converts it to seconds.
    $ar = array_reverse(explode(":", $rawDuration));
    $duration = floatval($ar[0]);
    if (!empty($ar[1])) $duration += intval($ar[1]) * 60;
    if (!empty($ar[2])) $duration += intval($ar[2]) * 60 * 60;

    //get the time in the file that is already encoded
    preg_match_all("/time=(.*?) bitrate/", $handles, $matches);

    $rawTime = array_pop($matches);

    //this is needed if there is more than one match
    if (is_array($rawTime)){$rawTime = array_pop($rawTime);}

    //rawTime is in 00:00:00.00 format. This converts it to seconds.
    $ar = array_reverse(explode(":", $rawTime));
    $time = floatval($ar[0]);
    if (!empty($ar[1])) $time += intval($ar[1]) * 60;
    if (!empty($ar[2])) $time += intval($ar[2]) * 60 * 60;

    //calculate the progress
    $progress = round(($time/$duration) * 100);




    echo '<BR><BR>¡Su video fue convertido correctamente! <BR><BR>Link al archivo:';


    echo "Duration: " . $duration . "<br>";
    echo "Current Time: " . $time . "<br>";
    echo "Progress: " . $progress . "%" . "<br>";

//////////////////////////////////////my coed //////////////////////////////////////////////

?>

so i dont under stand what is good for ffmpeg progressbAR

is exec or popen

so please give me hints for ffmpeg real time progressbar

what is good for progressbar

is html5 progress bar

or javascript progress bar

</div>
  • 写回答

1条回答 默认 最新

  • doudi2005 2013-10-03 14:17
    关注

    My approach was something like this

    $sCmd = "ffmpeg -i infile.mp4 ... -report outfile.mp4 > /var/log/ffmpeg.log";
    $proc = popen($sCmd." 2>&1", "r");
    $read = fread($proc, 2096);
    pclose($proc);
    

    Here is little bit modified code from one of my older projects. I hope it will give You some inspiration:

    <?php
    //get so far encoded time
    public function getEncodedTime(){
    
        $FFMPEGLog = file_get_contents('ffmpeg.log');
        $times     = explode('time=', $FFMPEGLog);
        $ctime     = count($times)-1;
        $timed     = explode(' bitrate=', $times[$ctime]);
        //print_r($timed);
        $nEncTime  = $timed[0];
        list($h, $m, $s) = explode(":", $nEncTime);
        $s = ceil($s); // 21.40 seconds => 22 seconds
        $nEncTime = hms2sec($h, $m, $s);
    
        return $nEncTime;
    
    }
    
    //covert H:i:s time to seconds
    public function hms2sec ($h, $m, $s) {
    
        //list($h, $m, $s) = explode (":", $hms);
        $seconds = 0;
        $seconds += (intval((string)$h) * 3600);
        $seconds += (intval((string)$m) * 60);
        $seconds += (intval((string)$s));
        return $seconds;
    
    }
    
    
    //get total length of file
    public function getTotalTime()
    {
        $play_time_sec = 0;
    
        $lines = file('ffmpeg.log');
        foreach ($lines as $line_num => $line) {
            if(strpos($line, 'Duration') !== false) {
                $line = explode("Duration: ", $line);
                $line = explode(",", $line[1]);
                $line = explode(":", $line[0]);
    
                $play_time_sec = 0;
                $play_time_sec += intval((string)$line[0]) * 60 * 60; // hour
                $play_time_sec += intval((string)$line[1]) * 60; // minute
                $play_time_sec += intval((string)round($line[2])); // second
                break;
            }
        }
    
        return $play_time_sec;
    }
    
    
    //get percents completed:
    public function getPercentsComplete()
    {
    
        $sFileContents = file_get_contents('ffmpeg.log');
        if(stripos($sFileContents, 'No more inputs to read from, finishing') !== false) {
            return 100;
        }
    
        $nTotalTime = getTotalTime();
        $nEncodedTime = getEncodedTime();
    
        if($nEncodedTime <= 0)
            return 0;
    
        if($nEncodedTime >= $nTotalTime)
            return 100;
    
        $nPercentsComplete = round(($nEncodedTime/$nTotalTime)*100);
    
        return $nPercentsComplete;
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器