Webカメラに接続してソケットから読み取り、print関数を使用してこのデータを出力する簡単なリレースクリプトを作成しました。データは、境界が既に設定されているMJPGデータです。読み取ったデータを出力するだけです。
問題はPHPはこのデータをバッファリングしているようです。カメラを1 FPSに設定すると、フィードは7〜8秒間フリーズし、すぐに8フレームを表示します。解像度を設定すると巨大なサイズにすると、カメラは毎秒1フレーム程度移動します。その後、バッファリングが行われていると仮定します(巨大なサイズはバッファをすぐにいっぱいにし、小さなサイズはそうではないため)。このバッファリングを無効にします。
コード:
ignore_user_abort(false);
$boundary = "myboundary";
//Set this so PHP doesn't timeout during a long stream
set_time_limit(0);
$socketConn = @fsockopen ("192.168.1.6", 1989, $errno, $errstr, 2);
if (!$socketConn)
exit();
stream_set_timeout($socketConn, 10);
fputs ($socketConn, "GET /mjpeg HTTP/1.0\r\n\r\n");
//Setup Header Information
header("Cache-Control: no-cache");
header("Cache-Control: private");
header("Pragma: no-cache");
header("Content-type: multipart/x-mixed-replace; boundary=$boundary");
@ini_set('implicit_flush', 1);
for ($i = 0; $i < ob_get_level(); $i++)
ob_end_flush();
ob_implicit_flush(1);
stream_set_blocking($f2, false);
//Send data to client
while (connection_status() == CONNECTION_NORMAL)
{
$chunk = fread($socketConn, 128);
print $chunk;
}
fclose($socketConn);
2つのことを行います。
ユーザースペースの出力バッファを無効にします...
グローバルに、どちらかによって...
output_buffering
_をオフにする、またはApache設定で_output_buffering
_を無効にする
_php_flag "output_buffering" Off
_
またはあなたが気にするスクリプトのために、どちらかによって...
ob_end_flush()
の呼び出し、またはob_end_clean()
の呼び出しまた、次のいずれかの方法で、サーバーレベルの出力バッファーを可能な限り無効にします。
ob_implicit_flush()
を呼び出す、またはecho
ステートメントまたは出力を応答本文に追加する他のステートメントの後にflush()
を呼び出す紛らわしいことに、関連する可能性のある2層のバッファリングがあり、PHPドキュメンテーションは2つを区別するのに不十分な仕事をします。
通常、最初の層は、「PHP docs」によって「出力バッファ」として参照されます。このバッファリング層は、HTTP応答のbodyへの出力にのみ影響し、ヘッダー。出力バッファリングは ob_start()
でオンにし、 ob_end_flush()
または ob_end_clean()
。また、php.iniの _output_buffering
_ オプションを使用して、すべてのスクリプトを出力バッファリングで自動的に開始させることもできます。
productionバージョンのphp.ini のこのオプションのデフォルト値は4096です。つまり、出力の最初の4096バイトが出力バッファーにバッファーされ、その時点でフラッシュされ、出力バッファーが行われます。オフにしました。
Php.iniファイルで_output_buffering
_をOff
に設定することにより(または、
_php_flag "output_buffering" Off
_
apacheを使用している場合は、Apache構成で)。または、スクリプトの開始時にob_end_clean()
またはob_end_flush()
を呼び出すことにより、単一のスクリプトに対して無効にすることができます。
出力バッファを超えるのは、PHPマニュアルが「書き込みバッファ」と呼ぶものに加えて、Webサーバーにあるバッファリングシステムです。PHP = _mod_php
_を介したApacheで、_mod_gzip
_を使用していない場合、 flush()
を呼び出してこれらをフラッシュできます。他のバックエンドでは、動作する可能性がありますが、マニュアルは保証を与えるのが難しいです:
説明
_void flush ( void )
_PHPと、バックエンドPHP=が使用しているもの(CGI、Webサーバーなど)の書き込みバッファをフラッシュします。これは、現在の出力をブラウザにはいくつかの注意事項があります。
flush()は、Webサーバーのバッファリングスキームをオーバーライドできない場合があり、ブラウザのクライアント側のバッファリングには影響しません。また、PHPのユーザー空間の出力バッファリングメカニズムにも影響しません。つまり、 ob_flush() とflush()の両方を呼び出して、ob出力バッファーを使用している場合はこれらを呼び出す必要があります。 。
また、いくつかの方法でPHP echo
を呼び出すたびに自動的にflush()
を呼び出します(または、応答に出力をエコーする他の操作を行う)体)。
1つ目は、 ob_implicit_flush()
を呼び出すことです。この関数の名前は一見したところに注意してください。接頭辞_ob_
_が与えられた場合、合理的な人は_ob_start
_、_ob_flush
_などのように「出力バッファ」に影響を与えると予想します。しかし、そうではありません。 ob_implicit_flush()
は、flush()
と同様に、サーバーレベルの出力バッファーに影響を与え、他の_ob_
_関数によって制御される出力バッファーとは一切対話しません。
2つ目は、php.iniで _implicit_flush
_ フラグをOn
に設定して、暗黙的なフラッシュをグローバルに有効にすることです。これは、すべてのスクリプトの開始時にob_implicit_flush()
を呼び出すことと同じです。マニュアルはこれに対して助言をしていることに注意してください"深刻なパフォーマンスへの影響"。これについては、この 接線関連の回答 で説明します。
出力バッファリングを無効にするのではなく、読み取り操作ごとに flush()
を呼び出すだけで済みます。これにより、サーバー構成を台無しにする必要がなくなり、スクリプトの移植性が向上します。
出力バッファリングは階層化することができ、以前のコードが複数のレベルを作成していた場合がありました。これですべてがクリアされます。
while (ob_get_level()) ob_end_clean();
// or ob_end_flush() if you want the contents of the buffer.
PHPで出力バッファリングを無効にするために、.htaccessファイルで以下のコードを提供できます。
php_flag "output_buffering" off
この質問は少し古いことを知っていますが、この質問に戻って、次のようにスクリプトごとに出力バッファリングをオフにすることができます。
if (ob_get_level())
ob_end_clean();
これにより、後続のスクリプトの出力バッファリングがすべてオフになります。