使用fluent-ffmpeg合并视频失败,返回错误码4294967274
解决fluent-ffmpeg合并不同宽高视频报错问题
问题分析
你遇到的错误码4294967274实际对应FFmpeg的-18错误,本质是输入视频参数不匹配导致的。mergeToFile默认使用FFmpeg的concat demuxer,该方式要求所有输入视频的分辨率、编码格式、帧率、音频参数等完全一致,仅裁剪尺寸接近无法满足要求。
解决方案
方案1:使用filter_complex concat滤镜(推荐,支持参数不同的视频)
concat滤镜可以在合并时自动统一视频参数(比如缩放分辨率到一致),无需提前转码。修改代码如下:
const fs = require('fs'); const ffmpeg = require('fluent-ffmpeg'); // 设置FFmpeg路径 ffmpeg.setFfmpegPath('C:\\ProgramData\\chocolatey\\lib\\ffmpeg\\tools\\ffmpeg\\bin\\ffmpeg.exe'); ffmpeg.setFfprobePath('C:\\ProgramData\\chocolatey\\lib\\ffmpeg\\tools\\ffmpeg\\bin\\ffprobe.exe'); fs.readdir('./scaled', (err, filenames) => { if (err) { console.error(err); return; } // 构建输入列表和滤镜参数 const inputs = filenames.map(name => `./scaled/${name}`); const filterParts = []; const inputLabels = []; // 为每个输入分配标签,可指定固定分辨率(比如1920:1080)或统一到第一个视频尺寸 inputs.forEach((_, index) => { const label = `v${index}`; inputLabels.push(label); // 这里用scale=iw:ih保持原尺寸,如需统一固定值替换为scale=1920:1080 filterParts.push(`[${index}:v]scale=iw:ih,setsar=1[${label}]`); }); // 拼接concat滤镜,n表示输入视频数量,v=1/a=1表示合并1路视频音频 filterParts.push(`[${inputLabels.join('][')}]concat=n=${inputs.length}:v=1:a=1[outv][outa]`); const filterString = filterParts.join(';'); // 初始化FFmpeg实例并添加所有输入 const ffmpegInstance = ffmpeg(); inputs.forEach(input => ffmpegInstance.input(input)); // 执行合并 ffmpegInstance .complexFilter(filterString) .outputOptions('-map', '[outv]') .outputOptions('-map', '[outa]') .output('./output/output.mp4') .on('error', (err) => { console.log('Error ' + err.message); }) .on('end', () => { console.log('Finished!'); }) .run(); });
方案2:先统一所有视频参数再合并
如果坚持用mergeToFile,需要先将所有视频转码为完全一致的参数(比如相同分辨率、编码、帧率),再进行合并:
- 编写转码函数:
function transcodeVideo(inputPath, outputPath) { return new Promise((resolve, reject) => { ffmpeg(inputPath) .outputOptions('-c:v', 'libx264') // 统一视频编码为H.264 .outputOptions('-c:a', 'aac') // 统一音频编码为AAC .outputOptions('-s', '1920x1080') // 固定分辨率 .outputOptions('-r', '30') // 固定帧率 .save(outputPath) .on('end', resolve) .on('error', reject); }); }
- 批量转码后合并:
fs.readdir('./scaled', async (err, filenames) => { if (err) { console.error(err); return; } // 确保转码目录存在 if (!fs.existsSync('./transcoded')) { fs.mkdirSync('./transcoded'); } // 批量转码所有视频 const transcodePromises = filenames.map(async (name) => { const input = `./scaled/${name}`; const output = `./transcoded/${name}`; await transcodeVideo(input, output); return output; }); const transcodedFiles = await Promise.all(transcodePromises); // 合并转码后的视频 let mergedVideo = ffmpeg(); transcodedFiles.forEach(file => { mergedVideo = mergedVideo.addInput(file); }); mergedVideo.mergeToFile('./output/output.mp4', './tmp/') .on('error', (err) => { console.log('Error ' + err.message); }) .on('end', () => { console.log('Finished!'); }); });
额外注意事项
- 确保
./tmp/和./output/目录已存在,FFmpeg需要临时目录处理合并过程 - 可单独用FFmpeg命令检查输入视频是否损坏:
ffmpeg -i ./scaled/xxx.mp4 -v error -f null -,若报错则说明原视频文件有问题
内容的提问来源于stack exchange,提问作者munaziri BNM
相关产品推荐
相关产品推荐

