使用FFMPEG.js转换Base64 PNG帧为MP4时遇输入无效错误求助
FFMPEG.js转换Canvas PNG帧序列为MP4时"Invalid data found"错误的解决方法
问题概述
尝试将Canvas捕获的Base64编码PNG帧序列通过ffmpeg.js转换为MP4时,出现错误:frame0000.png: Invalid data found when processing input。已验证单帧PNG格式正确,但ffmpeg无法识别输入数据。
环境信息
- OS: Ubuntu Linux 21.04 (Hirsute Hippo)
- NPM Version: 9.5.0
- ffmpeg.js Version: ^2.8.9001
- Browser: Chromium 125.0.6422.60 snap
核心错误点及修正方案
1. 无效的MEMFS文件写入逻辑
你循环调用ffmpeg({MEMFS: [file], ...})试图“写入”文件,但ffmpeg.js的每次调用都是独立的沙箱实例,前一次的MEMFS数据不会被保留到下一次调用中。这段代码完全无意义,直接删除即可。
2. 错误的FFMPEG命令构建
当前代码为每个帧单独添加-i参数,这会让ffmpeg将每个PNG视为独立的输入流,而非连续的帧序列。正确的做法是使用通配符语法让ffmpeg自动识别编号连续的帧序列:
修正前错误命令构建:
let command = `-loglevel debug -framerate 30`; inputFiles.forEach((buffer, index) => { command += ` -i frame${index.toString().padStart(4, '0')}.png`; }); command += ` -c:v libx264 -pix_fmt yuv420p ${outputFileName}`;
修正后的命令构建(用数组避免字符串拆分问题):
const command = [ '-loglevel', 'debug', '-framerate', '30', '-i', 'frame%04d.png', // 匹配4位编号的帧文件(frame0000.png ~ frame0024.png) '-c:v', 'libx264', '-pix_fmt', 'yuv420p', outputFileName ];
3. 优化Base64转换的鲁棒性(可选)
虽然你的签名验证通过,但可以对转换函数做小优化,兼容带DataURL前缀和纯Base64两种格式:
#base64ToUint8Array(base64) { // 兼容带DataURL前缀和纯Base64两种格式 const base64Data = base64.includes(',') ? base64.split(',')[1] : base64; const binaryString = atob(base64Data); const bytes = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes; }
修正后的完整执行代码
import ffmpeg from 'ffmpeg.js/ffmpeg-mp4.js'; // 转换帧为MEMFS格式 const inputFiles = videoFrames.map((dataUrl, index) => ({ name: `frame${index.toString().padStart(4, '0')}.png`, data: this.#base64ToUint8Array(dataUrl) })); // 验证PNG签名(保留原有逻辑) inputFiles.forEach(file => { if (!this.#isValidPNG(file.data)) { throw new Error(`Invalid PNG file: ${file.name}`); } }); // 构建正确的FFMPEG命令 const command = [ '-loglevel', 'debug', '-framerate', '30', '-i', 'frame%04d.png', '-c:v', 'libx264', '-pix_fmt', 'yuv420p', outputFileName ]; // 执行转换 const result = ffmpeg({ MEMFS: inputFiles, arguments: command, stdin: () => { }, });
额外检查点
- 确保所有帧文件名严格符合
frame%04d.png格式(你的padStart(4, '0')已经正确实现) - 如果仍有问题,查看ffmpeg的debug日志,确认MEMFS中文件的大小与预期一致,排除数据截断问题
内容的提问来源于stack exchange,提问作者Giles Thompson
相关产品推荐
相关产品推荐

