如何根据大小而不是时间从(网络)MediaRecorder 获取流数据?
How to get stream data from (web) MediaRecorder based on size instead of time?
我目前正在使用 MediaRecorder
从用户的网络摄像头/麦克风获取视频流的块,如下所示:
navigator.mediaDevices
.getUserMedia({audio: true, video: true})
.then((stream) => {
var mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start(5000);
mediaRecorder.ondataavailable = (blobEvent) => {
console.log('got 5 seconds of stream', blobEvent);
}
})
这会每 5 秒的视频发出一个流块,但是,我想要特定大小的块,而不是长度。似乎没有明确的方法可以做到这一点,因为如果不开始一个新块我就无法检查当前块的大小,而且事后我也无法将它们组合起来。这是我想出的解决方法,使用 2 个媒体记录器:
const MIN_BLOB_SIZE = 5000000;
var partSize = 0;
navigator.mediaDevices
.getUserMedia({audio: true, video: true})
.then((stream) => {
var mediaRecorder = new MediaRecorder(stream);
var mediaRecorder2 = new MediaRecorder(stream)
mediaRecorder.start();
mediaRecorder2.start(5000)
mediaRecorder2.ondataavailable = (blobEvent) => {
console.log('got 5 seconds of data', blobEvent)
const blob = blobEvent.data
partSize += blob.size;
if (partSize >= MIN_BLOB_SIZE) {
partSize = 0;
mediaRecorder.requestData();
}
}
mediaRecorder.ondataavailable = (blobEvent) => {
console.log('got a chunk at least 5mb', blobEvent);
};
});
但这感觉很老套,给出了不精确的块,需要我确保这两个记录器完全同步,使错误处理/边缘情况复杂化,而且我担心使用 2 个媒体记录器对性能的影响。会接受用一台媒体记录器完成这项工作的答案,或者,如果那是不可能的,如果有人可以说服我 2 台媒体记录器在性能方面表现出色,我也会接受并处理它造成的并发症。
组合块
您可以事后将区块与new Blob(blobArray)
. If you absolutely need to process blobs of a certain size, you can use Blob.slice
合并。它可能看起来像这样:
const MIN_BLOB_SIZE = 5000000;
var partSize = 0, parts = [];
navigator.mediaDevices
.getUserMedia({audio: true, video: true})
.then((stream) => {
var mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start(5000);
mediaRecorder.ondataavailable = (blobEvent) => {
console.log('got 5 seconds of data', blobEvent);
const blob = blobEvent.data;
partSize += blob.size;
parts.push(blob);
if (partSize >= MIN_BLOB_SIZE) {
let bigBlob = new Blob(parts, { type: blob.type });
// if the blob size doesn't need to be precise:
partSize = 0;
parts = [];
// do something with bigBlob
// or if the blob size needs to be precise:
// let sizedBlob = bigBlob.slice(0, MIN_BLOB_SIZE, blob.type);
// parts = [ bigBlob.slice(MIN_BLOB_SIZE, bigBlob.size, blob.type) ];
// partSize = parts[0].size;
// do something with sizedBlob
}
};
mediaRecorder.onstop = (blobEvent) => {
console.log('Recording Stopped');
const blob = blobEvent.data;
partSize += blob.size;
parts.push(blob);
let bigBlob = new Blob(parts, { type: blob.type });
// do something with bigBlob, which may be smaller than MIN_BLOB_SIZE
};
});
使用比特率调整 Blob 大小
您可能还对 MediaRecorder API 中的 bitsPerSecond
(以及 audioBitsPerSecond
和 videoBitsPerSecond
)选项感兴趣,这可能会为您提供更可预测的 blob 大小对于给定的记录时间。不过,这可能会影响视频和音频质量。
我目前正在使用 MediaRecorder
从用户的网络摄像头/麦克风获取视频流的块,如下所示:
navigator.mediaDevices
.getUserMedia({audio: true, video: true})
.then((stream) => {
var mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start(5000);
mediaRecorder.ondataavailable = (blobEvent) => {
console.log('got 5 seconds of stream', blobEvent);
}
})
这会每 5 秒的视频发出一个流块,但是,我想要特定大小的块,而不是长度。似乎没有明确的方法可以做到这一点,因为如果不开始一个新块我就无法检查当前块的大小,而且事后我也无法将它们组合起来。这是我想出的解决方法,使用 2 个媒体记录器:
const MIN_BLOB_SIZE = 5000000;
var partSize = 0;
navigator.mediaDevices
.getUserMedia({audio: true, video: true})
.then((stream) => {
var mediaRecorder = new MediaRecorder(stream);
var mediaRecorder2 = new MediaRecorder(stream)
mediaRecorder.start();
mediaRecorder2.start(5000)
mediaRecorder2.ondataavailable = (blobEvent) => {
console.log('got 5 seconds of data', blobEvent)
const blob = blobEvent.data
partSize += blob.size;
if (partSize >= MIN_BLOB_SIZE) {
partSize = 0;
mediaRecorder.requestData();
}
}
mediaRecorder.ondataavailable = (blobEvent) => {
console.log('got a chunk at least 5mb', blobEvent);
};
});
但这感觉很老套,给出了不精确的块,需要我确保这两个记录器完全同步,使错误处理/边缘情况复杂化,而且我担心使用 2 个媒体记录器对性能的影响。会接受用一台媒体记录器完成这项工作的答案,或者,如果那是不可能的,如果有人可以说服我 2 台媒体记录器在性能方面表现出色,我也会接受并处理它造成的并发症。
组合块
您可以事后将区块与new Blob(blobArray)
. If you absolutely need to process blobs of a certain size, you can use Blob.slice
合并。它可能看起来像这样:
const MIN_BLOB_SIZE = 5000000;
var partSize = 0, parts = [];
navigator.mediaDevices
.getUserMedia({audio: true, video: true})
.then((stream) => {
var mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start(5000);
mediaRecorder.ondataavailable = (blobEvent) => {
console.log('got 5 seconds of data', blobEvent);
const blob = blobEvent.data;
partSize += blob.size;
parts.push(blob);
if (partSize >= MIN_BLOB_SIZE) {
let bigBlob = new Blob(parts, { type: blob.type });
// if the blob size doesn't need to be precise:
partSize = 0;
parts = [];
// do something with bigBlob
// or if the blob size needs to be precise:
// let sizedBlob = bigBlob.slice(0, MIN_BLOB_SIZE, blob.type);
// parts = [ bigBlob.slice(MIN_BLOB_SIZE, bigBlob.size, blob.type) ];
// partSize = parts[0].size;
// do something with sizedBlob
}
};
mediaRecorder.onstop = (blobEvent) => {
console.log('Recording Stopped');
const blob = blobEvent.data;
partSize += blob.size;
parts.push(blob);
let bigBlob = new Blob(parts, { type: blob.type });
// do something with bigBlob, which may be smaller than MIN_BLOB_SIZE
};
});
使用比特率调整 Blob 大小
您可能还对 MediaRecorder API 中的 bitsPerSecond
(以及 audioBitsPerSecond
和 videoBitsPerSecond
)选项感兴趣,这可能会为您提供更可预测的 blob 大小对于给定的记录时间。不过,这可能会影响视频和音频质量。