Node.js 如何从上传视频的Buffer而非文件路径生成缩略图
完全可以直接基于Buffer或者转成流处理,不需要先写入磁盘生成文件路径,以下是两种成熟的实现方案:
方案1:基于ffmpeg流处理(推荐)
ffmpeg本身支持标准输入输出作为数据来源,不需要依赖本地文件路径,你可以直接把Buffer转成可读流传给ffmpeg处理,处理后直接输出缩略图Buffer,全程不需要落地到磁盘。
前置依赖
- 确保服务器环境已经安装了ffmpeg
- 安装Node.js相关依赖:
npm install fluent-ffmpeg bl
代码实现
const ffmpeg = require('fluent-ffmpeg'); const { Readable } = require('stream'); const BufferList = require('bl'); /** * 从视频Buffer生成指定帧的缩略图 * @param {Buffer} videoBuffer 上传的视频Buffer * @param {Number} frameTime 截取帧的时间点,单位秒,默认取第1秒 * @param {String} size 缩略图分辨率,默认640x360 * @returns {Promise<Buffer>} 缩略图PNG格式Buffer */ function generateThumbnail(videoBuffer, frameTime = 1, size = '640x360') { return new Promise((resolve, reject) => { // 将视频Buffer转为可读流 const videoStream = Readable.from(videoBuffer); const outputBuffer = new BufferList(); ffmpeg(videoStream) // 从指定时间点开始读取 .inputOption('-ss', frameTime.toString()) // 只截取1帧 .outputOption('-vframes', '1') // 指定输出为图片格式 .outputOption('-f', 'image2') // 指定图片编码为png .outputOption('-vcodec', 'png') // 指定缩略图分辨率 .outputOption('-s', size) .on('end', () => resolve(outputBuffer.slice())) .on('error', (err) => reject(err)) // 将输出流写入BufferList收集结果 .pipe(outputBuffer); }); } // 业务调用示例 const thumbnailBuffer = await generateThumbnail(req.file.buffer, 2);
方案2:WASM版FFmpeg(无系统依赖)
如果不想在服务器安装ffmpeg,可以用编译为WebAssembly的ffmpeg版本,完全在Node.js进程内运行,不需要额外系统依赖,缺点是包体积较大,处理大视频性能略低。
前置依赖
npm install @ffmpeg/ffmpeg @ffmpeg/core
注意事项
- 流处理全程在内存中进行,要是上传的视频体积超过服务器内存上限,建议先写入临时文件处理,处理完成后删除临时文件即可
- 截取帧的时间参数需要小于视频总时长,可以通过ffmpeg先读取视频元数据获取时长后再做参数校验,避免截取失败
- 可以根据业务需求调整输出的图片格式、质量等参数,比如将输出编码改为jpeg可以减小缩略图体积
内容的提问来源于stack exchange,提问作者Blumenthaler
相关产品推荐
相关产品推荐

