HTML5视频源作为本地存储的BLOB不再起作用

2022-03-03 00:00:00 blob javascript indexeddb

从Chrome 80开始,Blob或IndexedDB的工作方式似乎发生了变化。

将视频文件作为BLOB加载并通过createObjectURL将其分配给HTML5 Video元素仍然有效:

// load the blob through XMLHttprequest
RequestAsBlob("https://devserver/some-video.mp4",
function(blob)
{
  video.src = URL.createObjectURL(blob); 

  // same above, video.src is now "blob:https://devserver/36e15718-e597-4859-95d3-6bc39daaa999"
}

video.play();

输出:Promise:{} 并且视频播放正常。

检查Blob,如下所示:

Blob {size: 6752122, type: "video/mp4"}
size: 6752122
type: "video/mp4"
__proto__: Blob
arrayBuffer: ƒ arrayBuffer()
size: (...)
slice: ƒ slice()
stream: ƒ stream()
text: ƒ text()
type: (...)
constructor: ƒ Blob()
Symbol(Symbol.toStringTag): "Blob"
get size: ƒ size()
get type: ƒ type()
__proto__: Object

我过去常常将blob存储到IndexedDB(通过LocalForage),然后检索并回放它,如下所示。这个,不再

// blob is a blob fetched from indexedDB
video.src = URL.createObjectURL(blob);  

// video.src is now something like this:
// "blob:https://devserver/ec5e1dfe-0884-40e2-ae8c-c6062734d297"

video.play();

检查检索到的BLOB,它看起来与XMLHttpRequest返回的BLOB完全相同

但是,它不起作用:

输出:未捕获(承诺中)DOMException:该元素没有受支持的源。

我想不出是什么改变打破了以前的正常工作。 更奇怪的是:

如果我获得存储的blob,即显然不能再直接分配给video src的blob,则我执行此操作.

var url = URL.createObjectURL(cachedblob);

RequestAsBlob(url,
function(blob)
{
 var url = URL.createObjectURL(blob);

 video.src = url;
 video.play();
}

这行得通!!我引用了存储在IndexedDB中的BLOB,为它创建一个URL,通过XMLHttpRequest再次加载它,就像它实际上位于某个远程位置一样,再次将其作为BLOB接收……并再次创建指向它的URL.而且还能用。

这没有任何意义。 我希望有人能解释一下这件事。


解决方案

Could repro,即使在金丝雀版本(82)中,您的开场白也很棒this issue。

现在,有比通过XHR获取更简单的解决方法,例如在STRATE(80)中,您只需要将检索到的Blob包装在一个新的Blob中:

video.src = URL.createObjectURL(new Blob( [ blob ] ) ); 

ASa fiddle,因为堆栈片段™不允许访问索引数据库。

但是,此解决方法似乎只在稳定版本(80)上有效,在Canary(82)上,我们需要将整个Blob实际读取到ArrayBuffer并从该ArrayBuffer构建新的Blob:

const buf = await blob.arrayBuffer();
vid.src = URL.createObjectURL( new Blob( [ buf ] ) );

fiddle。
由于后者也适用于稳定,并且我们不知道他们何时能够修复该错误,因此您可能希望改用第二种解决方法。

1:或者如果您希望我这样做,请告诉我。

相关文章