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

Posted

技术标签:

【中文标题】如何在 Android/iOS 上的 webview/移动浏览器中最好地预缓存视频?【英文标题】:How to best precache videos in webview/mobile browser on Android/iOS? 【发布时间】:2020-11-02 16:31:25 【问题描述】:

说明

随着 同步 XMLHttpRequest 的快速删除(即:Chrome 88 正在删除它),我正在寻找下一个预缓存视频的最佳替代方法。

“同步 XMLHttpRequest 是一个可怕的想法” - 从来没有人说过

是的,您适合大多数场景,但这是不同的。

以前

androidios 上,我工作的公司有一个SDK,它在后台打开webview,将html 注入其中并等待onload 事件触发。这会在 webview 准备好向用户显示时通知 SDK。

必须在视频播放时没有缓冲以获得最佳体验。

为什么当 webview 在后台加载时,我们预先缓存了视频 synchronously with XMLHttpRequest(这会延迟 onload 事件的触发)。

可能的解决方案

我们已经考虑了一些不同的解决方案,它们各有优缺点;这里有几个:

    Preload content 通过<link rel="preload" ... /> 将视频嵌入到 base64 格式的 index.html 页面中(如果视频重量为 2-3Mo,转换为 base64 后重量会增加 30%)

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

(2) 是一种 hacky 且未经优化的方法,但与 (1) 相比,相对易于实现

问题

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

    保证(或严格保证)视频播放时不缓冲 在 webview/浏览器中完成 (最好)跨移动浏览器/webview 兼容 (最好但不是必需的)延迟触发 onload 事件

注意:并非所有用户都有 4g 或 wifi 连接。 注意2:标签在自动播放中

【问题讨论】:

能否将视频放置在 DOM 中隐藏的某个位置,让它开始异步加载,并在加载 webview 之前使用计时器检查它是否已缓冲? @joshstrike 你可以,但它不会工作。我尝试过长时间同步循环,而视频会异步加载..并让视频 onloadeddata 停止同步循环。没有成功,但是如果你让它工作,请告诉我。 您目前如何播放视频,我认为您应该在问题中包含与播放视频相关的代码。进行xml html请求的代码,以及视频是如何注入html的,以及使用什么html标签 @ehab 代码是无关紧要的,因为它已被完全弃用,我正在寻找一个全新的策略。 有什么原因你不能先获取视频,然后在获取视频时打开 webview 并注入 html? 【参考方案1】:

为保证播放视频时没有缓冲,可以先使用原生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 兼容。谢谢你的回答。 话虽如此,有趣的想法。我也觉得具体方法可能变成obselete in the future。 请注意,createObjectURL 的使用仅适用于 MediaStream 对象,不适用于 BlobMediaSource 对象。【参考方案2】:

新的解决方案是使用Cache API

caches = window.caches;
caches.open("app-assets").then((cache) => 
  cache.add(linkToFileToBeCached).then(() => 
    // Now the file is cached. Start rendering the app!
  );
);

【讨论】:

感谢您的回答,但我很困惑这应该如何解决问题? 你在困惑什么?这是一个很棒的 javascript API,您可以使用它以编程方式预缓存任何资源,并且它在除 Internet Explorer 之外的所有浏览器上都受支持 这并不能解决我的问题,并且不能保证当 webview 进入前台时视频将远程准备好。这是针对不同场景的解决方案。 我确实阅读了文档。这会将视频异步放入浏览器的缓存中以供使用和重用。我只想预缓存(在 webview 出现之前提前加载视频),然后向用户显示一次。这如何确保当 webview 出现时,视频能够立即(自动)播放而无需任何缓冲? 它返回一个 Promise。您可以编写代码等待 Promise 解决,同时暂时显示任何加载屏幕。您甚至可以在用户安装应用程序后开始加载所有资产,这样用户在打开时甚至不必等待加载屏幕视频。【参考方案3】:

如果您正在加载 html 页面 - 在视频标签中使用 preload="auto"。这告诉浏览器在页面加载时下载整个视频(默认为 preload = "metadata" 下载 3-5% 的视频)。

然后您可以查看 mediaEvent canPlayThrough 以了解视频何时可以播放 (MDN reference)。

您是否考虑过流式传输视频?正确配置的流应立即开始播放,并且几乎没有缓冲,因为自适应比特率算法可以根据设备屏幕和网络吞吐量更改传输的视频。 api.video 的服务很棒(带有适用于 iOS、Android 和多个 Web 后端的 SDK)

【讨论】:

以上是关于如何在 Android/iOS 上的 webview/移动浏览器中最好地预缓存视频?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 js 以编程方式为 android/ios 上的网站创建桌面快捷方式?

Android / iOS 上的模拟多人游戏技术

强制 Youtube 链接在 Android/iOS 上的应用程序中打开

小程序 height100% Android ios上的不同表现

有啥方法可以防止 android/ios 上的非法位置?

Android / iOS 应用内浏览器上的证书固定