2009-05-29 4 views
0

Ich habe eine IP-Kamera, die Live-Video auf eine meiner Websites streamen. Problem ist, dass es von einem ActiveX-Steuerelement angetrieben wird. Schlimmer noch, dieses Steuerelement ist nicht signiert. Um eine sicherere Alternative zu den Leuten zu bieten, die andere Browser als IE benutzen oder (rechtmäßig) ihre Sicherheitseinstellungen nicht ändern wollen, klicke ich auf die Kameras, die im Snap-Shot-Skript erstellt wurden und 640x480 JPEG Live-Bilder liefern. Der Plan war, das Bild alle ~ 500ms live auf dem Bildschirm mit Javascript zu aktualisieren, ohne die gesamte Seite neu laden zu müssen.Dynamisch Vorladen/Anzeigen von Webcam-Schnappschüssen auf einer Webseite mit AJAX

Ich versuchte, das Bild() Objekt mit dem Bild vorab laden und das SRC-Attribut des Bildelementes zu aktualisieren, wenn sie abgefeuert onload:

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

Diese anständig gearbeitet, aber es war schwierig, wenn die bestimmen Die Kamera war deaktiviert worden, was ich tun musste, um mich elegant zu verschlechtern. Das interne Snapshot-Skript wurde so eingerichtet, dass es unter diesen Umständen einen HTTP-Statuscode von 204 (Kein Inhalt) zurückgibt, und natürlich kann ich das Image-Objekt nicht erkennen. Darüber hinaus war das Onload-Ereignis nicht 100% zuverlässig.

Daher verwende ich die jQuery (Version 1.2.6) ajax Funktion eine GET-Anforderung auf der URL zu tun, und auf dem complete Rückruf ich den Statuscode auswerten und die URL entsprechend eingestellt:

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

Und das funktioniert wunderbar. Aber nur in IE! Das ist die Frage, die ich gerne beantwortet hätte: Warum funktioniert das nicht in Firefox oder Chrome? Das Ereignis complete wird nicht einmal in Firefox ausgelöst. Es wird in Chrome ausgelöst, aber nur sehr selten lädt das SRC das angeforderte Bild (normalerweise zeigt es nichts an).

+0

Wird der Callback überhaupt nicht aufgerufen? Oder funktioniert es einfach nicht? –

+0

Überprüfen Sie den letzten Absatz der Frage. –

Antwort

0

Nun, beendete ich die data URI scheme (Hut Spitze zu Eric Pascarello) mit bis zu Nicht-IE-Browsern. Ich schrieb einen HTTP-Handler (in VB.NET) die IP-Kamera und Base-64 kodieren das Bild proxy:

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 

Dann habe ich nur ein wenig Nicht-IE Erkennung setzen (das klassische Dokument verwenden.alle Prüfung), um die korrekte URL/stellen Sie die richtige SRC zu nennen:

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

Es ist sehr bedauerlich, die ich für diese Problemumgehung zurückgreifen musste. Ich hasse Browser-Erkennungscode, und ich hasse die zusätzliche Last, die auf meinen Server gelegt wird. Der Proxy wird mich nicht nur zwingen, mehr Bandbreite zu verschwenden, aber er wird wegen der inhärenten Proxy-Nachteile und aufgrund der Zeit, die erforderlich ist, um das Bild zu kodieren, nicht so effizient arbeiten. Darüber hinaus ist es nicht eingerichtet, als würdevoll als IE zu degradieren. Obwohl ich den Proxy neu schreiben könnte, um HttpWebRequest zu verwenden und die richtigen Statuscodes zurückzugeben, etc. Ich wollte nur den einfachsten Weg wie möglich, weil ich es satt habe, damit umzugehen!

Danke an alle!

-1

Ich glaube, die Jquery wird versuchen, die Antwort vom Server zu interpretieren. Ich glaube, einige Browser sind toleranter gegenüber der Interpretation der Antwort, so dass restriktivere Browser scheitern werden, weil ein Bild nicht als HTML angesehen werden kann!

