(Поскольку он содержит некоторую кодировку, но также касается конфигурации nginx, я думаю, что было бы лучше иметь ее в serverfault).
У меня есть несколько видеофайлов на моем сервере, которые хранятся в папке внутри моей файловой системы, и я использую PHP для чтения видеофайла и отправки его напрямую пользователям, использующим NginX в качестве WebServer.
Большинство видеофайлов прямые трансляции который я генерирую с помощью FFmpeg, но у меня есть фильмы также.
Файлы прямой трансляции: Они разделены на сегменты, и с помощью php я читаю файл m3u8, получаю файлы * .ts и транслирую их с помощью PHP, пока FFmpeg все еще работает в фоновом режиме.
Файлы фильмов: Всего один статический файл
У меня есть вопросы по конфигурации nginx / php.
Моя конфигурация NginX следующая:
server {
listen 80;
index index.php index.html index.htm;
root /var/www;
server_tokens off;
chunked_transfer_encoding off;
location ~ \.php$ {
try_files $uri =404;
fastcgi_index index.php;
fastcgi_pass unix:/var/run/php5-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}
}
Для каждого клиента, который читает видеофайлы с моего сервера, я регистрирую соединение и могу предсказать, находится ли он еще в сети или не использует
Функция connection_aborted () из PHP (в двух словах, если скрипт php все еще запущен)
Теперь проблема:
NginX по умолчанию fastcgi_buffering on; и это вызывает у меня проблемы, когда я предлагаю фильмы клиентам. Когда я хочу обслуживать файлы потоковой передачи в реальном времени, это нормально, так как я хочу, чтобы некоторые буферы уменьшали вероятность возникновения задержки, когда PHP считывает содержимое файлов потоковой передачи.
Но в фильмах он просто анализирует весь фильм (даже если он составляет 2 ГБ) напрямую в буферы и не может предсказать, получил ли клиент ответ или нет. Скрипт php завершается всего за секунду, а затем nginx передает фильм клиенту, поэтому журнал подключения, о котором я говорил ранее, был завершен в течение одной секунды.
Если я повернусь fastcgi_buffering off; все работает так, как я хочу, но я заметил некоторые задержки в Live Streaming Serving.
Лучше всего было бы иметь fastcgi_buffering on; в прямых трансляциях и fastcgi_buffering off; в фильмах. Но я понятия не имею, как это сделать.
Я попытался ob_implicit_flush (правда); но я думаю, что это не работает ни с NginX. На самом деле я не могу играть ни с какими промывать() функция и т. д.
Потоковый файл PHP использует следующую технику для отправки видеофайла клиенту.
<?php
# $video_file can be either a live stream or movie file.
$bytes = 0;
$stream = fopen( $video_file, "rb" );
while ( ! feof( $stream ) && ClientConnected() )
{
$response = stream_get_line( $stream, 8192 );
$bytes += strlen( $response );
echo $response;
}
fclose( $stream );
/*
$bytes have been sent
In movie files the bytes directly goes to the filesize of movie file if fastcgi_buffering is on.
*/
function ClientConnected()
{
if ( connection_status() != CONNECTION_NORMAL || connection_aborted() )
{
return false;
}
return true;
}
?>
Проблема здесь в том, что PHP не знает о состоянии подключения клиента, буферах и т. Д., Которые необходимы для потоковой передачи.
Nginx fastcgi_buffer*
параметры имеют смысл только для nginx, они указывают только размеры входного буфера nginx для данных, поступающих через интерфейс FastCGI.
Если вход (данные потока в вашем случае), поступающий через FastCGI, больше, чем буферы памяти, выделенные с помощью директив, то nginx сохраняет вывод во временный файл на диске.
Вы можете попытаться реализовать задержки вручную на стороне PHP, но, поскольку вы не знаете о статусе потоковой передачи клиента, вы не можете точно реализовать задержки.
Если ваши видео кодируются с помощью MPEG4, я рекомендую вам использовать ngx_http_mp4_module
. Это реализует потоковую передачу видео прямо внутри nginx.