使用MediaRecorder录制Canvas视频后无法通过Blob URL下载问题求助
问题诊断与解决方案
你的代码已成功完成视频录制,但下载行为不符合预期的核心原因是浏览器对可预览媒体类型Blob URL的默认处理逻辑,以及缺少几个关键的属性与操作:
问题根源
- 浏览器会优先预览自身支持的媒体文件(如WebM),即使设置了
download属性,也可能跳过下载直接打开 - 直接调用
link.click()未指定打开方式,导致浏览器在当前窗口替换原页面打开视频,而非触发下载流程 - 未及时释放
ObjectURL,会造成不必要的内存泄漏
修复后的代码
let self = this; this.chunks = []; const canvas2 = document.getElementById("self-canvas"); let recordStream = canvas2.captureStream(1); const options = {mimeType: 'video/webm; codecs=vp9'}; this.recorder = new MediaRecorder(recordStream, options); this.recorder.ondataavailable = function(evt) { self.chunks.push(evt.data); }; this.recorder.onstop = function(evt) { console.log("recorder stopping"); const link = document.createElement('a'); const videoBlob = new Blob(self.chunks, { type: "video/webm" }); console.log("file size: " + videoBlob.size); const url = URL.createObjectURL(videoBlob); link.href = url; link.download = "sample.webm"; // 指定在新标签打开,避免替换当前页面 link.target = "_blank"; // 隐藏链接,避免页面出现多余元素 link.style.display = 'none'; document.body.append(link); // 用模拟用户点击的方式触发下载,兼容更多浏览器安全策略 link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window })); // 下载完成后清理资源,避免内存泄漏 setTimeout(() => { document.body.removeChild(link); URL.revokeObjectURL(url); self.chunks = []; // 清空录制片段缓存 }, 100); }; console.log("finished setting controller") console.log("recorder starting"); this.recorder.start(10000); // the recorder.stop is called somewhere else
关键修改说明
- 添加
link.target = "_blank":强制浏览器在新标签页处理Blob URL,既不会替换原页面,也能配合download属性触发下载 - 使用
MouseEvent模拟点击:部分浏览器对直接调用click()的自动行为有安全限制,模拟用户交互的方式更可靠 - 增加资源清理步骤:下载完成后移除DOM元素、释放
ObjectURL并清空缓存,避免内存占用 - 隐藏链接:避免页面出现不必要的可视元素
额外注意:如果recorder.stop()不是由用户主动交互(如按钮点击)触发,浏览器的安全策略可能会阻止自动下载,这种情况下需要确保停止录制的操作在用户交互上下文内执行。
内容的提问来源于stack exchange,提问作者The Blind Hawk
相关产品推荐
相关产品推荐

