Node.js中使用FFmpeg生成视频截图后无法找到文件的问题求助
问题:fluent-ffmpeg截图日志显示成功但文件不存在
实现代码
const ffmpegPath = require('@ffmpeg-installer/ffmpeg'); import ffmpeg from 'fluent-ffmpeg'; import path from 'path'; const os = require('os'); ffmpeg.setFfmpegPath(ffmpegPath.path); export const generateThumbnailFromVideo = async (mp4Buffer) => { console.log('generateThumbnailFromVideo is triggered'); const timePosition = '00:00:00.500'; const filename = `temp/temp-${new Date().getTime()}.png`; return new Promise((resolve, reject) => { ffmpeg({ source: bufferToStream(mp4Buffer) }) .on('error', (err) => { console.error('An error occurred: ' + err.message); reject(err); }) .on('end', () => { console.log('Thumbnail generated successfully'); fs.readFile(filename, (err, data) => { if (err) { console.error('An error occurred while reading the thumbnail file:', err); reject(err); return; } fs.unlink(filename); uploadBuffer(data, filename, data.length) }) resolve(filename); }) .screenshots({ timestamps: [timePosition], filename: filename, folder: 'temp/', size: '320x240', }); }); }
运行日志
generateThumbnailFromVideo is triggered Thumbnail generated successfully createProjectMedia is triggered userId: 1 projectId: 25 mediaArray: [ { mediaUrl: 'medias/1/1686843801535/medias_1_1684753043519_1_(1)_(4)_(1).mp4', thumbnailUrl: 'medias/1/1686843801535/medias_1_1684753043519_1_(1)_(4)_(1)_thumbnail.jpg', mediaType: 2 } ] An error occurred while reading the thumbnail file: [Error: ENOENT: no such file or directory, open 'temp/temp-1686843802255.png'] { errno: -2, code: 'ENOENT', syscall: 'open', path: 'temp/temp-1686843802255.png' }
问题细节
- 日志打印
Thumbnail generated successfully,但项目根目录的temp文件夹始终为空,找不到生成的png文件 - 尝试用
__dirname和os.tmpdir()设置绝对路径,无效 - 已确认temp目录存在:删除temp会触发目录不存在的错误,重建后该错误消失
- 移除
fs.unlink(filename)语句后,情况依旧
解决方案
1. 修复路径拼接冲突
你在screenshots配置中同时设置了带路径的filename和folder参数,fluent-ffmpeg会自动拼接两个路径,最终生成的文件路径是temp/temp/temp-xxxxxx.png(而非预期的temp/temp-xxxxxx.png),这就是根目录temp为空的原因。
两种修改方式:
方式一:保留folder,filename仅写文件名
const filename = `temp-${new Date().getTime()}.png`; // ... .screenshots({ timestamps: [timePosition], filename: filename, folder: 'temp/', size: '320x240', });
方式二:移除folder,filename写完整路径
const filename = `temp/temp-${new Date().getTime()}.png`; // ... .screenshots({ timestamps: [timePosition], filename: filename, size: '320x240', });
2. 纠正Promise.resolve的时机
当前代码在end事件中先调用resolve(filename),再执行文件读取逻辑,会导致Promise提前完成,后续操作可能中断。需要把resolve移到文件读取成功的回调内:
.on('end', () => { console.log('Thumbnail generated successfully'); fs.readFile(filename, (err, data) => { if (err) { console.error('An error occurred while reading the thumbnail file:', err); reject(err); return; } fs.unlink(filename, (unlinkErr) => { if (unlinkErr) { console.error('Failed to delete temp file:', unlinkErr); } uploadBuffer(data, filename, data.length); resolve(filename); // 移至此处 }); }); })
3. 增加文件生成校验
添加filenames事件监听实际生成的文件路径,方便排查:
.on('filenames', (filenames) => { console.log('实际生成的文件路径:', filenames); })
内容的提问来源于stack exchange,提问作者Terry Windwalker
相关产品推荐
相关产品推荐

