2017-01-29 5 views
4

J'ai une application hors ligne qui met en cache toutes les ressources statiques. Actuellement, seules les 15 premières secondes des ressources vidéo sont mises en cache. Ci-dessous figure les implémentations de base des écouteurs d'événements install et fetch.Est-il possible de mettre en cache une vidéo HTML5 entière à l'aide de l'API Service Worker pour une utilisation hors connexion?

service des travailleurs:

self.addEventListener('install', event => { 
    event.waitUntil(
    caches.open('v1').then(cache => { 
     return cache.addAll([ 
     '/', 
     '/videos/one.mp4', 
     '/videos/two.mp4' 
     ]); 
    }) 
); 
}); 

self.addEventListener('fetch', event => { 
    event.respondWith(
    caches.match(event.request).then(response => { 
     if (response) return response; 
     return fetch(event.request); 
    }); 
); 
}); 

Et index.html

<video controls preload> 
    <source src="/videos/one.mp4" type="video/mp4"> 
</video> 
+1

vous pouvez peut-être convertir la vidéo en un blob et enregistrez le blob. [this] (https://simpl.info/video/offline/) semble avoir quelques techniques pertinentes – danyamachine

+0

Les employés du service d'API de cache utilisent [paires de requêtes/réponses de magasins] (https://developer.mozilla.org/en-US/docs/Web/API/Cache/put # Paramètres). Donc, je doute qu'il y ait une limitation de type de fichier. [Quote:] (https://developer.mozilla.org/en-US/docs/Web/API/Cache) '... un mécanisme de stockage pour les paires d'objets Demande/Réponse qui sont mises en cache ...' –

+1

En fait, je l'ai mis à l'essai et il fonctionne très bien, comme prévu. [Vous pouvez le vérifier ici] (https://lazysheepherd.com/sw-test/offline/) –

Répondre

3

J'utilisé les étapes suivantes pour réaliser la vidéo en ligne sur la première page de chargement sans avoir d'abord regarder la vidéo (s). Enregistrer un travailleur de service et mettre en cache toutes les demandes.

  1. Les actifs statiques sont juste '/' pour ce cas. Si vous inspectez l'événement fetch du service worker, vous verrez que les demandes suivantes sont également mises en cache. Utilisez l'API fetch pour demander une vidéo en tant que blob.

Exemple utilisant fetch pour demander une vidéo en tant que blob

const videoRequest = fetch('/path/to/video.mp4').then(response => response.blob()); 
videoRequest.then(blob => { 
    ... 
}); 
  1. Utilisez l'API IndexedDB pour stocker les blob. (Utilisez IndexedDB au lieu de LocalStorage pour éviter de bloquer le thread principal lors du stockage.)

C'est tout! Maintenant, en mode hors connexion, le technicien de service interceptera les demandes et servira le html et le blob du cache.

index.html

<!DOCTYPE html> 
<html> 
<head> 
    <title>Test</title> 
</head> 
<body> 

    <h1>Service Worker Test</h1> 

    <p>Try reloading the page without an Internet connection.</p> 

    <video controls></video> 

    <script> 
    if ('serviceWorker' in navigator) { 
     window.addEventListener('load',() => { 
     navigator.serviceWorker.register('/service-worker.js').then(registration => { 
      console.log('ServiceWorker registration successful with scope: ', registration.scope); 
     }).catch(error => { 
      console.log('ServiceWorker registration failed: ', error); 
     }); 
     }); 
    } else { 
     alert('serviceWorker is not in navigator'); 
    } 
    </script> 

    <script> 
    const videos = { 
     one: document.querySelector('video') 
    }; 

    const videoRequest = fetch('/path/to/video.mp4').then(response => response.blob()); 
    videoRequest.then(blob => { 
     const request = indexedDB.open('databaseNameHere', 1); 

     request.onsuccess = event => { 
     const db = event.target.result; 

     const transaction = db.transaction(['videos']); 
     const objectStore = transaction.objectStore('videos'); 

     const test = objectStore.get('test'); 

     test.onerror = event => { 
      console.log('error'); 
     }; 

     test.onsuccess = event => { 
      videos.one.src = window.URL.createObjectURL(test.result.blob); 
     }; 
     } 

     request.onupgradeneeded = event => { 
     const db = event.target.result; 
     const objectStore = db.createObjectStore('videos', { keyPath: 'name' }); 

     objectStore.transaction.oncomplete = event => { 
      const videoObjectStore = db.transaction('videos', 'readwrite').objectStore('videos'); 
      videoObjectStore.add({name: 'test', blob: blob}); 
     }; 
     } 
    }); 
    </script> 
</body> 
</html> 

service pour les travailleurs

const latest = { 
    cache: 'some-cache-name/v1' 
}; 

self.addEventListener('install', event => { 
    event.waitUntil(
    caches.open(latest.cache).then(cache => { 
     return cache.addAll([ 
     '/' 
     ]); 
    }) 
); 
}); 

self.addEventListener('fetch', event => { 
    // exclude requests that start with chrome-extension:// 
    if (event.request.url.startsWith('chrome-extension://')) return; 
    event.respondWith(
    caches.open(latest.cache).then(cache => { 
     return cache.match(event.request).then(response => { 
     var fetchPromise = fetch(event.request).then(networkResponse => { 
      cache.put(event.request, networkResponse.clone()); 
      return networkResponse; 
     }) 
     return response || fetchPromise; 
     }) 
    }) 
); 
}); 

self.addEventListener('activate', event => { 
    event.waitUntil(
    caches.keys().then(cacheNames => { 
     return Promise.all(
     cacheNames.filter(cacheName => { 
      if (cacheName === latest.cache) { 
      return false; 
      } 

      return true; 
     }).map(cacheName => { 
      return caches.delete(cacheName) 
     }) 
    ); 
    }) 
); 
}); 

Ressources: