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

Electron应用保存desktopCapturer录屏为视频文件时生成空文件问题

嘿,我之前也踩过Electron录屏生成空WebM文件的坑!结合你说的「Blob有内容,但转ArrayBuffer后存出来的文件是0B」这个情况,大概率是文件写入环节的细节没处理到位,我给你梳理几个核心排查点和解决方案:

1. 确保媒体录制的生命周期处理正确

你提到Blob有内容,说明ondataavailable事件确实在收集数据,但要注意:只有调用mediaRecorder.stop()后,onstop事件触发时,所有视频片段才会完整拼接。如果提前写入或者没等onstop就处理数据,很可能拿到的是不完整的内容。

一定要把文件保存的逻辑放在mediaRecorder.onstop回调里,而不是ondataavailable中。

2. ArrayBuffer转Node.js Buffer的关键步骤

Electron主进程里用Node.js的fs模块写文件时,不能直接传入ArrayBuffer,必须转成Node.js原生的Buffer类型。这是很多人忽略的点,直接传ArrayBuffer会导致写入空文件。

转换代码很简单:

const arrayBuffer = await blob.arrayBuffer();
const buffer = Buffer.from(arrayBuffer); // 这一步必不可少!

3. 先确认目标目录存在

如果videos文件夹不存在,fs.writeFile不会自动创建目录,可能静默失败(或者抛出错误但你没捕获),导致看起来生成了文件但实际没写入内容。

提前创建目录的代码:

const videosDir = path.join(app.getAppPath(), 'videos');
if (!fs.existsSync(videosDir)) {
  fs.mkdirSync(videosDir, { recursive: true }); // recursive确保父目录也能创建
}

完整的可运行示例代码

把这些点整合起来,给你一个完整的录屏保存流程:

const { desktopCapturer, app } = require('electron');
const fs = require('fs');
const path = require('path');

async function startScreenRecording() {
  // 获取屏幕源
  const sources = await desktopCapturer.getSources({ types: ['screen'] });
  const stream = await navigator.mediaDevices.getUserMedia({
    audio: false,
    video: {
      mandatory: {
        chromeMediaSource: 'desktop',
        chromeMediaSourceId: sources[0].id,
        minWidth: 1280,
        maxHeight: 720
      }
    }
  });

  // 初始化媒体录制器
  const mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm' });
  const videoChunks = [];

  // 收集视频片段
  mediaRecorder.ondataavailable = (e) => {
    if (e.data.size > 0) {
      videoChunks.push(e.data);
      console.log('收到Blob片段,大小:', e.data.size);
    }
  };

  // 录制结束后处理保存
  mediaRecorder.onstop = async () => {
    const fullBlob = new Blob(videoChunks, { type: 'video/webm' });
    const arrayBuffer = await fullBlob.arrayBuffer();
    
    // 转成Node.js Buffer
    const buffer = Buffer.from(arrayBuffer);

    // 确保目标目录存在
    const videosDir = path.join(app.getAppPath(), 'videos');
    if (!fs.existsSync(videosDir)) {
      fs.mkdirSync(videosDir, { recursive: true });
    }

    // 写入文件
    const savePath = path.join(videosDir, `recording_${Date.now()}.webm`);
    fs.writeFile(savePath, buffer, (err) => {
      if (err) {
        console.error('保存文件失败:', err);
      } else {
        console.log('视频已保存到:', savePath);
      }
    });

    // 释放流资源,避免内存泄漏
    stream.getTracks().forEach(track => track.stop());
  };

  // 开始录制,5秒后自动停止(示例)
  mediaRecorder.start();
  setTimeout(() => mediaRecorder.stop(), 5000);
}

startScreenRecording();

额外排查建议

  • 给fs.writeFile加上错误回调,看看是不是有权限问题或者路径错误;
  • 开发环境和打包后的环境,app.getAppPath()的路径可能不一样,打印出来确认是不是你期望的应用根目录;
  • 如果需要录制音频,记得在getUserMedia里开启audio: true,并且确保MediaRecorder的mimeType支持音频(比如video/webm;codecs=vp8,opus)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:51:52