首页 文章

在php中从Mjpeg流中获取帧

提问于
浏览
1

我正在尝试从PHP中的Mjpeg流中获取帧 . 我已经尝试过文件读取来读取文件,然后在 Headers 提取框架的基础上 . 但我无法做到 . 我能够看到文件中存在 Headers ,但是当使用exif_read_data查找 Headers 是否存在时,它会显示没有 Headers . 我获取帧的代码是:

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; 
 }
}

我想使用内容长度标头来查找帧长度,然后获取整个帧数据,然后再次循环以查找下一帧 .

1 回答

  • 1

    这里的代码可能对您有所帮助 . 它将从MJPEG流生成JPEG快照 . 您需要更改$ boundary以匹配mjpeg流中找到的边界名称 . 您应该能够修改代码以捕获多个帧 .

    (来自https://gist.github.com/megasaturnv/81279fca49f2f34b42e77815c9bb1eb8 . 代码在https://gist.github.com/megasaturnv/35578337662acd28e0bcd2946a4b069e的img标签中生成图像)

    <?php
    //Megasaturnv 2018-01-12
    $camurl="http://192.168.1.100:8081/";                           // Mjpeg URL
    //$camurl="http://username:password@192.168.1.100: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
    ?>
    

相关问题