如何从 Blob url 中检索 MediaStream?
Posted
技术标签:
【中文标题】如何从 Blob url 中检索 MediaStream?【英文标题】:How to retrieve a MediaStream from a Blob url? 【发布时间】:2013-08-21 04:48:34 【问题描述】:可以使用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 对象?
【问题讨论】:
是的。 developer.mozilla.org/en-US/docs/WebRTC/MediaStream_API 如果您发布的代码不起作用,很可能是因为您在 src 之后设置了侦听器,请记住 blob 是本地资源,因此加载速度比互联网资源。 【参考方案1】:注意:
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);
唯一的方法就是跟踪你的原始对象。
为此,我们可以围绕createObjectURL
和revokeObjectURL
设计简单的包装器来更新可通过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);
【讨论】:
【参考方案2】:如果您使用的是 angular2,您可以使用 platform-browser-package 中提供的 DOMSanitizer:
import DomSanitizer from '@angular/platform-browser';
constructor(
private sanitizer: DomSanitizer)
然后像下面这样使用你的流:
//your code comes here...
video.src = this.sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(stream));
这应该只是
【讨论】:
createObjectURL 即将被弃用【参考方案3】:video.src 不是 video.srcObject
而且是的他们会发生冲突 ;) !
video.src
获取源网址
video.srcObject
获取源 OBJECT(目前截至 2019 年只有 MediaStream
is safely supported,也许将来您可以将 Blob 直接放在这里,但现在不行......)
所以这取决于你真正想做什么:
A) 显示当前正在录制的内容
您必须有可用的MediaStream
对象(您可以这样做)并将其放入video.srcObject
navigator.getUserMedia( video: true, audio: true , function (localMediaStream)
var video = document.querySelector('video');
video.src = ''; // just to be sure src does not conflict with us
video.srcObject = localMediaStream;
B) 显示现有视频/刚刚录制的视频
video.srcObject = null; // make sure srcObject is empty and does not overlay our src
video.src = window.URL.createObjectURL(THE_BLOB_OBJECT);
THE_BLOB_OBJECT
- 你要么已经通过 File API 创建了一个,或者通常如果你有某种记录器,让我们假设在 recorder
变量中,通常有 getBlob()
或类似的东西,如 recorder.getBlob()
我强烈建议您为此使用一些现有的记录器库,但要完整,有一个官方的 MediaRecorder API - https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder
所以您看到您刚刚将 2 件事组合在一起,您只需将它们分开并确保它们不会冲突 :)
【讨论】:
你说的是真的,但它没有回答问题......在 2013 年(当问题被问到时)没有srcObject
,当时显示 MediaStream 的唯一方法是制作指向此 MediaStream 的 BlobURL。从那时起,这已被弃用,但在发布该问题时,这是正常的做法。那么问题是“如何从指向 MediaStream 的 Blob URL 中检索 MediaStream”。因为我们可以用于 Blob 的 fetch(blobURL) 在这里不起作用。
如果您愿意,根据我们今天可以做的,问题将是“如何从 blobURL
检索 MediaSource 对象,其中 blobURL
是通过执行 URL.createObjectURL(MediaSource_instance)
生成的。”
@Kaiido 你是对的,我错过了日期,虽然问题是如何获得MediaStream
对象,而不是MediaSource
,除非你想要,否则这没有多大意义录制视频。
我使用 MediaSource 作为示例,因为它是另一个非 Blob 对象,我们可以从中生成 blobURI(就像之前可以使用 MediaStream 一样)。所以它是当代的等价物。并且有很好的案例想要检索一个 MSE,例如,能够将新的块附加到它。
好的,但是如果能够追加新的块,你不应该已经有了对象引用吗? (只是想知道:D)以上是关于如何从 Blob url 中检索 MediaStream?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 PHP 从 MYSQL 中插入和检索图像 blob?
如何使用 c# 从 azure blob 存储中检索 xml 文件
如何将图像存储为 Sqlite 中的 blob 以及如何检索它?