1

このようにPHPでmjpegをストリーミングしています

<?php
//example /cli/watch.php?i=0&j=200

function get_one_jpeg($i) {
    $path = "img";
    //$f = fopen("$path/$i.jpg", "rb");
    return file_get_contents("$path/$i.jpg");
}
ini_set('display_errors', 1);
# Used to separate multipart
$boundary = "my_mjpeg";

# We start with the standard headers. PHP allows us this much
//header("Connection: close");
header("Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0");
header("Cache-Control: private");
header("Pragma: no-cache");
header("Expires: -1");
header("Content-type: multipart/x-mixed-replace; boundary=$boundary");

# From here out, we no longer expect to be able to use the header() function
print "--$boundary\n";

# Set this so PHP doesn't timeout during a long stream
set_time_limit(0);

# Disable Apache and PHP's compression of output to the client
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);

# Set implicit flush, and flush all current buffers
@ini_set('implicit_flush', 1);
for ($i = 0; $i < ob_get_level(); $i++)
    ob_end_flush();
ob_implicit_flush(1);

# The loop, producing one jpeg frame per iteration
$i = $_GET['i'];
$j = $_GET['j'];

while ($i <= $j) {
    # Per-image header, note the two new-lines
    print "Content-type: image/jpeg\n\n";

    # Your function to get one jpeg image
    print get_one_jpeg($i);

    # The separator
    print "--$boundary\n";

    # Sleeping for 0.1 seconds for 10 frames in second
    usleep(100000);

    $i++;
}
?>

しかし、たとえば 0 から 300 までの大きな範囲の画像を設定すると、無期限にブラウザの表示が停止します。

これは特定のフレームや瞬間ではなく、さまざまなブラウザーで表示されるため、原因は Apache であると考えられます。

Apache 2.2.9 および 2.2.21 で試してみましたが、同じ結果が得られました。IIS Express では、さらに悪化します。

それはどのような問題になる可能性がありますか?

4

2 に答える 2

1

この質問がまだ有効かどうかはわかりませんが、有効でない場合でも、直接的な答えはありません。

「画像が破損または切り捨てられました」というエラーが発生していると思います。私のコードはほとんど同じで、usleep(..)を使用するときに同じ問題に直面しました。

根本的な原因はusleep(..)の配置です。これは、print($ boundary)の後ではなく、前に呼び出す必要があります。印刷後に配置すると、境界セクションの直後の画像を想定しているため、ブラウザは何かがおかしいと思います。このコードでは、境界の直後にusleep(..)があり、これはストリームを100ミリ秒間保持し、そのブラウザーのために何かが間違っていると考えます。

このコードを変更します。

print "--$boundary\n";
usleep(100000);

これに:

usleep(100000);
print "--$boundary\n";

そして、すべてが正常に機能します。

于 2012-06-21T16:53:45.860 に答える
1

与えられた情報のみに基づく:

フレームサイズ/解像度が大きい場合、1秒あたり10フレームはmjpegにとって少し攻撃的です。これは、フレームの静的な部分が送信されない mpeg ではないことに注意してください。ここでは、フレーム/画像全体が毎回送信されます。最初にフレーム レートを 5 程度に下げてみます。問題が改善された場合は、データ レートに問題があることがわかります。コードが最初にいくつかのフレームをバッファリングしてからバッファから読み取る場合、10 fps で問題を改善できる可能性があります。そうすれば、フレームの表示が遅い場合でも、コードやブラウザが詰まることはありません。あきらめて次の画像に進む前に、画像が表示されるまでコードが待機する時間を制限する必要があると思います。お役に立てれば。

于 2011-11-15T19:12:23.630 に答える