如何从Blob网址检索MediaStream? [英] How to retrieve a MediaStream from a Blob url?

查看:115
本文介绍了如何从Blob网址检索MediaStream?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以使用window.URL.createObjectURL()从流中获取URL,如下面的代码所示.

It was possible to get an URL using window.URL.createObjectURL() from a stream like in below code.

navigator.getUserMedia({ video: true, audio: true }, function (localMediaStream) {

    var video = document.querySelector('video');
    video.src = window.URL.createObjectURL(localMediaStream);
    video.onloadedmetadata = function (e) {
        // Do something with the video here.
    };
}, 
function (err) {
    console.log("The following error occured: " + err);
}
);

问题是我现在有一个Blob URL,例如:

Problem is now I have a blob URL like:

blob:http%3A//localhost%3A1560/f43bed15-da6c-4ff1-b73c-5640ed94e8ee

blob:http%3A//localhost%3A1560/f43bed15-da6c-4ff1-b73c-5640ed94e8ee

是否可以从中检索MediaStream对象?

Is there a way to retrieve the MediaStream object from that?

推荐答案

注意:

URL.createObjectURL(MediaStream)已被弃用. 不再在代码中使用它,它会在任何最新的浏览器中抛出.
问题的前提仍然有效.

Note:

URL.createObjectURL(MediaStream) has been deprecated. Do not use it in code anymore, it will throw in any recent browsers.
The premise of the question is still valid though.

没有内置方法来检索blob URL指向的原始对象.

There is no built in way to retrieve the original object a blob URL points to.

使用Blob,我们仍然可以获取该Blob网址,并获得原始Blob的副本.

With Blobs, we can still fetch this blob URL and we'll get a copy of the original Blob.

const blob = new Blob(['hello']);
const url = URL.createObjectURL(blob);

fetch(url)
  .then(r => r.blob())
  .then(async (copy) => {
    console.log('same Blobs?', copy === blob);
    const blob_arr = new Uint8Array(await new Response(blob).arrayBuffer());
    const copy_arr = new Uint8Array(await new Response(copy).arrayBuffer());
    console.log("same content?", JSON.stringify(blob_arr) === JSON.stringify(copy_arr))
    console.log(JSON.stringify(copy_arr));
  })

但是对于其他对象,这将无法工作...

With other objects though, this won't work...

const source = new MediaSource();
const url = URL.createObjectURL(source);

fetch(url)
  .then(r => r.blob())
  .then(console.log)
  .catch(console.error);

唯一的方法就是跟踪原始对象.

The only way then is to keep track of your original objects.

为此,我们可以在createObjectURLrevokeObjectURL周围提供简单的包装程序,以更新可通过URL访问的对象的字典:

To do so, we can come up with simple wrappers around createObjectURL and revokeObjectURL to update a dictionary of objects accessible by URL:

(() => {
  // overrides URL methods to be able to retrieve the original blobs later on
  const old_create = URL.createObjectURL;
  const old_revoke = URL.revokeObjectURL;
  Object.defineProperty(URL, 'createObjectURL', {
    get: () => storeAndCreate
  });
  Object.defineProperty(URL, 'revokeObjectURL', {
    get: () => forgetAndRevoke
  });
  Object.defineProperty(URL, 'getFromObjectURL', {
    get: () => getBlob
  });
  const dict = {};

  function storeAndCreate(blob) {
    var url = old_create(blob); // let it throw if it has to
    dict[url] = blob;
    return url
  }

  function forgetAndRevoke(url) {
    old_revoke(url);
    // some checks just because it's what the question titel asks for, and well to avoid deleting bad things
    try {
      if(new URL(url).protocol === 'blob:')
        delete dict[url];
    }catch(e){} // avoided deleting some bad thing ;)
  }

  function getBlob(url) {
    return dict[url];
  }
})();

// a few example uses

// first a simple Blob
test(new Blob(['foo bar']));

// A more complicated MediaSource
test(new MediaSource());

function test(original) {
  const url = URL.createObjectURL(original);
  const retrieved = URL.getFromObjectURL(url);
  console.log('retrieved: ', retrieved);
  console.log('is same object: ', retrieved === original);
  URL.revokeObjectURL(url);
}

这篇关于如何从Blob网址检索MediaStream?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