Есть ли способ в PHP предпринять какие-либо действия (например, вставка mysql), если нет новых запросов, скажем, в течение 1 секунды?
Я пытаюсь определить начало и конец последовательности изображений, отправляемых с IP-камеры. Камера отправляет серию изображений при обнаружении движения и останавливает отправку, когда движение останавливается. Я знаю, что камера делает 5 изображений в секунду (каждые 200 мс). Если в течение более 1 с нет новых изображений, я хочу пометить последнее изображение как конец последовательности, вставить запись в mysql, поместить img в соответствующую папку (где все другие imgs из той же последовательности уже написаны) и дать команду app сделать MJPEG клип изображений в этой папке.
Прямо сейчас я могу определить первое изображение в последовательности, используя Альтернативные PHP наличные чтобы сохранить эталонное время из предыдущего запроса, но проблема в том, что следующая последовательность изображений может произойти через несколько часов, и я не могу дать команду PHP закрыть последовательность, если в течение некоторого времени нет запросов, только когда поступает первый запрос новой последовательности.
Мне действительно нужна помощь в этом. Мой PHP отстой почти как мой английский … 🙂
Псевдокод для моей проблемы:
<?php
if(isset($headers["Content-Disposition"]))
{
$frame_time = microtime(true);
if(preg_match('/.*filename=[\'\"]([^\'\"]+)/', $headers["Content-Disposition"], $matches))
{ $filename = $matches[1]; }
else if(preg_match("/.*filename=([^ ]+)/", $headers["Content-Disposition"], $matches))
{ $filename = $matches[1]; }
}
preg_match("/(anpr[1-9])/", $filename, $anprs);
$anpr = $anprs[1];
$apc_key = $anpr."_last_time"; //there are several cameras so I have to distinguish those
$last = apc_fetch($apc_key);
if (($frame_time - $last)>1)
{
$stream = "START"; //New sequence starts
} else {
$stream = "-->"; //Streaming
};
$file = fopen('php://input', 'r');
$temp = fopen("test/".$filename, 'w');
$imageSize = stream_copy_to_stream($file, $temp); //save image file on the file system
fclose($temp);
fclose($file);
apc_store($apc_key, $frame_time); //replace cashed time with this frame time in APC
// here goes mysql stuff...
/* Now... if there is no new requests for 1 second $stream = "END";
calling app with exec() or similar to grab all images in the particular folder and make
MJPEG... if new request arrives cancel timer or whatever and execute script again. */
?>
Не могли бы вы сделать каждый запрос за 1,5 секунды до выхода и в качестве последнего шага проверить, обновлялась ли временная метка последовательности? Если да, выйдите и ничего не делайте. Если нет, сохраните последовательность в mysql. (Это потребует мьютексов, поскольку каждый http-запрос будет проверять и пытаться сохранить последовательность, но только один должен быть разрешен.)
Этот подход позволит объединить вложенный файл / скрипт в код php (единую кодовую базу, проще в обслуживании), но, возможно, он может уменьшить использование памяти (каждый запрос будет оставаться в памяти 1,5 секунды, что является длительным временем для занятого сервера) ,
Другой подход заключается в том, чтобы превратить вложенный файл / сценарий в петлевой запрос на локальном http-сервере, по-видимому, с гораздо меньшим объемом памяти. Каждый кадр запускает запрос на завершение последовательности (аналогично, снова с мьютексами).
Или, может быть, создайте отдельный сервисный вызов, который проверит и сохранит все последовательности, и будет задание cron проверять его каждые несколько секунд. Или попросите каждый кадр пропинговать его, если второй запрос может обнаружить, что служба уже запущена, он может выйти. (разделить состояние в кеше APC)
Изменить: я думаю, что я только что предложил то, что сказано выше.
Что если вы просто сохраните сценарий запущенным в течение 1 секунды после сохранения кадра, чтобы проверить наличие дополнительных кадров? Я предполагаю, что вы можете закрыть соединение до истечения 1 секунды, но у tomlgold2003 и arr1 есть ответ для вас: http://php.net/manual/en/features.connection-handling.php#93441
Я думаю, что это будет работать для вас:
<?php
ob_end_clean();
header("Connection: close\r\n");
header("Content-Encoding: none\r\n");
ignore_user_abort(true); // optional
ob_start();
// Do your stuff to store the frame
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush(); // Strange behaviour, will not work
flush(); // Unless both are called !
ob_end_clean();
// The connection should now be closed
sleep(1);
// Check to see if more frames have been added.
?>
Если ожидается, что ваш сервер испытывает высокую нагрузку, это может не помочь вам, так как при получении 5 кадров в секунду будет 5 скриптов, проверяющих, отправили ли они последний кадр.
Сохраняйте каждый запрос с камеры со всеми его данными и отметкой времени в файле (в сериализованной форме php). В cronjob запускайте (каждые 10 секунд или около того) скрипт, который читает этот файл и находит запросы, которые имеют более одной секунды после них перед следующим запросом. Сохраните данные из таких запросов и удалите все остальные запросы.