PHP NginX - 輸出緩衝 - 影片流
(因為它包含一些編碼,但它也與 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 不知道流式傳輸所需的客戶端連接狀態、緩衝區等。
nginx
fastcgi_buffer*
選項僅對 nginx 有意義,它們僅指定來自 FastCGI 介面的數據的 nginx 輸入緩衝區大小。如果來自 FastCGI 的輸入(在您的情況下為流數據)大於使用指令分配的記憶體緩衝區,則 nginx 將輸出儲存到磁碟上的臨時文件中。
您可以嘗試在 PHP 端實現手動延遲,但由於您不了解客戶端流狀態,因此無法準確實現延遲。
如果您的影片使用 MPEG4 編碼,我建議您使用
ngx_http_mp4_module
. 這直接在 nginx 內部實現了流式影片。