mjpeg广播的瓶颈在哪里?
我像这样用 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 下,情况甚至更糟。
这可能是什么问题?
I'm streaming mjpeg with PHP just like this
<?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++;
}
?>
But if I set a big range of images, for example, from 0 to 300, in indefinite time browser just stop showing.
It's not a specific frame or moment of time, and shows in different browsers, so I think that the causer of it is Apache.
I tried it under Apache 2.2.9 and 2.2.21 and get the same result. Under IIS Express it works even worse.
What problem it can be?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
仅基于给出的信息:
如果帧大小/分辨率较大,每秒 10 帧对于 mjpeg 来说可能有点激进。请记住,这不是 mpeg,其中静态帧的部分不会被发送。这里每次都会发送整个帧/图像。我会首先尝试将帧速率降低到 5 左右。如果问题有所改善,那么您就知道问题出在数据速率上。如果您的代码首先缓冲一些帧然后从缓冲区读取,您也许能够在 10 fps 时改善问题。这样,如果框架显示代码的速度很慢,或者浏览器不会阻塞。我认为您还需要限制代码在放弃并继续下一个图像之前等待图像显示的时间。希望这有帮助。
Based only on the info given:
10 frames per second can be a little aggresive for mjpeg if the frame size/resolution is larger. Remember, this is not mpeg where parts of the frame that are static don't get sent. Here the entire frame/image is sent every time. I would first try lowering the frame rate to around 5. If the problem improves then you know the issue is data rate, somewhere/somehow. You might be able to improve your problem at 10 fps if your code buffered some frames first then read from the buffer. That way if a frame is slow to show up your code or browser don't choke. I think you also need to limit the time your code will wait for an image to show up before giving up and continuing with the next image. Hope this helps.
我不确定这个问题是否仍然有效,但即使不是,也没有直接的答案。
我假设您收到“图像损坏或截断”错误。我的代码几乎相同,并且在使用 usleep(..) 时遇到了同样的问题。
根本原因是 usleep(..) 位置 - 它应该在 print($boundary) 之前调用,而不是之后调用。当您在打印后放置它时,浏览器会认为有问题,因为它期望图像直接位于边界部分之后。在此代码中,紧接在边界之后的是 usleep(..) ,它使流保持 100 毫秒,并且由于该浏览器认为出现了问题。
更改此代码:
更改为:
一切都会正常工作。
I'm not sure if this question is still valid, but even if it's not, there is no direct answer.
I assume you are getting "image corrupt or truncated" error. My code is almost identical and I faced the same issue when using usleep(..).
The root cause is the usleep(..) placement - it should be called before print($boundary), not after. When you place it after print, browser will thing that something is wrong since it expect image directly after boundary section. IN this code immediately after boundary is usleep(..) which hold the stream for 100ms and because of that browser think that something is wrong.
Change this code:
To this one:
And everything will be working fine.