我目前正在构建一个媒体播放器 Web 应用程序,该应用程序需要将音频和视频存储在客户端。要求还避免流式传输,并且它必须在 Safari 中工作。
为此,我选择了 IndexedDb 并将所有内容都很好地存储在浏览器中。我可以通过网络音频 api 获取音频和播放没有问题,但是 - 我很快就遇到了视频问题。
我目前的方法是从 indexeddb 获取视频并为 src 属性创建一个 blob url:
const objectUrl = createObjectURL(record.videoData);
this.video.src = objectUrl;
这种方法适用于小视频(任何小于 30mb 的视频),但对于较大的视频,播放会断断续续,我注意到网络检查器中对 blob url 的几个错误请求(见图):
尽管“错误”请求视频加载和播放。唯一的问题是口吃。我还注意到,随着文件大小的增加,这种情况变得越来越严重。
我环顾四周,但没有找到任何替代方法来实现无流媒体播放。我查看了 Safari 发行说明,注意到以下内容(来自:safari release notes):
Changed memory handling to keep all of the decoded frames for an animated image if the total memory size of the frames is under 30MB (up from 5MB)
这看起来可能是卡顿的原因 - 我假设 safari 正在尝试下载 bloburl 的 block 。
对于我想要实现的目标,是否有替代方法?这在 chrome 中表现得更好(没有卡顿),但是 - 这必须在 Safari 中工作。
非常感谢任何帮助。
最佳答案
我可以看到可能对您有帮助的三件事。
首先,您是否在每次不再使用 blobURI 时都撤销它?
从 indexedDB 中检索 Blob 实际上会复制内存中的数据,这与 input[file] 不同,这意味着当您从这些 Blob 创建 blobURI 时,这些 blobURI 不会指向磁盘上的文件,但会绑定(bind) Blob 的内存中的数据,直到 blobURI 被撤销或 session 过期。因此,当您刷新页面时,您可能会多次在内存中保存相同的数据。
然后,您可以尝试将大文件拆分成较小的 block ,并在需要时合并它们。如果您认为 5MB 的文件工作正常,您可以使用 Blob.slice(startByte, endByte)在生成较小 Blob 的循环中,您将与 new Blob([chunks])
合并,并且只从这个合并的 Blob 创建一个 blobURI。
这是一个 fiddle demonstrating it .
虽然合并的 Blob 解决方案对我来说已经足以消除这些卡顿的渲染,但这在内存较少的设备上可能会失败,因此作为 final方法,您可以使用 block 的想法,但不合并它们。相反,您可以使用 MediaSource API ,并使用您将从 block 中获得的 arrayBuffers 提供一个流(通过 FileReader.readAsArrayBuffer
)。
关于javascript - Safari BlobUrl 30mb 限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47520997/