You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过captureStream和MediaRecorder导出高质量Fabric.js Canvas视频

解决Fabric.js Canvas导出视频画质模糊/像素化问题

你遇到的核心问题是MediaRecorder默认采用高压缩编码,加上canvas的渲染尺寸与录制尺寸不匹配,导致导出视频画质损失。以下是针对性的解决方法:

1. 强制设置MediaRecorder高比特率编码参数

MediaRecorder默认的视频比特率极低,直接导致画质被过度压缩。创建MediaRecorder时传入自定义编码配置,提升比特率:

var canvasStatic = document.getElementById('canvas');
const chunks = []; 
const stream = canvasStatic.captureStream(30);

// 自定义编码配置,设置高比特率(数值越高画质越好,文件体积越大)
const recorderOptions = {
  mimeType: 'video/mp4',
  videoBitsPerSecond: 5000000 // 5Mbps,可根据需求调整
};
const rec = new MediaRecorder(stream, recorderOptions); 

rec.ondataavailable = e => chunks.push(e.data);
rec.onstop = e => exportBlob(chunks);
rec.start();
setTimeout(()=>rec.stop(), duration); 

function exportBlob(chunks) {
  let blob = new Blob(chunks, {type: 'video/mp4'});
  const vid = document.createElement('video');
  vid.src = URL.createObjectURL(blob);
  vid.controls = true;
  vid.autoplay = true;
  
  let a = document.createElement('a');
  a.download = 'title.mp4';
  a.href = vid.src;
  a.click(); // 补充触发下载的逻辑
}

2. 确保Canvas渲染尺寸与显示尺寸一致

浏览器中canvas的width/height是实际绘制像素,CSS的width/height是显示尺寸,若两者不匹配(尤其是高清屏),录制时会出现缩放像素化。给canvas设置正确的像素尺寸:

// 适配高清屏的设备像素比
const dpr = window.devicePixelRatio || 1;
const canvas = document.getElementById('canvas');
// 设置canvas实际绘制尺寸为显示尺寸 × 设备像素比
canvas.width = canvas.offsetWidth * dpr;
canvas.height = canvas.offsetHeight * dpr;
// 调整画布上下文的缩放比例
canvas.getContext('2d').scale(dpr, dpr);

// 初始化Fabric.js时开启Retina缩放支持
const fabricCanvas = new fabric.Canvas(canvas, {
  enableRetinaScaling: true
});

3. 优化Fabric.js渲染细节

  • 禁用对象缓存,避免Fabric.js生成低分辨率的缓存对象:
    // 对所有Fabric对象设置
    fabricObject.set('objectCaching', false);
    
  • 导出前关闭状态缓存,确保每一帧都是实时渲染:
    fabricCanvas.statefulCache = false;
    

4. 手动逐帧捕获(极端情况备选)

如果captureStream的画质仍达不到要求,可以尝试手动捕获每一帧canvas内容,再通过第三方库(如whammy、FFmpeg.js)合成视频:

// 示例:手动捕获30fps的帧
const frames = [];
const captureInterval = setInterval(() => {
  const dataUrl = canvasStatic.toDataURL('image/png');
  frames.push(dataUrl);
}, 1000/30);

setTimeout(() => {
  clearInterval(captureInterval);
  // 调用第三方库将frames数组合成视频
}, duration);

内容的提问来源于stack exchange,提问作者DigitalFrame

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 21:32:53