我正在尝试使用 img 标签在 HTML5 中呈现 MJpeg 流。当我运行以下命令时,一切正常,这意味着视频开始播放,直到视频结束:
<img src="http://[some ip]:[port]/mjpg">
我的问题是如何逐帧获取流。对于每一帧,我想得到它,做一些事情(对服务器的 ajax 调用),然后将帧显示为图像。
谢谢。
我正在尝试使用 img 标签在 HTML5 中呈现 MJpeg 流。当我运行以下命令时,一切正常,这意味着视频开始播放,直到视频结束:
<img src="http://[some ip]:[port]/mjpg">
我的问题是如何逐帧获取流。对于每一帧,我想得到它,做一些事情(对服务器的 ajax 调用),然后将帧显示为图像。
谢谢。
您可以在不重复发出 Http 请求的情况下执行此操作。只有一个就足够了。您可以使用fetch api创建一个ReadableStream,访问它的Reader并继续从流中读取。
一旦你让阅读器继续递归地从流中读取块。在字节流中查找 SOI (0xFF 0xD8),它表示标头的结束和 JPEG 帧的开始。标头将包含要读取的 JPEG 的长度(以字节为单位)。从块和任何连续的块中读取那么多字节并将其存储到Uint8Array中。成功读取帧后,将其转换为 blob,从中创建一个 UrlObject 并将其分配给 img 对象的 src 属性。
继续这样做,直到连接关闭。
无耻的插头。这是github上工作示例的链接。
如果相机显示原始 JPEG 图像(不是 .MJPEG 扩展名),您必须手动重新加载它(如果扩展名是 .MJPEG,浏览器将执行所有操作,只需输入正确的 src)。如果您有 .MJPEG 并且想要使用原始 .JPEG,请查看您的相机文档。大多数相机都会公开 .MJPEG 和原始 .JPEG 流(只是在不同的 URL 上)。
不幸的是,您将无法通过 ajax 轻松获取图像,但您可以定期更改图像的 src。
您可以使用Date.getTime()
并将其添加到查询字符串以强制浏览器重新加载图像,并在每次图像加载时重复。
如果您使用 jQuery,代码将如下所示:
相机.html
<!DOCTYPE html>
<html>
<head>
<title>ipCam</title>
</head>
<body>
<h1>ipCam</h1>
<img id="motionjpeg" src="http://user:pass@127.0.0.1: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
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
});
}
请注意,我的示例将在页面加载时播放 MotionJPEG,但不允许播放/暂停/停止功能
如果您的流源无法在另一个地址(http://[some ip]:[port]/frame/XXX)上返回帧,那么您可以在服务器上使用 MJPEG 流解析器。例如,Paparazzo.js解析流并返回单个 jpeg。实际上它只返回最后一帧而不保存前一帧,但可以更改。
只有在没有一些插件和服务器的带有js的浏览器中才能解决问题。