Javascript 是否可以使用Service Worker API缓存整个HTML5视频以供脱机使用?

Javascript 是否可以使用Service Worker API缓存整个HTML5视频以供脱机使用?,javascript,html,browser-cache,service-worker,Javascript,Html,Browser Cache,Service Worker,我有一个离线应用程序,可以缓存所有静态资源。目前,仅缓存前15秒的视频资源 下面显示了install和fetch事件侦听器的基本实现 服务人员: self.addEventListener('install', event => { event.waitUntil( caches.open('v1').then(cache => { return cache.addAll([ '/', '/videos/one.mp4',

我有一个离线应用程序,可以缓存所有静态资源。目前,仅缓存前15秒的视频资源

下面显示了
install
fetch
事件侦听器的基本实现

服务人员:

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);
    });
  );
});
index.html

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

我使用以下步骤在第一页加载时完成脱机视频,而无需先观看整个视频

  • 注册服务工作者并缓存所有请求。在这种情况下,静态资产只是
    '/'
    。如果检查服务工作者的
    fetch
    事件,您将看到后续请求也被缓存
  • 使用
    fetch
    API请求视频作为
    blob
  • 使用fetch请求视频作为blob的示例

    const videoRequest = fetch('/path/to/video.mp4').then(response => response.blob());
    videoRequest.then(blob => {
      ...
    });
    
  • 使用
    IndexedDB
    API存储
    blob
    。(使用
    IndexedDB
    而不是
    LocalStorage
    ,以避免在存储时阻塞主线程。)
  • 就这样!现在,在脱机模式下,服务工作者将拦截请求,并从缓存中为
    html
    blob
    提供服务

    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>
    
    资源:

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

    也许您可以将视频转换为blob并保存blob。似乎有一些相关技术是API服务人员使用的。所以我怀疑是否有任何文件类型限制<代码>…缓存的请求/响应对象对的存储机制…事实上,我已经对它进行了测试,正如预期的那样,它工作得很好@UmurKaragöz谢谢你,我也这么做了,而且效果很好。(我刚刚发布了一个答案,包括代码)嗨@Raphael Rafatpanah,我正在尝试为多个视频做这件事,有没有办法做到这一点,基本上我想在indexeddb中保存总共5个视频,并能够在浏览器中列出视频,以便我可以在脱机时单击并播放它们。只要设备有足够的光盘空间,这可能是可行的。您可能会在iOS上遇到问题,因为我认为与Chrome相比,iOS的存储限制更为严格。下面是一个示例,让您开始: