【问题标题】:If Blob URLs are immutable, how does Media Source Extension API use them to stream videos?如果 Blob URL 是不可变的,Media Source Extension API 如何使用它们来流式传输视频?
【发布时间】:2024-01-14 16:19:01
【问题描述】:

让我们从一个例子开始:

  1. 您访问 youtube.com,该网站在某些设备上使用带有 HTML5 的媒体源扩展 (MSE)。
  2. MSE 使用 blob URL 注入
  3. 在流​​式传输整个视频的过程中,您的浏览器会进行多次网络调用以下载各种视频块,并将它们附加到 MSE 的 SourceBuffer
  4. 因此,Meda Source 对象作为一个整体在整个视频流中更新
  5. 但是,最初附加到

对我来说,这似乎没有多大意义。假设 Blob URL 表示永远不会更改的不可变数据块。但似乎 MSE 能够让它们代表一个可变的内存缓冲区。

这在后台是如何工作的?如果我们还想让 blob URL 表示一些可变的内存缓冲区,我们如何使用 javascript 自己做到这一点?

【问题讨论】:

    标签: javascript html browser media-source


    【解决方案1】:

    您需要了解 BlobURI不代表任何数据。它们只是链接,指向内存中的某些资源,就像字符串 https://*.com/questions/54613972 本身不包含您正在阅读的任何内容一样,它只是指向将生成页面的服务器指令。

    它们的链接可以说是不可变的,一旦你使用URL.createObjectURL(target)生成它,你就不能改变它的target,就像你使用const关键字一样。

    const foo = {} 为例,现在foo 不能设置为除此对象之外的其他内容。 但是foo地址指向的对象仍然是可变的。 foo.bar = 'baz' 还是可以的。

    const foo = {};
    try{
      foo = 'fails';
    }
    catch(e) {
      console.error(e);
    }
    foo.mutable = true;
    
    console.log(foo);

    对于 blobURI 来说也是一样的。 blobURI 指向 target 对象,此链接无法更改,但 target 仍然是可变的。这适用于 MediaSource 对象,但也适用于其他对象。

    如果您还记得几年前,我们仍然可以为 MediaStreams 使用 blobURI(这是一个坏主意),这是相同的过程,blobURI 以不可变的方式指向 MediaStream 对象,但是媒体数据不断变化(一个流)。

    即使对于文件,您也可以很好地拥有一个指向硬盘驱动器上的文件的 blobURI,这不会阻止您将其从硬盘中删除,即使 blobURI 现在不再指向任何地方。

    这方面的一个特殊情况是 Blob,它是从内存中的数据生成的(即不仅仅是指向磁盘上文件的指针)。这里 Blob 持有的数据是不可变的,所以在这种情况下,blobURI 确实指向了一个持有不可变数据的对象。

    对于您请求有一个指向存储在内存中的某些数据的 blobURI,但仍然能够修改这些数据,这是无法做到的...
    这是因为这种情况意味着您使用内存中的数据从 Blob 对象创建了 blobURI,而内存中的数据再次将数据保持在不可变状态。

    【讨论】:

    • “这不行。” 技术上可以做到Where is Blob binary data stored?
    • @guest271314 来自 Web API 的“这无法完成”...显然您可以将您的计算机扔进火中...
    • 是的,已经烧了好几个实验了。 Capturing MediaStream from HTMLMediaElement where src is set to MediaSource crashes tab #207MediaSource 中的错误示例之一。这是一种特殊情况,在 Mozilla 和 Chromium 实现之间的行为上有明显的差异。可能是由于用 C++ 编写的底层媒体播放器播放媒体,尽管在实现中绝对可以观察到一个错误。
    • 当然这个对象很特殊,可能有特殊的错误,但这与当前的问题完全无关,也与 blobURIs 无关...
    • 不同意。问题本质上是MediaSource 是如何工作的。这需要相当多的努力来收集。这并不像解释Blob URLs 与Blob URIs 有何不同或相同那么简单。阅读以前和当前的规范、打开和关闭的问题、邮件列表。项目历史。实际上在不同的浏览器上运行代码,这就是“橡胶与道路相遇的地方”。在无错误的实现中,错误无关紧要。当错误使浏览器选项卡崩溃且未修复时,系统性问题可能在未经测试的情况下不会立即显现。
    【解决方案2】:

    用于MediaSourceBlob URL 是一种特殊情况。 MediaSource 是一个特例。

    这个概念

    假设 Blob URL 代表不可变数据块,这些数据永远不会 变化。

    不一定是真的。考虑包含例如 HTML 和 JavaScript 的 Blob URL。可以从原始Blob URL 生成更多数据,包括额外的Blob URLs。

    【讨论】:

    • 实际上 Blob 对于 OP 的 blobURI 来说是特殊的。我不确定你对Further data can be generated from that original Blob URL, including additional Blob URLs 的意思。 blobURI 只指向某个资源,以后用它做的任何事情都不能说是 blobURI 的事实。当我从 blobURI 加载 mp3 时,它不是在我的计算机中唱歌的 blobURI,就像它也不是一个 url 一样。
    • @Kaiido 是的,一个特例。如果开发MediaSource的组的源代码和严格的参数,以及与Blob使用相关的问题,以及规范审查可以变得更加清晰。是的,可以说进一步处理的起源是在最初的Blob URLBlob URI
    • 对不起,我不明白您的评论...我的意思是 Blob 在这里很特别,因为只有 Blob 确实保存不可变数据。磁盘上的文件、MediaStream 或 MediaSource 都没有这种特殊性。所以 Blob 是这里的特例。
    • @Kaiido 不确定您要传达什么。数据不是“不可变的”。 Blob URLs 指向的数据可以在磁盘上修改,只要有足够的动机这样做。此外,Blob URL 可以动态生成其他进程,其中派生的进程不是不可变的,因此 Blob URL 本身不是不可变的。在 MediaSource 的情况下,Blob URLBlob URIBlob URL 的行为特别不同,Blob URLMediaSource 无关,尤其是在 Chromium/Chrome 浏览器实现中。
    • blob URL 本身只是一个字符串...此字符串指向内存中的某个对象,此链接无法修改 => 它是“不可变的”。现在,由内存中的数据(如new Blob(['foo bar']))制成的 Blob 将其数据以不可变的方式卡在内存中:在生成 Blob 后,任何 Web API 都无法修改此数据(而例如 ArrayBuffers 是可变的)。而我停留在 Web API 领域,问题被标记为 js 和浏览器。
    最近更新 更多