Выбрать кадры из потока Mjpeg в Stack Overflow

Я пытаюсь получить кадры из потока Mjpeg в PHP. Я пытался прочитать файл, чтобы прочитать файл, а затем на основе заголовков выборки кадров. Но я не могу этого сделать.
Я могу видеть заголовки, присутствующие в файле, но при использовании exif_read_data, чтобы найти, существуют ли заголовки, он показывает, что заголовков нет.
Мой код для получения кадра:

function grab_frame($url) {
$f = fopen($url, 'r'); //6,168
if($f) {
$r = null;
while(substr_count($r, "Content-Length")!= 5){
$r.= fread($f,40000000);
$start = strpos($img,'F1');
$end   = strpos($img,'F2');
$frame  = substr($r, $start, $end);
}
fclose($f);
return $frame;
}
}

Я хочу использовать заголовок content-length, чтобы найти длину кадра, а затем извлечь данные всего кадра, а затем повторить цикл, чтобы найти следующий кадр.

1

Решение

Код здесь может помочь вам. Он создаст снимок JPEG из потока MJPEG. Вам нужно будет изменить $ border для соответствия имени границы, найденному в вашем потоке mjpeg. Вы должны быть в состоянии изменить код для захвата нескольких кадров.

(от https://gist.github.com/megasaturnv/81279fca49f2f34b42e77815c9bb1eb8 . код генерирует изображение в теге img в https://gist.github.com/megasaturnv/35578337662acd28e0bcd2946a4b069e)

<?php
//Megasaturnv 2018-01-12
$camurl="http://192.168.1.100:8081/";                           // Mjpeg URL
//$camurl="http://username:[email protected]:8081/"        // HTTP Auth mjpeg URL (optional)
$boundary="--BoundaryString";                                   // $boundary = The boundary string between jpegs in an mjpeg stream
//NOTE: $boundary changes between mjpeg stream providers. For example, https://github.com/Motion-Project/motion uses '--BoundaryString'. https://github.com/ZoneMinder/ZoneMinder uses '--ZoneMinderFrame'. To find out $boundary for your stream you will need to save 1 or more frames of the mjpeg and open it with a text editor. --<boundary string> should be visible on the first line
$f = fopen($camurl, "r");                                       // Open mjpeg url as $f in readonly mode
$r = "";                                                        // Set $r to blank variable

if($f) {
while (substr_count($r,"Content-Length") < 2)               // While the number of times "Content-Length" appears in $r is less than 2
$r.=fread($f, 16384);                                   // Append 16384 bytes of $f to $r

$start = strpos("$r", $boundary);                           // $start is set to the position of the first occurrence of '$boundary' in $r
$end = strpos("$r", $boundary, $start + strlen($boundary)); // $end is essentially set to the position of the second occurrence of '$boundary' in $r. I use $start + strlen($boundary) to offset the start position and skip the first occurrence
$boundaryAndFrame = substr("$r", $start, $end - $start);    // $boundaryAndframe is set to the string in $r starting at position $start and with a length of ($end - $start)

$pattern="/(Content-Length:\s*\d*\r\n\r\n)([\s\S]*)/";      // Use regex to search for '(Content-Length:       90777\r\n\r\n)(<jpeg image data>)
preg_match_all($pattern, $boundaryAndFrame, $matches);      // Search for regex matches in $boundaryAndFrame
$frame = $matches[2][0];                                    // $frame is set to the second regex character group (in this case, <jpeg image data>)
header("Content-type: image/jpeg");                         // Set header for jpeg image
echo $frame;                                                // Echo the jpeg image data
} else {
echo "Error, cannot open URL";                              // Error message if $camurl cannot be opened
}

fclose($f);                                                     // Close the url
?>
1

Другие решения

Мое решение для анализа кадра

function readPixel($url, $x, $y, $callback)
{
$loop = 0;
//Megasaturnv 2018-01-12
// Mjpeg URL
$camurl = $url;
//$camurl="http://username:[email protected]:8081/"        // HTTP Auth mjpeg URL (optional)
$boundary="--BoundaryString";                                   // $boundary = The boundary string between jpegs in an mjpeg stream
//NOTE: $boundary changes between mjpeg stream providers. For example, https://github.com/Motion-Project/motion uses '--BoundaryString'. https://github.com/ZoneMinder/ZoneMinder uses '--ZoneMinderFrame'. To find out $boundary for your stream you will need to save 1 or more frames of the mjpeg and open it with a text editor. --<boundary string> should be visible on the first line
$f = fopen($camurl, "r");                                       // Open mjpeg url as $f in readonly mode
$r = "";                                                        // Set $r to blank variable

if($f) {
while (true){
$r.=fread($f, 50000);

$startsearch = strpos($r, "Content-Length: ");
if($startsearch!==false){
$r = substr($r, $startsearch+16);

$index=0;
$length = "";
while(true){
$char = substr($r, $index, 1);
$index++;

if(is_numeric($char)){
$length.= $char;
}else{
break;
}
}

$r = substr($r, strlen($length)+4);
$totalbytes = $length-0;
$havebytes=strlen($r);
$remain = $totalbytes-$havebytes;

//echo "Length:$length\n";
//echo "Stream:$r\n";
//echo "HaveBytes $havebytes totalbytes: $totalbytes, Remain: $remain\n";

while($havebytes < $totalbytes){
$r .=fread($f, $totalbytes-$havebytes);
$havebytes = strlen($r);
}

//save/debug image
//file_put_contents("test.jpg", $r);

$im = imagecreatefromstring($r);

//test if image is valid
//$valid = ($im != FALSE);
//echo ($valid?"VALID":"INVALID")."\n";
//echo imagesx($im).'x'.imagesy($im) ."\n";

$rgb = imagecolorat ($im, $x, $y);

$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;

imagedestroy($im);
$loop++;

if($callback($r,$g,$b, $loop)){
echo "TEST colors: $r $g $b\n";
}else{
fclose($f);
return true;
}

$r="";
}
}
} else {
echo "Error, cannot open URL"; // Error message if $camurl cannot be opened
}

fclose($f); // Close the url
}
0

По вопросам рекламы [email protected]