(Como contém alguns códigos, mas também é sobre a configuração do nginx, acho que seria melhor tê-lo no serverfault).
Eu tenho alguns arquivos de vídeo no meu servidor que estão armazenados em uma pasta dentro do meu sistema de arquivos e estou usando PHP para ler o arquivo de vídeo e enviá-lo diretamente para os usuários usando NginX como WebServer.
A maioria dos arquivos de vídeo são transmissões ao vivo que eu gero usando o FFmpeg, mas também tenho alguns filmes .
Live Streaming Files : Há divisões em segmentos e com o php eu leio o arquivo m3u8, recebo os arquivos * .ts e os estou transmitindo usando o PHP enquanto o FFmpeg ainda está sendo executado em segundo plano .
Arquivos de filme : apenas um arquivo estático
Eu tenho algumas perguntas sobre a configuração do nginx / php.
Minha configuração do NginX é a seguinte:
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;
}
}
Para cada cliente que lê arquivos de vídeos do meu servidor eu registro a conexão e posso prever se ele ainda está online ou não usando o
connection_aborted() function from PHP
(In a few words, if php script is still running)
Agora o problema:
O NginX tem por padrão o fastcgi_buffering on; e isso está me causando um problema quando estou exibindo filmes para os clientes. Quando eu quero servir arquivos Live Streaming isso é bom, pois eu quero alguns buffers para reduzir as chances de ocorrer um atraso enquanto o PHP está lendo o conteúdo dos arquivos de streaming ao vivo.
Mas nos filmes ele apenas analisa o filme inteiro (mesmo que seja 2gb), diretamente para buffers e não pode prever se o cliente recebeu a resposta ou não. O script php termina em apenas um segundo e depois o nginx está servindo o filme para o cliente, então o log de conexão sobre o qual eu falei antes foi encerrado em um segundo.
Se eu ativar fastcgi_buffering , tudo estará funcionando como quero, mas vi alguns atrasos na transmissão ao vivo.
O melhor seria ter fastcgi_buffering ativado em transmissões ao vivo e fastcgi_buffering; em filmes. Mas eu realmente não tenho ideia de como fazer isso.
Eu tentei ob_implicit_flush (true); mas isso não funciona com o NginX, eu acho. Na verdade, eu não posso jogar com qualquer função flush () etc.
O arquivo PHP Streaming usa a seguinte técnica para enviar um arquivo de vídeo para o cliente
<?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;
}
?>