我正在使用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下,它的工作效果更差。
它可能是什么问题?
答案 0 :(得分:1)
仅基于给出的信息:
如果帧大小/分辨率较大,则每秒10帧可能对mjpeg有点积极影响。请记住,这不是mpeg,其中静态帧的部分不会被发送。这里每次都发送整个帧/图像。我会先尝试将帧速率降低到5左右。如果问题有所改善,那么你知道问题是数据速率,某处/某种程度。如果您的代码首先缓冲一些帧然后从缓冲区读取,您可能能够以10 fps改善您的问题。这样,如果框架显示您的代码很慢,或浏览器不会阻塞。我认为您还需要限制代码在放弃并继续下一个图像之前等待图像显示的时间。希望这会有所帮助。答案 1 :(得分:1)
我不确定这个问题是否仍然有效,但即使不是,也没有直接答案。
我假设您遇到“图像损坏或截断”错误。我的代码几乎完全相同,使用usleep(..)时遇到了同样的问题。
根本原因是usleep(..)位置 - 它应该在print($ boundary)之前调用,而不是在之后调用。在打印之后放置的时候,因为在边界部分之后直接期待图像所以浏览器会出现问题。在此代码中,在边界之后立即使用usleep(..)来保存流100ms并且因为该浏览器认为出现了问题。
更改此代码:
print "--$boundary\n";
usleep(100000);
对此:
usleep(100000);
print "--$boundary\n";
一切都会正常。