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

仅基于给出的信息:

如果帧大小/分辨率较大,每秒 10 帧对于 mjpeg 可能有点激进。请记住,这不是 mpeg,其中静态帧的部分不会被发送。每次都发送整个帧/图像。我会首先尝试将帧速率降低到 5 左右。如果问题有所改善,那么您就知道问题出在数据速率上,某处/不知何故。如果您的代码先缓冲一些帧然后从缓冲区中读取,您可能能够以 10 fps 的速度改善您的问题。这样,如果框架显示您的代码或浏览器的速度很慢,就不会窒息。我认为您还需要限制代码在放弃并继续下一个图像之前等待图像出现的时间。希望这可以帮助。

于 2011-11-15T19:12:23.630 回答