如何解决如何摆脱 MediaRecorder 创建的 blob? [内存泄漏]
MediaRecorder 创建的 Blob 永远不会发布。 [内存泄漏?]
Chrome 88 桌面版和移动版
我创建了一个监控应用程序,想经常录制较大的视频剪辑(30-100MB)并将数据上传到云端。
在开发过程中遇到了
- “错误:数据错误:无法写入 blob。”
- “ERR_OUT_OF_MEMORY:没有足够的内存或磁盘空间可用于 blob”(在 chrome://blob-internals 中可见)
经过测试和调查,我能够将问题缩小到在 chrome://blob-internals 中可见的创建的 blob。 就我而言,blob 列表 (chrome://blob-internals) 越来越长,我的 PWA 出现内存问题并最终完全失败。
我设置了一个 jsfiddle 来显示问题。 小提琴:
const app = () => {
let recordingsCount = 0;
let recordedSize = 0;
let recorder;
let mediaStream;
let intervalId;
let numberFormatter = new Intl.NumberFormat('en-US');
let videoTag;
const wakeLock = () => {
if ('wakeLock' in window.navigator) {
window.navigator.wakeLock.request('screen');
}
};
const delay = async (ms) => {
return new Promise((resolve) => setTimeout(resolve,ms,undefined));
};
const updateInfoInUI = () => {
document.getElementById('status').innerText = 'recordings: ' + recordingsCount + ' total recorded size: ' + numberFormatter.format(recordedSize);
};
const getWebCamMediaStream = () => {
const constraints = {
audio: true,video: {
width: {exact: 1280},height: {exact: 720}
}
};
return navigator.mediaDevices.getUserMedia(constraints);
}
const logStream = (stream) => {
var tracks = stream.getTracks();
console.log('stream ID:',stream.id);
for (var i = 0; i < tracks.length; i++) {
console.log("track ID:",tracks[i].id,"track label:",tracks[i].label,"kind:",tracks[i].kind);
}
}
const recordVideoClip = async () => {
console.log("record video clip");
const stopRecorder = () => {
if (!recorder) {
return;
}
try {
if (recorder.state === 'recording') {
recorder.stop();
}
} catch (err) {}
};
const recordedChunks = [];
recorder.ondataavailable = (event) => recordedChunks.push(event.data);
const stopped = new Promise((res,rej) => {
recorder.onstop = res;
recorder.onerror = (event) => rej(event);
});
recorder.start();
const recorded = delay(30000).then(stopRecorder);
await Promise.all([ stopped,recorded ]);
const blob = getBlob(recordedChunks);
console.log("recorded clip size:",blob.size);
recordingsCount++;
recordedSize+= blob.size;
updateInfoInUI();
}
const getBlob = (recordedChunks) => {
if (!recordedChunks || recordedChunks.length === 0) {
return null;
}
let blobMimeType = recordedChunks[0].type;
if (!blobMimeType) {
blobMimeType = 'application/octet-stream';
}
return new Blob(recordedChunks,{ type: blobMimeType });
}
const start = async () => {
console.log('start');
// get a media stream from webcam
mediaStream = await getWebCamMediaStream();
if(!mediaStream){
console.log('no media stream!');
return;
}
videoTag.srcObject = mediaStream;
await videoTag.play();
// log stream info
logStream(mediaStream);
// create media recorder
const mimeType = 'video/webm;codecs=vp8,opus';
const options = { mimeType,videoBitsPerSecond: 7000000,audioBitsPerSecond: 128000 };
recorder = new MediaRecorder(mediaStream,options);
await recordVideoClip();
intervalId = setInterval(recordVideoClip,1000 * 60); // every minute
}
const stop = () => {
if(recorder){
recorder.stop();
console.log('recorder stopped');
}
if(mediaStream){
mediaStream.getTracks().forEach((track) => {
track.stop();
console.log('media stream track stopped');
});
}
if(intervalId){
clearInterval(intervalId);
console.log('interval stopped');
}
recorder = null;
mediaStream = null;
intervalId = null;
recordingsCount = 0;
recordedSize = 0;
videoTag.srcObject = null;
}
const initDomElements = () => {
videoTag = document.getElementById('videoLocal');
document.getElementById('start').addEventListener("click",start.bind(this));
document.getElementById('stop').addEventListener("click",stop.bind(this));
}
initDomElements();
wakeLock();
}
app();
小提琴:https://jsfiddle.net/vryz7sha/
当您启动它时,它将每分钟拍摄 30 秒长的高清视频。可以打开任务管理器查看不断增长的内存消耗 以及显示创建的 blob 永远不会再被删除的 blob 内部列表。
我还尝试为每个录音重新创建 MediaRecorder。但这也无济于事。
我的问题:
- 如何摆脱 MediaRecorder 创建的 blob?
- 我的代码有问题吗?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。