2015-04-16 12 views
13

Ich habe einen Service-Mitarbeiter, der Anfragen meiner Seite abfängt (fetch Ereignis), und wenn die URL mit einem bestimmten Muster übereinstimmt, würde es eine andere URL holen und die Antwort durch diesen neuen Inhalt ersetzen. Es funktioniert perfekt für Textdaten (JS, XML ...) oder binäre Daten (z. B. Bilder), aber wenn es um Video geht, gibt es einen Fehler.Wie kann ich ein Video von einem ServiceWorker streamen?

Ich verwende Chrome 41 unter OSX.

Dies ist der vereinfachte Code meiner Arbeiter:

self.addEventListener('fetch', function(event) { 
    var url = event.request.url; 
    console.log('SW: fetch', url); 
    if (/\.mp4$/.test(url)) { 
    url = 'https://vjs.zencdn.net/v/oceans.mp4'; 
    var options = { 
     credentials: 'include', 
     mode: 'no-cors' 
    }; 
    event.respondWith(fetch(url, options)); 
    } 
}); 

Und dies ist der vereinfachte Code in meinem HTML-Seite:

navigator.serviceWorker.register('sw.js').then(function(reg) { 
    console.info('ServiceWorker registration successful for', reg.scope); 

    var video = document.createElement('video'); 
    video.src = '/video.mp4'; 
    video.controls = true; 
    video.autoplay = true; 
    video.onerror = function(err) { 
    console.error('Video load fail', err); 
    } 
    video.onload = function(data) { 
    console.info('Video load success'); 
    } 
    document.body.appendChild(video); 

}).catch(function(err) { 
    console.error('ServiceWorker registration failed:', err); 
}); 

Das erste Mal, wenn Sie die Seite lädt, installiert der Arbeiter, Die Videoanforderung wird also nicht abgefangen und schlägt somit fehl. Wenn Sie die Seite jedoch neu laden (ohne den Cache zu bereinigen), wird sie erfolgreich abgefangen, und der Worker lädt das Video erfolgreich (HTTP 200 in seinem Inspektor), aber aus irgendeinem Grund wirft die Hauptseite eine net::ERR_FAILED.

Und ich kann nicht manuell lesen/es streamen, weil sie von einem anderen Ursprung kommen, was zu einem „opaque“ Antworttyp: http://www.w3.org/TR/service-workers/#cross-origin-resources

UPDATE: Update auf Chrome 42, der Fehler ist jetzt HTTP 400 Service Worker Fallback Required (from ServiceWorker). Seltsame Sache ist, dass the source code (Zeile 510) angibt, dass es nur ausgelöst werden sollte, wenn CORS-Header fehlen, aber hier ist der Modus no-cors.

Antwort

7

Zunächst einmal würde ich empfehlen, versuchen in der aktuellen Chrome Canary, die derzeit Release 44.0.2371.0 entspricht. Die Entwickler-Tools für Service-Mitarbeiter werden mit jeder neuen Chrome-Version immer besser und mit Version 43+ im Allgemeinen viel besser.

Es sieht nicht so aus opaque Response Objekten können für die src ein <video> Element verwendet werden, und ich gehe davon aus, das ist Absicht. (Opaque Response s kann für bestimmte Zwecke verwendet werden, und ich fürchte, ich habe keinen vollständigen Überblick über das, was wird und wird nicht mit einem undurchsichtigen Response arbeiten.)

Aber in jedem Fall, du bist Glück, dass vjs.zencdn.net CORS unterstützt, so dass Sie mit der Verwendung der Standard-CORS-fähigen Request, die Ihnen eine undurchsichtige Response geben wird.

Eine Sache, die Sie nicht tun können, ist die Verwendung credentials: 'include' in Ihrem CORS Request, weil es zu einer Fetch API führen kann https://vjs.zencdn.net/v/oceans.mp4 nicht geladen werden. Ein Platzhalter '*' kann nicht im Header 'Access-Control-Allow-Origin' verwendet werden, wenn das Credentials-Flag wahr ist. Fehler. Dies scheint kein Problem mit Ihrem speziellen Host zu sein, da keine Anmeldeinformationen erforderlich sind.

Als ich Ihren Code um event.respondWith(fetch('https://vjs.zencdn.net/v/oceans.mp4')); zu verwenden, funktionierte alles gut.

+0

Vielen Dank Jeff, CORS Header waren in der Tat das Problem! – antoine129

+0

Ich habe ein Problem auf dem Chromium-Tracker geöffnet, um das Debugging zu verbessern: https://code.google.com/p/chromium/issues/detail?id=477685 – antoine129

Verwandte Themen