Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to best precache videos in webview/mobile browser on Android/iOS?

Description

With the fast approaching removal of synchronous XMLHttpRequest (i.e.: Chrome 88 is removing this), I am looking for the next optimal alternative method to precache a video.

"Sychronous XMLHttpRequest is a horrible idea" - said no one ever

Yes, you're right for most scenarios but this is different.

Previously

On android and ios, the company I work for has an SDK that opens a webview in the background, injects HTML into it and waits for the onload event to fire. This notifies the SDK when the webview is ready to be shown to the user.

It is imperative that when a video plays there is NO buffering whatsoever for the best possible experience.

This is why when the webview is loading in the background, we precache the video synchronously with XMLHttpRequest (which by consequence, delays the onload event from being fired).

Possible solutions

We've thought about some different solutions, and they each have their pros and cons; here are a few:

  1. Preload content via <link rel="preload" ... />
  2. Embed the video within the index.html page in base64 (if the video weights 2-3Mo, it'll weigh 30% more after converting to base64)

(1) is the cleanest method, but requires some heavy changes on our backend for various reasons. There is also no guarantee that the video will be fully cached by the time the browser/webview appears. There is no guarantee that the priority of the precaching will be the same across webviews and mobile browsers. Users can deactivate the precaching features, for example, in their Chrome configuration. It also does not work when the connection is 4G or lower (sigh).

(2) is a hacky and unoptimized method but is relatively simple to implement compared to (1)

Question

What is the next best method to precache a video in the background of a webview/mobile browser that:

  1. Guarantees (or closely guarantees) no buffering when the video is played
  2. Is done within webview/browser
  3. Is (preferably) cross mobile browser/webview compatible
  4. (preferably and not required) delays the onload event from being triggered

Note: not all users may have a 4g or wifi connection. Note2: tag is in autoplay

like image 617
kemicofa ghost Avatar asked Jul 13 '20 13:07

kemicofa ghost


2 Answers

To guarantee that there is no buffering when the video is played, the video can first be downloaded as a blob using the native fetch API and then converted to objectURL using window.URL.createObjectURL. This URL can then be used as the source for video element

This is a native API built-in the webview/browser and the compatibility report can be found here Can I use fetch

And instead of listening for onload event, listen for some other custom made event which you can manually control. This will give better flexibility in future also.

  <script>

      fetch('http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4').then(response => {
          //Video Download Started
          return response.blob();

      }).then(data => {
          //Video Downloaded"
          let objectUrl = window.URL.createObjectURL(data);
          document.querySelector("#myvideoPlayer").src = objectUrl;

          //Trigger a custom event here
      }).catch(error => {
          // Log Error
      })

  </script>

  <video controls id="myvideoPlayer"></video>
like image 118
Prakhar Avatar answered Oct 04 '22 16:10

Prakhar


The new solution is by using the Cache API

caches = window.caches;
caches.open("app-assets").then((cache) => {
  cache.add(linkToFileToBeCached).then(() => {
    // Now the file is cached. Start rendering the app!
  });
});
like image 28
Menas Avatar answered Oct 04 '22 16:10

Menas