[英]Dynamically Preloading/Displaying Webcam Snapshots on a Web Page Using AJAX
我有一个IP摄像机,可将实时视频流式传输到我的网站。 问题是,它由ActiveX控件提供动力。 更糟糕的是,该控件是未签名的。 为了给使用IE以外的浏览器或(理所当然)不愿意更改其安全设置的人们提供更安全的替代方法,我使用了内置有640x480实时JPEG图像的快照脚本内置的摄像机。 计划是使用Javascript每隔500毫秒更新屏幕上实时显示的图像,而不必重新加载整个页面。
我尝试使用Image()对象预加载图像并在onload触发时更新图像元素的SRC属性:
function updateCam() {
var url = "../snapshot.cgi?t=" + new Date().getTime();
img = new Image();
img.onload = function() {
$("#livePhoto").attr("src", url);
camTimer = setTimeout(updateCam, 500);
}
img.src = url;
}
这可以正常工作,但是很难确定何时禁用了相机,这是我需要做的,以使其正常降级。 在这种情况下,内部快照脚本被设置为返回HTTP状态代码204(无内容),当然,我没有办法使用Image对象检测到该错误。 此外,onload事件并非100%可靠。
因此,我正在使用jQuery(1.2.6版) ajax
函数对URL进行GET请求,并在complete
回调中评估状态代码并相应地设置URL:
function updateCam() {
var url = "../snapshot.cgi?t=" + new Date().getTime();
$.ajax({
type: "GET",
url: url,
timeout: 2000,
complete: function(xhr) {
try {
var src = (xhr.status == 200) ? url : '../i/cam-oos.jpg';
$("#livePhoto").attr("src", src);
}
catch(e) {
JoshError.log(e);
}
camTimer = setTimeout(updateCam, 500);
}
});
}
这很漂亮。 但仅在IE中! 这是我想回答的问题:为什么在Firefox或Chrome中无法使用? complete
事件甚至不会在Firefox中触发。 它确实可以在Chrome中启动,但是设置SRC很少真正加载请求的图像(通常不显示任何内容)。
发布第二个答案,因为第一个答案确实不正确。 我无法测试此解决方案(因为我无权访问您的网络摄像头脚本),但我建议您尝试清理来自摄像头的响应-由于您显然无法处理原始图像数据,请尝试添加dataFilter设置如下:
function updateCam() {
var url = "../snapshopt.cgi?t=" + new Date().getTime();
$.ajax({
type: "GET",
url: url,
timeout: 2000,
dataFilter : function(data, type) {
return '<div></div>' //so it returns something...
},
complete: function(xhr) {
try {
var src = (xhr.status == 200) ? url : '../i/cam-oos.jpg';
$("#live").attr("src", src);
}
catch(e) {
JoshError.log(e);
}
camTimer = setTimeout(updateCam, 500);
}
});
}
就像我说的那样,我一直无法测试-但是它可能允许jquery使用状态代码而不会像疯了一样崩溃。
img.onerror = function(){
alert('offline');
}
好吧,我最终在非IE浏览器中使用了数据URI方案 (Eric Pascarello的技巧)。 我编写了一个HTTP处理程序(在VB.NET中)以代理IP摄像机,并以base-64编码图像:
Imports Common
Imports System.IO
Imports System.Net
Public Class LiveCam
Implements IHttpHandler
Private ReadOnly URL As String = "http://12.34.56.78/snapshot.cgi"
Private ReadOnly FAIL As String = Common.MapPath("~/i/cam-oos.jpg")
Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
Dim Data As Byte()
With context.Response
.ContentEncoding = Encoding.UTF8
.ContentType = "text/plain"
.Write("data:image/png;base64,")
Try
Using Client As New WebClient()
Data = Client.DownloadData(URL)
End Using
Catch ex As WebException
Data = File.ReadAllBytes(FAIL)
End Try
.Write(Convert.ToBase64String(Data))
End With
End Sub
End Class
然后,我只是进行了一些非IE的检测(使用经典document.all检查),以便调用正确的URL /设置正确的SRC:
function updateCam() {
var url = (document.all) ? "../snapshot.cgi?t=" : "../cam.axd?t=";
url += new Date().getTime();
$.ajax({
type: "GET",
url: url,
timeout: 2000,
complete: function(xhr) {
try {
var src;
if(document.all)
src = (xhr.status == 200) ? url : '../i/cam-oos.jpg';
else
src = xhr.responseText;
$("#livePhoto").attr("src", src);
}
catch(e) {
JoshError.log(e);
}
camTimer = setTimeout(updateCam, 500);
}
});
}
不幸的是我不得不求助于这种解决方法。 我讨厌浏览器检测代码,并且讨厌服务器上的额外负载。 代理不仅会迫使我浪费更多的带宽,而且由于代理固有的缺陷以及基于base-64编码图像所需的时间,它也无法高效运行。 此外,它没有设置为像IE 一样优雅地降级。 尽管我可以重新编写代理以使用HttpWebRequest并返回正确的状态代码,等等。我只是想找到最简单的方法,因为我讨厌处理此问题!
谢谢大家!
我相信jquery会尝试解释服务器的响应。 我相信某些浏览器更能容忍响应解释,因此,限制性更强的浏览器将失败,因为无法将图像视为HTML!
解决方案是使用HEAD请求类型而不是GET(类型:“ HEAD”)。 这样,您仍然可以获取状态响应,而无需获取图像本身。 因此,响应将为空(并且不应使您烦恼)。 同样,响应应该更快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.