2

わかりました、私は数日間この問題と戦ってきました。ローカルの Windows マシンでは正常に動作しますが、CentOS サーバーでは動作しないようです。私のスクリプトは、変換中のビデオの長さを取得し、ffmpeg 内で処理された現在の秒数も取得します。ただし、ffmpeg出力の「入力ファイル」を取得してそこで停止するだけです。何らかの理由でffmpegがSTDERRパイプで出力するのが好きなため、両方のパイプ(STDOUT [1]とSTDERR [2])を使用してみました。変。

$filename = "somefilename.tmp";
$descriptor = array(
    0 => array("pipe", "r"),
    1 => array("pipe", "w"),
    2 => array("pipe", "w")
);

$ffmpeg = "ffmpeg -i /var/www/spotloader/videos/flipped/tmp/".$file."_comb.ts -vcodec mpeg2video -acodec pcm_s16le -pix_fmt yuv422p -vtag xdvb -b:v 13000k -r 30000/1001 /var/www/spotloader/videos/flipped/tmp/".$file.".mov";

//open the process
$process = proc_open($ffmpeg, $descriptor, $pipes, NULL, $_ENV);

//if the process opened
if ( is_resource( $process ) == true )
{
    //get process status
    $procStatus = proc_get_status( $process );

    //if its running, let node know
    if ( $procStatus['running'] )
    {
        //nodejs socket, nothing wrong here
        $this->_sendSocket('converting', array('filename' => str_replace('.tmp', '', $file)));
    }

    //while the process is running
    while( $procStatus['running'] === true )
    {
        //there is output in the pipe
        if ( !feof( $pipes[1] ) )
        {
            //get the output
            $data = fgets($pipes[1], 128);
            //match the outputs duration and save it.
            if(preg_match('/Duration:\s([0-9]{2}:[0-9]{2}:[0-9]{2})/', $data, $matches)) 
            {
                static $duration;
                $duration = $this->_convertToSeconds($matches[1]);
            }

            //match the outputs current encoding time
            if(preg_match('/time=([0-9]{2}:[0-9]{2}:[0-9]{2})/', $data, $matches)) 
            {
                //convert to seconds works fine, so it is not included.
                $curTime = $this->_convertToSeconds($matches[1]);
                //nodejs socket, nothing wrong here
                $this->_sendSocket('update', array('percent' => round( ($curTime / $duration) * 100), 'filename' => str_replace('.tmp', '', $file)));
            }
        }

        //update process status
        $procStatus = proc_get_status( $process );
    }

    //nodejs socket, nothing wrong here
    $this->_sendSocket('converted', array('percent' => 100, 'filename' => str_replace('.tmp', '', $file)));
}

上記の PHP コードを使用して受信した FFMPEG 出力

ffmpeg version 1.2.1 Copyright (c) 2000-2013 the FFmpeg developers
built on May 10 2013 15:14:14 with gcc 4.4.6 (GCC) 20120305 (Red Hat 4.4.6-4)
configuration: --prefix=/usr --libdir=/usr/lib64 --shlibdir=/usr/lib64 
--mandir=/usr/share/man --enable-shared --enable-runtime-cpudetect --enable-gpl 
--enable-version3 --enable-postproc --enable-avfilter --enable-pthreads 
--enable-x11grab --enable-vdpau --disable-avisynth --enable-frei0r --enable-libopencv 
--enable-libdc1394 --enable-libgsm --enable-libmp3lame --enable-libnut 
--enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg 
--enable-librtmp --enable-libspeex --enable-libtheora --enable-libvorbis 
--enable-libvpx --enable-libx264 --enable-libxavs --enable-libxvid 
--extra-cflags='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions 
-fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fPIC' 
--disable-stripping
libavutil      52. 18.100 / 52. 18.100
libavcodec     54. 92.100 / 54. 92.100
libavformat    54. 63.104 / 54. 63.104
libavdevice    54.  3.103 / 54.  3.103
libavfilter     3. 42.103 /  3. 42.103
libswscale      2.  2.100 /  2.  2.100
libswresample   0. 17.102 /  0. 17.102
libpostproc    52.  2.100 / 52.  2.100
[mpegts @ 0x243c620] max_analyze_duration 5000000 reached at 5016000 microseconds
Input #0, mpegts, from '/var/www/spotloader/videos/flipped/tmp/Wildlife10.tmp_comb.ts':
Duration: 00:00:02.02, start: 1.389978, bitrate: 227018 kb/s
Program 1
Metadata:
  service_name    : Service01
  service_provider: FFmpeg
Stream #0:0[0x100]: Video: mpeg2video (4:2:2) ([2][0][0][0] / 0x0002), yuv422p, 1920x1080 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc
Stream #0:1[0x101](eng): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, 1 channels (FL+FR), s16p, 128 kb/s

FFMPEG の出力 最後の方の「time=00:00:00」が、リアルタイムでキャプチャする必要があると期待しています。これは、FFMPEG コマンドをシェルで直接実行することによって取得されます。

