Я пытаюсь использовать FFMPEG, чтобы сделать некоторые работы с видео на сервере, и что мне нужно сделать, это получить прогресс процесса.
Я немного искал и нашел это решение который говорит записать журнал в файл, а затем прочитать и проанализировать его.
Что сводит меня с ума, так это то, что я говорю FFMPEG — с exec
— (процесс А) записать журнал в файл, но когда я пытаюсь его прочитать — с file_get_contents()
— (процесс Б) не показывает содержимое до процесс А закончен (или прервал сценарий PHP).
Так когда процесс А заканчивается или он говорит «Тайм-аут сценария PHP», тогда я могу читать файл сколько угодно раз, обновляя страницу (процесс Б) и показывая содержимое в то время.
Я пытался использовать fopen()
создать файл с w
, w+
а также a
параметры, используя — и без использования — fclose()
, Я пытался использовать также flock()
на всякий случай становится быстрее читать процесс Б если он знает, что он уже заблокирован и не должен ждать, но тогда FFMPEG не сможет записать в файл.
Я искал многопоточность тоже, но я думаю, что должно быть проще и проще.
Я использовал также контекст CURL и HTTP, как эта ссылка предлагает, но не повезло.
Я тоже пытался использовать PHP-FFMPEG, но он не поддерживает последнюю версию FFMPEG, поэтому я не могу его использовать.
Когда я говорил раньше «(или прервал сценарий PHP)», это потому, что я пытался ждать и, когда PHP получил тайм-аут, процесс Б работал хорошо, и файл все еще обновлялся.
exec('ffmpeg -y -i input_file.mp4 output_file.avi 2> C:\Full\Path\To\File\log.txt 1>&2');
$content = file_get_contents($file);
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 "Duration: " . $duration . "<br>";
echo "Current Time: " . $time . "<br>";
echo "Progress: " . $progress . "%";
}
Я просто открываю fileA.php
на вкладке Chrome и через несколько секунд я открываю fileB.php
на другой вкладке Chrome (и остается погрузка).
Мне нужно иметь возможность загрузить файл и показать информацию, которую я хочу показать во время записи файла ( exec
а также FFMPEG
или другие сценарии PHP), поэтому я могу обновлять процент выполнения с помощью некоторых вызовов AJAX.
На данный момент я использую PHP 5.4 на IIS 7.5 с Windows 7 Professional.
Спасибо всем за потраченное время, помощь и терпение!
С наилучшими пожеланиями.
Кажется, сейчас работает. После стольких попыток без работы единственное изменение, которое я сделал, кажется, имеет смысл писать session_write_close()
до вызывая exec
команда. Итак, следуя моему примеру, это будет что-то вроде:
session_write_close();
exec('ffmpeg -y -i input_file.mp4 output_file.avi 2> C:\Full\Path\To\File\log.txt 1>&2');
Теперь, я был бы очень рад, если бы кто-то сказал мне, имеет ли это какой-то смысл или это имеет отношение к чему-то еще, что я не вижу.
Спасибо!
Других решений пока нет …