Nginx

PHP NginX - 輸出緩衝 - 影片流

  • July 15, 2014

(因為它包含一些編碼,但它也與 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;
   }
}

對於從我的伺服器讀取影片文件的每個客戶端,我都會記錄連接,我可以預測他是否仍然線上或不使用

PHP 的 connection_aborted() 函式(簡而言之,如果 php 腳本仍在執行)

現在的問題:

NginX 預設開啟***fastcgi_buffering;***當我向客戶提供電影時,這給我帶來了問題。當我想提供實時流文件時,這很好,因為我想要一些緩衝區來減少在 PHP 讀取實時流文件的內容時發生延遲的機會。

但是在電影中它只是解析整個電影(即使它是 2gb),直接到緩衝區並且無法預測客戶端是否得到響應。php 腳本在一秒鐘內結束,然後 nginx 將電影提供給客戶端,因此我之前談到的連接日誌在一秒鐘內結束。

如果我關閉***fastcgi_buffering;***一切都按我的意願工作,但我看到直播服務有一些滯後。

最好的辦法是***開啟 fastcgi_buffering;在實時流和fastcgi_buffering 中;***在電影中。但我真的不知道該怎麼做。

我試過ob_implicit_flush( true ); 但我認為這不適用於 NginX。事實上,我不能玩任何***flush()***函式等。

流式 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 不知道流式傳輸所需的客戶端連接狀態、緩衝區等。

nginxfastcgi_buffer*選項僅對 nginx 有意義,它們僅指定來自 FastCGI 介面的數據的 nginx 輸入緩衝區大小。

如果來自 FastCGI 的輸入(在您的情況下為流數據)大於使用指令分配的記憶體緩衝區,則 nginx 將輸出儲存到磁碟上的臨時文件中。

您可以嘗試在 PHP 端實現手動延遲,但由於您不了解客戶端流狀態,因此無法準確實現延遲。

如果您的影片使用 MPEG4 編碼,我建議您使用ngx_http_mp4_module. 這直接在 nginx 內部實現了流式影片。

引用自:https://serverfault.com/questions/612622