Die Lösung hierfür wäre die Verwendung eines HEAD-Anforderungstyps anstelle von GET (Typ: "HEAD"). Auf diese Weise erhalten Sie immer noch Statusantworten zurück, ohne das Bild selbst zu erfassen. Daher ist die Antwort leer (und sollte Sie nicht vermasseln). Außerdem sollte die Antwort viel schneller sein.

+0

Die Verwendung von HEAD gibt mir eine viel schnellere Antwort, aber es ist ein 404! –

+0

Ist das Webcam-Skript eine benutzerdefinierte HTTP-Implementierung? – Kazar

+0

Nein, es ist in den internen Server der IP Cam eingebaut und ich habe keine Möglichkeit es zu ändern. Ich könnte meinen eigenen Proxy schreiben, aber das wird nichts lösen. –

0

Eine zweite Antwort schreiben, weil die erste wirklich falsch war. Ich kann diese Lösung nicht testen (weil ich keinen Zugriff auf Ihr Webcam-Skript habe), aber ich würde vorschlagen, die Antwort von der Kamera zu bereinigen - da Sie offensichtlich mit den Rohbilddaten nicht umgehen können, versuchen Sie den dataFilter hinzuzufügen Einstellung wie folgt:

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

wie ich schon sagte, ich habe dies nicht in der Lage gewesen zu testen - aber es könnte jquery ermöglicht die Statuscodes zu verwenden, ohne wie verrückt zu brechen.

+0

Kein Glück :( Alles funktioniert perfekt in Internet Explorer. Ich könnte versuchen, einen Proxy zu schreiben, um das CGI-Skript zu wickeln und das Bild als Base-64 in XML codiert zurück. Was für ein PITA. –

+0

In der Tat, was für ein Schmerz, Angst Ich habe dann keine Ideen mehr - offensichtlich könnte es ein zugrunde liegendes Problem geben, das nichts mit dem Javascript zu tun hat, wahrscheinlich nicht von der Tatsache, dass die Webcam nicht das volle HTTP implementiert (Rolls Eyes) – Kazar

+0

Nicht sicher, was du meinst durch Implementierung von vollständigem HTTP.Es implementiert es gut. Unabhängig könnte ich sehr leicht einen Proxy schreiben, um zurückzugeben, was HTTP ich wünschte. Leider löst das noch nicht das Problem. –

0
img.onerror = function(){ 
    alert('offline'); 
} 
+0

Dank Eric. Ich muss wirklich den Statuscode obwohl weil es könnte auch eine 304 sein. Ich muss auf diese anders reagieren. Plus, wie erwähnt, ist das Onload-Ereignis unzuverlässig. Es feuert nicht immer wollte nicht ein setInterval tun, um die Aktualisierungshäufigkeit von der Verbindungsgeschwindigkeit abhängig zu machen, also mache ich ein Timeout innerhalb des Ladeereignisses (das den Angerufenen aufruft). Wenn Onload aus irgendeinem Grund nicht ausgelöst wird, wird die Aktualisierung gestoppt. Kannst du irgendeinen Grund sehen, warum mein AJAX-Ansatz in Firefox scheitern würde? –

+0

Würde etwas wie das Hinzufügen eines anderen QS-Wertes es zwingen, es zu holen. Vielleicht sieht es es als zwischengespeichert, da Sie es mit dem Ajax-Aufruf aufgerufen haben. var src = (xhr.status == 200)? url + "& foo = bar": "../i/cam-oos.jpg"; – epascarello

+0

Mein Fehler, ich habe deinen Kommentar falsch interpretiert. Ich würde das versuchen, aber der "komplette" Rückruf wird NICHT ALLE in Firefox abgefeuert. Nicht ein einziges Mal. Auch wenn es möglich war zu versuchen, beseitigt das nicht den ganzen Punkt des Vorladens? Ich würde einfach den SRC des Image-Tags direkt einstellen, wenn ich nicht vorher laden musste. Danke nochmal, dass du mir geholfen hast! Ich bin so ratlos, dass es nicht einmal lustig ist. –

Verwandte Themen