Во-первых, я потратил неделю на поиски и отбор вариантов десятков и десятков ответов для Unix, но это полный провал, мне нужен ответ для Windows , так что это не дубликат вопроса об эквивалентах Unix.
Мы пытаемся создать запланированное задание, которое будет обрабатывать очередь заданий в PHP и поддерживать массив до 10 экземпляров ffmpeg за раз. Я пробовал exec
, shell_exec
и proc_open
, в сочетании с / без start /B
без "полной" удачи.
Я также совершенно уверен, что это связано с настройкой descriptorspec и каналов (с которыми я совершенно не знаком), и вот почему:
За https://trac.ffmpeg.org/wiki/PHP,
Часть, которая говорит "> / dev / null", будет перенаправлять стандартный OUTPUT
(stdout) экземпляра ffmpeg в / dev / null (фактически игнорируя
output) и «2> / dev / null» перенаправят стандартную ОШИБКУ (stderr) на
/ dev / null (эффективно игнорирует любые сообщения журнала ошибок). Эти двое могут
быть объединены в более короткое представление: "> / dev / null 2> & 1". если ты
Например, вы можете? Узнайте больше о перенаправлении ввода / вывода.
Важное примечание следует упомянуть здесь. Командная строка ffmpeg
инструмент использует stderr для вывода сообщений журнала ошибок, а stdout -
зарезервировано для возможного использования каналов (для перенаправления носителя вывода
поток, сгенерированный из ffmpeg в другой инструмент командной строки). Тот
как говорится, если вы запустите свой ffmpeg в фоновом режиме, вы будете наиболее
вероятно, хотите перенаправить stderr в файл журнала, чтобы иметь возможность
проверьте это позже.
Еще одна вещь, о которой нужно позаботиться, это стандартный INPUT (stdin).
Средство командной строки ffmpeg разработано как интерактивная утилита, которая
принимает ввод пользователя (обычно с клавиатуры) и сообщает журнал ошибок
на текущем экране / терминале пользователя. Когда мы запускаем ffmpeg в
фон, мы хотим сказать ffmpeg, что вход не должен быть принят
(и не ждал) от стандартного ввода. Мы можем сказать это ffmpeg, используя ввод / вывод
перенаправление снова
echo "Starting ffmpeg...\n\n";
echo shell_exec("ffmpeg -y -i input.avi output.avi </dev/null >/dev/null 2>/var/log/ffmpeg.log &");
echo "Done.\n";
В этом примере фактически используется shell_exec
, хотя мы хотим использовать proc_open, чтобы мы могли использовать цикл для проверки, завершен ли процесс или нет.
Вот базовый пример цикла из того, что я пробовал. Проблема в выполнении этого состоит в том, что фактическая обработка ffmpeg завершается, но процесс зависает, ожидая чего-то. Когда я использую отладку, выхожу из цикла и завершаю процесс через несколько минут, вывод ffmpeg записывается и сценарий продолжается. (Из командной строки ffmpeg занимает меньше минуты)
$descriptorspec = array(
array('pipe', 'r'),
array('pipe', 'w'),
array('pipe', 'w'),
);
$pipes = null;
$cwd = null;
$env = null;
$process = proc_open('start /B ffmpeg.exe -i input.mov output.mp4 -nostdin', $descriptorspec, $pipes, $cwd, $env);
$status = proc_get_status($process);
while($status['running']) {
sleep (60);
$status = proc_get_status($process);
}
proc_terminate($process);
Кроме того, как указано в ffmpeg Main-options :
Включить взаимодействие на стандартном вводе. По умолчанию, если не стандарт
вход используется как вход. Чтобы явно отключить взаимодействие, вам нужно
указать -nostdin
.
Опция -nostdin
, кажется, указывает на то, что она решает мою проблему, но она не оказывает видимого влияния. Во всех решениях для Unix, которые я обнаружил, по-прежнему требуется некоторая форма этого добавленного Unix: </dev/null
или 2>&1
.
Итак, с помощью этого несколько исчерпывающего пролога кто-то может объяснить, как правильно настроить функцию proc_open
, чтобы удовлетворить взаимодействие ffmpeg.exe
с вводом / выводом? Если есть лучший или более подходящий подход, я с удовольствием это сделаю, но важно иметь возможность циклически проходить через массив процессов, чтобы проверить, завершены ли они, чтобы другие более быстрые процессы могли завершиться в То время.
UPDATE Похоже, что после исчерпывающих НИОКР ввод-вывод не является проблемой для реализации этого (опция - nostdin
, кажется, работает так, как объявлено). Исходная посылка моего проекта состояла в том, чтобы использовать proc_get_status()
, чтобы определить, когда ffmpeg
был закончен. Недостаток этого подхода заключается в том, что очевидно, что он НЕ возвращает фактический PID процесса ffmpeg ... он возвращает parent PID. Итак, когда proc_get_status()
вернуло, что преобразование видео было завершено, оно фактически продолжало работать, а не зависало. Это было еще сложнее при тестировании больших видеофайлов. Чем больше видео, тем дольше оставалось «остаточное» время, которое потребовалось для фактического завершения - не было проблемы с вводом / выводом - проблема была в том, что просмотр родительского PID вместо дочернего PID. Таким образом, без углубления во внутренние системы более низкого уровня с Windows это не представляется возможным напрямую с PHP. Я решил отказаться от этого подхода, но, надеюсь, это открытие сэкономит кому-то еще время и проблемы.