Довелось однажды писать скрипт, который в процессе своей работы пробегал по списку видео файлов и для каждого запускал ffmpeg с ключом, позволяющим получить информацию о файле. Мне собственно требовалось время воспроизведения.
Все бы хорошо, да вот на одном файле ffmpeg подвисал и не думал завершаться, а в момент завершения отваливался и php скрипт без видимых на то причин.
После долгих поисков решения данной проблемы, был найден код, который после небольшой переделки я готов представить на ваш суд :)
Основная проблема заключалась в том, что не было возможности ограничить время выполнения ffmpeg.
Помог следующий код:
Код довольно простой и понятный, по этому наверное нет смысла писать к нему описание.
Пример использования
PsExecute('ffmpeg -i video_file.flv', 5, 1, '/tmp/1.txt');
Если за 5 секунд ffmpeg не завершится, то он будет завершен автоматически.
Скачать в архиве
Все бы хорошо, да вот на одном файле ffmpeg подвисал и не думал завершаться, а в момент завершения отваливался и php скрипт без видимых на то причин.
После долгих поисков решения данной проблемы, был найден код, который после небольшой переделки я готов представить на ваш суд :)
Основная проблема заключалась в том, что не было возможности ограничить время выполнения ffmpeg.
Помог следующий код:
<?php
/**
* Run process with timeout
* @param str $command
* @param int $timeout - sec
* @param int $sleep
* @param str $file_out_put - if default value, then return true else return out of process
* @return bool or str
*/
function PsExecute($command, $timeout = 10, $sleep = 1, $file_out_put = '/dev/null') {
$pid = PsExec($command, $file_out_put);
if( $pid === false ) {
return false;
}
$cur = 0;
// пока не истекло время отведенное на выполнение скрипта продолжаем ждать
while( $cur < $timeout ) {
sleep($sleep);
$cur += $sleep;
if( !PsExists($pid) ) {
// скрипт завершил своё выполнение, можно посмотреть его результат или просто вернуть true
if ($file_out_put != '/dev/null') {
return file_get_contents($file_out_put);
} else {
return true;
}
}
}
// не дождались пока звершиться скрипт, по этому автоматически убиваем его
PsKill($pid);
return false;
}
/**
* Run process in background with out buffer to file
* @param str $commandJob
* @param str $file_out_put
* @return int or false
*/
function PsExec($commandJob, $file_out_put) {
$command = $commandJob.' > '.$file_out_put.' 2>&1 & echo $!';
exec($command ,$op);
$pid = (int)$op[0];
if($pid!="") return $pid;
return false;
}
/**
* If process exists then return true else return false
* @param int $pid
* @return bool
*/
function PsExists($pid) {
exec("ps ax | grep $pid 2>&1", $output);
while( list(,$row) = each($output) ) {
$row_array = explode(" ", $row);
$check_pid = $row_array[0];
if($pid == $check_pid) {
return true;
}
}
return false;
}
/**
* Kill process
* @param int $pid
*/
function PsKill($pid) {
exec("kill -9 $pid", $output);
}
?>
* This source code was highlighted with Source Code Highlighter.
Код довольно простой и понятный, по этому наверное нет смысла писать к нему описание.
Пример использования
PsExecute('ffmpeg -i video_file.flv', 5, 1, '/tmp/1.txt');
Если за 5 секунд ffmpeg не завершится, то он будет завершен автоматически.
Скачать в архиве