如何在Android/iOS的webview/移动浏览器中最佳预缓存视频?

9

描述

随着 同步 XMLHttpRequest 的快速移除(例如:Chrome 88 正在移除此功能),我正在寻找下一个最佳的替代方法来预缓存视频。

"同步 XMLHttpRequest 是个可怕的想法" - 从未有人这样说过。

是的,对于 大多数 场景,你是对的,但这是不同的。

以前

上,我所在公司有一个 SDK,在后台打开一个 ,将 HTML 注入其中,并等待 onload 事件触发。这会通知 SDK 准备好向用户展示 webview。

为了获得最佳的体验,播放视频时绝不能有任何缓冲。

这就是为什么在后台加载webview时,我们会使用XMLHttpRequest预缓存视频(同步方式)(由此导致延迟onload事件触发)。

可能的解决方案

我们考虑了一些不同的解决方案,它们各有优缺点;以下是其中的几个:

  1. 通过<link rel="preload" ... />预加载内容
  2. 将视频以base64嵌入index.html页面中(如果视频大小为2-3Mo,则转换为base64后重量会增加30%)

(1) 是最干净的方法,但由于各种原因需要在我们的后端进行一些较大的更改。同时也不能保证视频在浏览器/ webview 出现时完全被缓存。在不同的webview和移动浏览器中,预缓存的优先级也无法保证相同。例如,用户可以在他们的Chrome配置中停用预缓存功能。当连接是4G或更低时,它也无法工作(叹气)。

(2) 是一个hacky和未经优化的方法,但与(1)相比,实现起来相对简单。

问题

在webview /移动浏览器的背景中预缓存视频的下一个最佳方法是什么:

  1. 保证(或接近保证)视频播放时没有缓冲
  2. 在webview /浏览器内完成
  3. 最好跨移动浏览器/webview兼容
  4. (最好但不是必需的)延迟触发onload事件

注意:并非所有用户都可能拥有4g或wifi连接。 注意2:标签是自动播放的


你能否将视频放在DOM中某个隐藏的位置,并让它异步开始加载,然后使用计时器检查是否已缓冲好再加载Web视图? - joshstrike
@joshstrike 你可以这样做,但是它不会起作用。我曾经尝试过在视频异步加载时使用长时间同步循环,并在视频onloadeddata事件中停止同步循环。但是并没有成功,但是如果你能让它工作,请告诉我一声。 - kemicofa ghost
你目前是如何播放视频的?我认为你应该在问题中包含与播放视频相关的代码。包括执行 XML HTML 请求的代码,以及视频是如何注入 HTML 中并使用哪些 HTML 标签的信息。 - ehab
@ehab,这段代码已经过时了,不再相关,我正在寻找一种全新的策略。 - kemicofa ghost
你不能先获取视频,然后在获取到视频后打开webview并注入HTML吗? - Ahmed Mokhtar
@AhmedMokhtar 是的,完全可以这样做,这也是我们考虑过的一种方法,但与使用当前现有系统找到解决方案相比,这种方法的复杂性更为重要。 - kemicofa ghost
3个回答

2
为了保证视频播放时没有缓冲,可以使用本地的fetch API先将视频下载为blob,然后使用window.URL.createObjectURL将其转换为objectURL。这个URL可以作为视频元素的源来使用。
这是一个内置于webview/浏览器中的本地API,兼容性报告可以在这里找到:Can I use fetch 而且,不要监听onload事件,而是监听其他自定义事件,这样你可以手动控制。这也将在未来提供更好的灵活性。
  <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>

fetch是异步的,它无法延迟onload事件,因此无法保证视频已加载。不幸的是,我必须使用onload。它是行业标准的一部分,并且与其他公司的SDK存在兼容性问题。而且它将无法与我们旧的SDK兼容,这些SDK正在被其他开发人员使用。感谢您的答复。 - kemicofa ghost
话虽如此,这是一个有趣的想法。我也认为特定的方法可能会在未来过时。参考链接 - kemicofa ghost
请注意,createObjectURL 的使用仅对 MediaStream 对象已被弃用,而不是 BlobMediaSource 对象。 - Prakhar

1
如果您正在加载一个html页面,请在视频标签中使用preload="auto"。这将告诉浏览器在页面加载时下载整个视频(默认值是preload = "metadata",仅下载视频的3-5%)。
然后,您可以查看mediaEvent canPlayThrough以知道视频何时准备好播放(参见MDN reference)。
您考虑过流式传输视频吗?适当配置的流应立即开始播放,并且根据设备屏幕和网络吞吐量,自适应比特率算法可以更改提供的视频。 api.video提供了出色的服务(具有适用于iOS、Android和多个web后端的SDK)。

1
新的解决方案是使用缓存 API
caches = window.caches;
caches.open("app-assets").then((cache) => {
  cache.add(linkToFileToBeCached).then(() => {
    // Now the file is cached. Start rendering the app!
  });
});

这并不能解决我的问题,也不能保证视频在webview回到前台时远程就准备好了。这只是针对不同情况的一种解决方案。 - kemicofa ghost
我已经阅读了文档。这将异步地将视频放入浏览器缓存中以供使用和重复使用。我只想预先缓存(在Web视图出现之前加载视频),然后向用户显示它。这如何确保当Web视图出现时,视频将能够立即(自动)播放而不需要进行任何缓冲? - kemicofa ghost
它返回一个Promise。您可以编写代码等待Promise被解决,同时暂时显示任何加载屏幕...甚至可以在用户安装应用程序后开始加载所有资产,这样用户在打开视频时甚至不必等待加载屏幕。 - Menas
不能有任何的加载屏幕。我从事移动广告业务。如果在视频播放之前出现了加载屏幕,那将对业务造成灾难性的影响。 - kemicofa ghost
视频下载肯定需要时间。如果您不想显示加载页面,可以在用户打开视频之前很久就加载它。 - Menas
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接