Electron主进程如何用async正确搭配execFile与fs.readFile处理ffmpeg视频裁剪读取(遇ENOENT报错)
主进程async调用ffmpeg裁剪视频报ENOENT的解决方案
核心问题根因
你当前的代码混用了回调式异步API和Promise/async语法,最直接的触发点是:
execFile默认是回调驱动的异步API,没有被async/await捕获等待,代码刚启动ffmpeg进程,还没等裁剪文件生成,就直接执行fs.readFile去读还不存在的文件,自然报ENOENT。- 引入
fs.promises后,对应的文件操作方法都是Promise版本,不需要传回调,硬塞回调会导致逻辑异常。 ipcMain.on的回调签名错误,实际第一个参数是事件对象,第二个才是renderer传的业务数据,之前的参数接收逻辑会拿不到正确的buffer。- 临时目录删除操作没有await,会导致流程未完成就提前清理文件。
修正后的可运行代码
const fs = require('fs').promises const path = require('path') const os = require('os') const util = require('util') const { execFile } = require('child_process') // 将回调式execFile转为Promise版本,支持await const execFileAsync = util.promisify(execFile) ipcMain.on("capture:buffer", async (event, video_object) => { const {x_pos, y_pos, window_width, window_height, buffer} = video_object const dir = await fs.mkdtemp(path.join(await fs.realpath(os.tmpdir()), path.sep)) const capturedVideoPath = path.join(dir, "screen_capture_video.mp4") const croppedVideoPath = path.join(dir, "cropped_video.mp4") try { // 写入原始录制buffer,Promise版本直接await,不需要传回调 await fs.writeFile(capturedVideoPath, buffer) console.log("Screen Capture File written") // 等待ffmpeg裁剪执行完成,再走后续读文件逻辑 await execFileAsync(ffmpeg.path, [ '-i', capturedVideoPath, '-vf', `crop=${window_width}:${window_height}:${x_pos}:${y_pos}`, croppedVideoPath ]) console.log("Cropped File created") // 读取裁剪后的视频为base64,直接await返回结果 const base64Buffer = await fs.readFile(croppedVideoPath, 'base64') mainWindow.webContents.send("main:video_buffer", Buffer.from(base64Buffer)) } catch (error) { console.log(error) } finally { // 等待临时目录删除完成,避免文件占用问题 await fs.rm(dir, {recursive: true, force: true}) } })
关键调整点
- 移除所有fs Promise方法的回调参数,纯靠async/await处理流程顺序
- 用
util.promisify包装execFile,确保ffmpeg裁剪完成后才会执行后续读文件操作 - 修正ipcMain的回调参数接收逻辑,正确获取renderer传来的视频buffer
- 用
fs.rm替代旧的fs.rmdir处理递归删除,避免Node新版本的废弃警告,同时加force参数避免目录非空时报错
内容的提问来源于stack exchange,提问作者Radespy
相关产品推荐
相关产品推荐

