TransWikia.com

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

Stack Overflow Asked by kemicofa ghost on November 12, 2021

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 and , the company I work for has an SDK that opens a 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

3 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>

Answered by Prakhar on November 12, 2021

If you are loading an html page - use preload="auto" in the video tag. This tells the browser to download the entire video on page load (the default is preload = "metadata" which downloads 3-5% of the video).

You can then look at the mediaEvent canPlayThrough to fire to know when the video is ready to play(MDN reference).

Have you thought about streaming the video? A properly configured stream should begin playback immediately, and have little to no buffering as the adaptive bitrate algorithm can change the video delivered based on the device screen AND network throughput. api.video has a great service (with SDKs for iOS, Android and several web backends)

Answered by Doug Sillars on November 12, 2021

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

Answered by Menas on November 12, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP