web-dev-qa-db-ja.com

PHP NginX-出力バッファリング-ビデオストリーミング

(いくつかのコーディングが含まれているだけでなく、nginx構成にも関係しているため、serverfaultに含めるのが最善だと思います)。

サーバーにいくつかのビデオファイルがあり、ファイルシステム内のフォルダーに保存されています。PHPを使用してビデオファイルを読み取り、NginXをWebサーバーとして使用してユーザーに直接送信しています。

ほとんどのビデオファイルはライブストリーム FFmpegを使用して生成しますが、いくつかの映画もあります。

ライブストリーミングファイル:セグメントに分割されており、phpでm3u8ファイルを読み取り、*。tsファイルを取得し、PHP FFmpegはまだバックグラウンドで実行されています。

ムービーファイル:静的ファイルを1つだけ

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()関数from PHP(簡単に言うと、phpスクリプトがまだ実行されている場合)

今問題:

NginXにはデフォルトでfastcgi_buffering on;があり、クライアントに映画を提供しているときに問題が発生します。ライブストリーミングファイルを提供したい場合、PHPがライブストリーミングファイルのコンテンツを読み取っている間にラグが発生する可能性を減らすためにいくつかのバッファーが必要なので、これは問題ありません。

ただし、映画では、映画全体(2GBであっても)を直接バッファに解析するだけであり、クライアントが応答を受け取ったかどうかを予測することはできません。 phpスクリプトはわずか1秒で終了し、nginxはクライアントにムービーを提供しているため、前に説明した接続ログは1秒以内に終了しました。

fastcgi_buffering off;をオンにすると、すべてが期待どおりに機能しますが、ライブストリーミングサービングにいくつかの遅延が見られました。

最良の方法は、ライブストリームでfastcgi_buffering;およびfastcgi_buffering off;映画の場合。しかし、私はそれをどのように行うのか本当にわかりません。

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;
}
?>
1
user3393046

ここでの問題は、PHPには、ストリーミングに必要なクライアント接続ステータス、バッファなどに関する知識がないことです。

Nginx fastcgi_buffer*オプションは、nginxに対してのみ意味があり、FastCGIインターフェイスを介して送信されるデータのnginx入力バッファーサイズのみを指定します。

FastCGIを介して送られる入力(この場合はストリームデータ)がディレクティブで割り当てられたメモリバッファーよりも大きい場合、nginxは出力をディスク上の一時ファイルに保存します。

PHP側で手動遅延を実装することを試みることができますが、クライアントストリーミングステータスの知識がないため、遅延を正確に実装することはできません。

ビデオがMPEG4でエンコードされている場合は、ngx_http_mp4_moduleを使用することをお勧めします。これは、nginx内に直接ストリーミングビデオを実装します。

0
Tero Kilkanen