使用ffmpeg.wasm输出图片组时如何提取生成的文件?
解决ffmpeg.wasm生成批量缩略图无法读取文件的问题
问题背景
开发视频上传功能时,已通过ffmpeg.wasm完成视频编码环节,当前需实现DPlayer播放器要求的100张缩略图雪碧图生成功能。执行生成命令后无法提取文件,报错信息:Uncaught (in promise) Error: ffmpeg.FS('readFile', 'thumbnail%d.png') error. Check if the path exists
问题原因
使用thumbnail%d.png作为输出文件名时,ffmpeg.wasm会生成一系列带序号的独立文件(如thumbnail1.png、thumbnail2.png……),但代码中直接以通配符路径thumbnail%d.png读取文件,该路径并不实际存在,因此触发读取失败。
解决步骤
1. 创建专属输出目录(推荐)
先在ffmpeg文件系统中创建目录存放缩略图,避免文件混乱:
var in_name = "upload.mp4"; var out_dir = "thumbnails"; var out_pattern = `${out_dir}/thumbnail%d.png`; (async () => { await ffmpeg.load(); // 创建输出目录 ffmpeg.FS('mkdir', out_dir); // 写入待处理视频文件 ffmpeg.FS('writeFile', in_name, await fetchFile(original_video_file)); // 执行缩略图生成命令,160秒视频生成100张,即每1.6秒1张 await ffmpeg.run('-i', in_name, '-vf', 'fps=1/(160/100)', out_pattern); })();
2. 遍历读取所有生成的缩略图
生成完成后,通过读取目录列表获取所有缩略图文件,再逐个读取:
// 接上述代码 // 获取目录下所有文件 const files = ffmpeg.FS('readdir', out_dir); // 过滤出png格式的缩略图文件 const thumbnailFiles = files.filter(file => file.endsWith('.png')); // 逐个读取并转为Blob对象 const thumbnails = thumbnailFiles.map(file => { const fileData = ffmpeg.FS('readFile', `${out_dir}/${file}`); return new Blob([fileData.buffer], { type: 'image/png' }); }); console.log(thumbnails);
3. 合成DPlayer所需的雪碧图
DPlayer需要单张雪碧图,可通过Canvas将所有缩略图合成:
// 将Blob转为Image对象 function blobToImage(blob) { return new Promise((resolve) => { const img = new Image(); img.onload = () => resolve(img); img.src = URL.createObjectURL(blob); }); } // 合成雪碧图(按10行10列排列,适配100张图) async function generateSpriteSheet(thumbnails) { const imageElements = await Promise.all(thumbnails.map(blobToImage)); const singleWidth = imageElements[0].width; const singleHeight = imageElements[0].height; const canvas = document.createElement('canvas'); canvas.width = singleWidth * 10; canvas.height = singleHeight * 10; const ctx = canvas.getContext('2d'); imageElements.forEach((img, index) => { const x = (index % 10) * singleWidth; const y = Math.floor(index / 10) * singleHeight; ctx.drawImage(img, x, y); }); // 生成雪碧图Blob canvas.toBlob(blob => { // 此处可处理雪碧图,比如上传或预览 console.log('雪碧图生成完成', blob); }, 'image/png'); } // 调用合成函数 generateSpriteSheet(thumbnails);
注意事项
- 确保使用最新稳定版ffmpeg.wasm,避免版本兼容性问题;
- 若视频时长变动,需动态计算fps参数:
fps=1/(视频总时长/100); - 处理大量图片时需注意浏览器内存占用,避免崩溃。
内容的提问来源于stack exchange,提问作者Jveshi
相关产品推荐
相关产品推荐