ffmpeg version 1.2.1 Copyright (c) 2000-2013 the FFmpeg developers
built on May 10 2013 15:14:14 with gcc 4.4.6 (GCC) 20120305 (Red Hat 4.4.6-4)
configuration: --prefix=/usr --libdir=/usr/lib64 --shlibdir=/usr/lib64 
--mandir=/usr/share/man --enable-shared --enable-runtime-cpudetect --enable-gpl 
--enable-version3 --enable-postproc --enable-avfilter --enable-pthreads 
--enable-x11grab --enable-vdpau --disable-avisynth --enable-frei0r --enable-libopencv 
--enable-libdc1394 --enable-libgsm --enable-libmp3lame --enable-libnut 
--enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg 
--enable-librtmp --enable-libspeex --enable-libtheora --enable-libvorbis 
--enable-libvpx --enable-libx264 --enable-libxavs --enable-libxvid 
--extra-cflags='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions 
-fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fPIC' 
--disable-stripping
  libavutil      52. 18.100 / 52. 18.100
  libavcodec     54. 92.100 / 54. 92.100
  libavformat    54. 63.104 / 54. 63.104
  libavdevice    54.  3.103 / 54.  3.103
  libavfilter     3. 42.103 /  3. 42.103
  libswscale      2.  2.100 /  2.  2.100
  libswresample   0. 17.102 /  0. 17.102
  libpostproc    52.  2.100 / 52.  2.100
[mpegts @ 0x10c9620] max_analyze_duration 5000000 reached at 5016000 microseconds
Input #0, mpegts, from '/var/www/spotloader/videos/flipped/tmp/Wildlife10.tmp_comb.ts':
  Duration: 00:00:02.02, start: 1.389978, bitrate: 227018 kb/s
  Program 1
    Metadata:
      service_name    : Service01
      service_provider: FFmpeg
    Stream #0:0[0x100]: Video: mpeg2video (4:2:2) ([2][0][0][0] / 0x0002), yuv422p, 1920x1080 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc
    Stream #0:1[0x101](eng): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, 1 channels (FL+FR), s16p, 128 kb/s
Channel layout 'stereo' with 2 channels does not match specified number of channels 1: ignoring specified channel layout
Output #0, mov, to '/var/www/spotloader/videos/flipped/tmp/Wildlife10.tmp.mov':
  Metadata:
    encoder         : Lavf54.63.104
    Stream #0:0: Video: mpeg2video (xdvb / 0x62766478), yuv422p, 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 13000 kb/s, 30k tbn, 29.97 tbc
    Stream #0:1(eng): Audio: pcm_s16le (sowt / 0x74776F73), 48000 Hz, stereo, s16, 1536 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (mpeg2video -> mpeg2video)
  Stream #0:1 -> #0:1 (mp2 -> pcm_s16le)
Press [q] to stop, [?] for help
Input stream #0:1 frame changed from rate:48000 fmt:s16p ch:1 chl:1 channels (FL+FR) to rate:48000 fmt:s16p ch:2 chl:stereo
Input stream #0:1 frame changed from rate:48000 fmt:s16p ch:2 chl:stereo to rate:48000 fmt:s16p ch:1 chl:mono
Input stream #0:1 frame changed from rate:48000 fmt:s16p ch:1 chl:mono to rate:48000 fmt:s16p ch:2 chl:stereo
Input stream #0:0 frame changed from size:1920x1080 fmt:yuv422p to size:1280x720 fmt:yuv422p0
Input stream #0:1 frame changed from rate:48000 fmt:s16p ch:2 chl:stereo to rate:44100 fmt:s16p ch:2 chl:stereo
frame=  741 fps= 52 q=2.6 size=   43866kB time=00:00:24.65 bitrate=14573.5kbits/s dup=5 drop=0

何か案は?Windows から CentOS への切り替えに伴い、何を変更する必要がありますか?

編集:代わりにpopen を使用してこれを機能させました。また、コードを削減しました。他の誰かが解決策を持っている場合は、先に進んで投稿してください。ありがとう!

4

1 に答える 1

0

何かある

これは、私がしばらく前に取り組んでいたプロジェクトからのものでした。ご希望にかなり近いと思います。少しバグがあり、あまり安全ではないことに注意してください

ffmpeTest.php

<html>
<body>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<h2>Video Uploader</h2>

<form method="post" enctype="multipart/form-data">
  <input type="file" required id="upload"  name="file"/>
  <input type="submit" value="Upload video" id="upload" name="upload"/> 
</form>

<?
ini_set('memory_limit', '1000M');
ini_set('post_max_size', '1000M');
ini_set('upload_max_filesize', '1000M');


if(isset($_POST['upload'])){

$ffmpeg = '/usr/local/Cellar/ffmpeg/1.2.1/bin/ffmpeg';//path to ffmpeg    

$origVideo =  $_FILES['file']['tmp_name'];
$newVideo = "videos/".$_FILES['file']['name'];
move_uploaded_file($origVideo, $newVideo);
$time = time();
  
$command1 = $ffmpeg.' -i "'.$newVideo.'" videos/'.$time.'.flv ';
shell_exec(sprintf('%s > videos/block.txt 2>&1 &', $command1));   
}
?>

<div id="load"></div>
<script>  

$('#thumb').load(function(){
setInterval(function() {
          $('#load').load('http://localhost/Playground/ffmpeLoader.php                           ffmpeLoader.php');
}, 600);
});
</script>
</body>
</html>

ffmpeloader.php

<?
$content = @file_get_contents('videos/block.txt');

if($content){
    //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 "<progress id='p' max='100' value='" . $progress . "'></progress><span> ".$progress."%</span>";

    
}
if($progress == 100){
    

        echo '<p> Done!</p>';
    }
?>
于 2013-09-25T20:31:57.760 に答える