Javascript HTML5视频源作为本地存储的blob不再工作

Javascript HTML5视频源作为本地存储的blob不再工作,javascript,blob,indexeddb,Javascript,Blob,Indexeddb,从Chrome80开始,Blob或IndexedDB的工作方式似乎发生了变化 将视频文件加载为blob并通过createObjectURL将其分配给HTML5视频元素仍然有效: // load the blob through XMLHttprequest RequestAsBlob("https://devserver/some-video.mp4", function(blob) { video.src = URL.createObjectURL(blob); // same a

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

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

// 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();
输出:承诺{} 视频播放得很好

检查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(通过localfollow),然后检索并播放它,如下所示。这个,不再是了

// 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完全相同

但是,它不起作用:

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

我不知道是什么变化打破了过去的工作方式,直到现在。 更奇怪的是:

如果我得到存储的blob,一个显然不能再直接分配给视频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。。。它是有效的

这毫无意义。 我希望有人能对此有所了解。

,即使是在金丝雀造型(82)中,你的开场白也很出色

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

video.src = URL.createObjectURL(new Blob( [ blob ] ) ); 
从StackSnippet开始™ 不允许访问IndexedDB

然而,这种解决方法似乎只适用于稳定版本(80),而在金丝雀(82),我们需要实际将整个Blob读入ArrayBuffer并从该ArrayBuffer构建一个新Blob:

const buf = await blob.arrayBuffer();
vid.src = URL.createObjectURL( new Blob( [ buf ] ) );
.
由于后者也适用于stable,而且我们不知道他们什么时候能够修复bug,因此您可能需要使用第二种解决方法


1:如果你想让我做,也可以告诉我。

谢谢Kaido,打开了这个问题。不知怎的,我怀疑一种回归与。。安全只是一种直觉。我还看到,应该可以直接将blob分配给HTMLVideo.srcObject,但这似乎也不起作用。我想知道是否有任何方法可以从blob创建MediaTrack?根据规范,我们应该能够将srcObject用于blob和MediaSources是的,但是目前除了MediaStreams之外,没有人将它用于其他任何东西。将Blob中的视频转换为MediaStream需要将其加载到视频中,这并不是很有用。MediaSource可能更合适,但您需要将其作为ArrayBuffer来阅读,因此
新Blob([Blob.ArrayBuffer()])
解决方案仍然是最好的。我们也有同样的问题,显然它对于所有没有faststart(开始时是moov)的mp4来说都是坏的-我们也打开了一个问题-是的,您的解决方案有效(arrayBuffer one,我们已经从Blob中获得了新的Blob,但它仍然在v80上停止工作),谢谢!由于问题出现在mpeg 4第14部分(mp4)视频中,文件末尾有
moov
atom,因此视频播放器必须跳转到文件末尾,然后返回到开头。我认为这可能会破坏缓存系统或损坏缓存文件,具体取决于他们实际缓存文件的方式。如果他们对文件进行流式缓存,那么在文件周围跳来跳去是不好的。我认为,通过请求整个
arrayBuffer
可以强制缓冲区完全缓存,然后再将其传递给播放器进行跳转,尽管我不知道这是否适用于较大的文件(我认为arrayBuffer保存在RAM中)。@Kaido证实。我刚刚记得:这似乎正是我以前在iOS上遇到的一些MP4文件,但不是全部。我想这可能就是Eek所提到的(缺少faststart),但我对编码的怪癖不太熟悉。不幸的是,我记不起什么iOS/Safari版本出现了这个问题,但我相当肯定我在去年11月就看到了这个问题。顺便问一下,有没有什么快速修复方法可以在不重新编码的情况下将faststart添加到MP4s中?我为同一个问题提交了一个chrome bug:(它最终是你的半复制品)