Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
134
rated 0 times [  137] [ 3]  / answers: 1 / hits: 16408  / 8 Years ago, sun, january 29, 2017, 12:00:00

I have an offline app that caches all static resources. Currently, only the first 15 seconds of video assets are cached.



Below shows basic implementations of the install and fetch event listeners.



Service Worker:



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


And in index.html



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

More From » html

 Answers
4

I used the following steps to accomplish offline video on the first page load without first watching the entire video(s).




  1. Register a service worker and cache all requests. Static assets are just '/' for this case. If you inspect the service worker's fetch event, you'll see that subsequent requests are also cached.

  2. Use the fetch API to request a video as a blob.



Example using fetch to request a video as a blob



const videoRequest = fetch('/path/to/video.mp4').then(response => response.blob());
videoRequest.then(blob => {
...
});



  1. Use the IndexedDB API to store the blob. (Use IndexedDB instead of LocalStorage to avoid blocking the main thread while storing.)



That's it! Now when in offline mode, the service worker will intercept requests and serve both the html and blob from 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 Worker



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


Resources:




[#59167] Thursday, January 26, 2017, 8 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
cameron

Total Points: 591
Total Questions: 112
Total Answers: 88

Location: Botswana
Member since Sat, Jan 7, 2023
1 Year ago
cameron questions
;