Html 在 html5 中渲染 MJpeg 流

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19346775/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 14:24:42  来源:igfitidea点击:

Rendering MJpeg stream in html5

javascripthtmlmjpeg

提问by Lior Ohana

I'm trying to render MJpeg stream in HTML5 using the img tag. When I'm running the following, everything works great, meaning, the video starts to play until the video ends:

我正在尝试使用 img 标签在 HTML5 中呈现 MJpeg 流。当我运行以下命令时,一切正常,这意味着视频开始播放,直到视频结束:

<img src="http://[some ip]:[port]/mjpg">

My question is how can I get the stream frame by frame. For each frame, I want to get it, do something (ajax call to the server) and then display the frame as an image.

我的问题是如何逐帧获取流。对于每一帧,我想得到它,做一些事情(对服务器的ajax调用),然后将帧显示为图像。

Thanks.

谢谢。

回答by Zorgatone

If the camera exposes raw JPEG images (not .MJPEG extension) you'll have to reaload it manually (if the extension is .MJPEG the browser will do everything, just put the correct src). If you have .MJPEG and want to use the raw .JPEG check your camera documentation. Most cameras expose both the .MJPEG and raw .JPEG streams (just on different URLs).

如果相机显示原始 JPEG 图像(不是 .MJPEG 扩展名),您必须手动重新加载它(如果扩展名是 .MJPEG,浏览器将执行所有操作,只需输入正确的 src)。如果您有 .MJPEG 并且想要使用原始 .JPEG,请检查您的相机文档。大多数相机同时公开 .MJPEG 和原始 .JPEG 流(只是在不同的 URL 上)。

Unfortunately you won't be able to easily get the image through ajax, but you could change the src of the image periodically.

不幸的是,您将无法通过 ajax 轻松获取图像,但您可以定期更改图像的 src。

You can use Date.getTime()and add it to the querystring to force the browser to reload the image, and repeat each time the image loads.

您可以使用Date.getTime()它并将其添加到查询字符串中以强制浏览器重新加载图像,并在每次图像加载时重复。

If you use jQuery the code will look something like this:

如果您使用 jQuery,代码将如下所示:

camera.html

相机.html

<!DOCTYPE html>
<html>

<head>
    <title>ipCam</title>
</head>

<body>
    <h1>ipCam</h1>
    <img id="motionjpeg" src="http://user:[email protected]:8080/" />
    <script src="motionjpeg.js"></script>
    <script>
        //Using jQuery for simplicity

        $(document).ready(function() {
            motionjpeg("#motionjpeg"); // Use the function on the image
        });
    </script>
</body>

</html>

motionjpeg.js

运动jpeg.js

function motionjpeg(id) {
    var image = $(id), src;

    if (!image.length) return;

    src = image.attr("src");
    if (src.indexOf("?") < 0) {
        image.attr("src", src + "?"); // must have querystring
    }

    image.on("load", function() {
        // this cause the load event to be called "recursively"
        this.src = this.src.replace(/\?[^\n]*$/, "?") +
            (new Date()).getTime(); // 'this' refers to the image
    });
}

Notethat my example will play the MotionJPEG on page load, but won't allow play/pause/stop functionalities

请注意,我的示例将在页面加载时播放 MotionJPEG,但不允许播放/暂停/停止功能

回答by arun tom

You can do this without repeatedly making Http requests. Only one will suffice. You can use the fetch apito create a ReadableStream, access it's Readerand keep reading from the stream.

您无需重复发出 Http 请求即可执行此操作。只有一个就足够了。您可以使用fetch api创建一个ReadableStream,访问它的Reader并继续从流中读取。

Once you have the reader keep reading chunks from the stream recursively. Look for the SOI ( 0xFF 0xD8) in the byte stream which signals the end of the header and the beginning of the JPEG frame. The header will contain the length of the JPEG in bytes to be read. Read that many bytes from the chunk and any successive chunks and store it into a Uint8Array. Once you've successfully read the frame convert it into a blob, create a UrlObject out of it and assign it to the src property of your img object.

一旦你让读者继续从流中递归读取块。在字节流中查找 SOI ( 0xFF 0xD8 ),它表示标头的结束和 JPEG 帧的开始。标头将包含要读取的 JPEG 的长度(以字节为单位)。从块和任何连续的块中读取那么多字节并将其存储到Uint8Array 中。成功读取帧并将其转换为 blob 后,从中创建一个 UrlObject 并将其分配给 img 对象的 src 属性。

Keep doing this till the connection is closed.

继续这样做,直到连接关闭。

Shameless plug. Here's a link to a working sample on github.

无耻的插头。这是github上工作示例的链接。

回答by Alex

If you stream source can't return frames on another address (http://[some ip]:[port]/frame/XXX) then you can use MJPEG stream parser on the server. For example, Paparazzo.jsparse stream and return single jpeg. Actually it returns only last frame without saving previous, but it can be changed.

如果您的流源无法在另一个地址 (http://[some ip]:[port]/frame/XXX) 上返回帧,那么您可以在服务器上使用 MJPEG 流解析器。例如,Paparazzo.js解析流并返回单个 jpeg。实际上它只返回最后一帧而不保存前一帧,但它可以改变。

Problem can't be solved only in browser with js without some plugins and server.

问题不能只在浏览器中解决,没有一些插件和服务器。