javascript - 如何从 Blob url 检索 MediaStream?

标签 javascript html5-video html5-audio

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

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:

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

有没有办法从中检索 MediaStream 对象?

最佳答案

备注:

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



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

使用 Blob,我们仍然可以获取此 Blob URL,并且我们将获得原始 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));
  })

但是对于其他对象,这将不起作用...

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

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

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

为此,我们可以想出围绕 createObjectURLrevokeObjectURL 的简单包装器来更新可通过 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);
}

关于javascript - 如何从 Blob url 检索 MediaStream?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18312962/

相关文章:

javascript - 捕获音频数据(使用 JavaScript)并以 MP3 形式上传到服务器

javascript - PHP-如何捕获XML错误描述

javascript - 存储和加载文件系统中的媒体到 Electron 应用程序

javascript - chrome 视频 src 更改不起作用

javascript - 在 div 中水平对齐 html5 音频元素

asp.net-mvc - MVC 音频控制从字节播放歌曲

c# - 如何从代码后面隐藏和显示 asp :buttons in asp.net?

javascript - 如何知道 if 语句中哪个条件为真?

javascript - 如何使用 jQuery 检测点击事件是否发生?

javascript - 无法在首页加载时使用 HTML5 和 Google Chrome 中的 getUserMedia() 从网络摄像头拍照