PHP - чтение и запись одного и того же файла зависает

Я пытаюсь использовать FFMPEG для работы с видео на сервере, и мне нужно кое-что сделать, это получить ход процесса.

Я немного поискал и нашел это решение, которое говорит написать войти в файл, а затем прочитать и проанализировать его.

Проблема

Что сводит меня с ума, так это то, что я говорю FFMPEG - с exec - (процесс A) записать журнал в файл, но когда я пытаюсь его прочитать - с file_get_contents() - (процесс B ) он не показывает содержимое до тех пор, пока процесс A не завершится (или не будет прерван PHP-скрипт).

Таким образом, когда процесс A завершается или появляется сообщение "Тайм-аут сценария PHP", я могу читать файл столько раз, сколько захочу, обновляя страницу (процесс B) и показывая содержание в то время.

Что я пробовал

Я пытался использовать fopen() для создания файла с параметрами w, w+ и a, используя и не используя fclose(). Я пытался также использовать flock() на тот случай, если процесс B будет быстрее читать, если он знает, что он уже заблокирован и ему не нужно ждать, но тогда FFMPEG не может записать в файл .

Я также искал многопоточность, но я думаю, что должен быть более легкий и простой способ.

Я также использовал контекст CURL и HTTP, как ссылка предлагает, но не повезло.

Я тоже пытался использовать PHP-FFMPEG, но он не поддерживает последнюю версию FFMPEG, поэтому я не могу его использовать.

Когда я сказал раньше "(или прервал PHP-скрипт)", это потому, что я пытался подождать и, когда PHP получил тайм-аут, процесс B работал нормально, и файл все еще обновлялся. эм>

Код

Процесс А (файл A.php)

exec('ffmpeg -y -i input_file.mp4 output_file.avi 2> C:\Full\Path\To\File\log.txt 1>&2');

Процесс B (файл B.php)

$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.

Спасибо всем за ваше время, помощь и терпение!

С наилучшими пожеланиями.


person Unapedra    schedule 01.02.2016    source источник
comment
Убедились ли вы, что Log.txt записывается и заполняется содержимым до завершения процесса A?   -  person maxhb    schedule 01.02.2016
comment
Да! Это становится! На самом деле я могу открыть файл с помощью Блокнота и увидеть текст, и он все равно будет записан, если я закрою его и открою снова.   -  person Unapedra    schedule 01.02.2016
comment
Однако, если он не будет записан, я должен увидеть пустой экран, потому что скрипт уже загрузил весь контент (это так, ничего), но я получаю экран загрузки до тех пор, пока процесс A не завершится или не завершится...   -  person Unapedra    schedule 01.02.2016


Ответы (1)


Вроде сейчас работает. После стольких безуспешных попыток единственное изменение, которое я сделал, кажется, имеет смысл, это написать 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');

Теперь я был бы очень рад, если бы кто-нибудь сказал мне, имеет ли это какой-то смысл или это связано с чем-то еще, чего я не вижу.

Спасибо!

person Unapedra    schedule 02.02.2016
comment
Теперь он снова не работает в некоторых моментах... он работает случайным образом и перестает работать. Я попытаюсь проверить свои конфигурации IIS и PHP, потому что ничего не могу понять. В любом случае, спасибо всем за уделенное время! - person Unapedra; 02.02.2016