我有一个电子程序,可以选择一个风景视频的多个区域,让你在一个肖像画布上重新排列它们。我在建立正确的ffmpeg命令来创建视频时遇到了问题。我有这个有点工作。我可以导出2层,但如果我只有1层或如果我选择了3层或更多层,则无法导出。
选择2个视频区域
layers [
{ top: 0, left: 658, width: 576, height: 1080 },
{ top: 262, left: 0, width: 576, height: 324 }
]
newPositions [
{ top: 0, left: 0, width: 576, height: 1080 },
{ top: 0, left: 0, width: 576, height: 324 }
]
filtergraph [0]crop=576:1080:658:0,scale=576:1080[v0];[0]crop=576:324:0:262,scale=576:324[v1];[v0][v1]overlay=0:0:0:0[out]
No Error export successful
选择1个地区
layers [ { top: 0, left: 650, width: 576, height: 1080 } ]
newPositions [ { top: 0, left: 0, width: 576, height: 1080 } ]
filtergraph [0]crop=576:1080:650:0,scale=576:1080[v0];[v0]overlay=0:0[out]
FFmpeg error: [fc#0 @ 000001dd3b6db0c0] Cannot find a matching stream for unlabeled input pad overlay
Error initializing complex filters: Invalid argument
选择3个视频区域
layers [
{ top: 0, left: 641, width: 576, height: 1080 },
{ top: 250, left: 0, width: 576, height: 324 },
{ top: 756, left: 0, width: 576, height: 324 }
]
newPositions [
{ top: 0, left: 0, width: 576, height: 1080 },
{ top: 0, left: 0, width: 576, height: 324 },
{ top: 756, left: 0, width: 576, height: 324 }
]
filtergraph [0]crop=576:1080:641:0,scale=576:1080[v0];[0]crop=576:324:0:250,scale=576:324[v1];[0]crop=576:324:0:756,scale=576:324[v2];[v0][v1][v2]overlay=0:0:0:0:0:756[out]
FFmpeg error: [AVFilterGraph @ 0000018faf2189c0] More input link labels specified for filter 'overlay' than it has inputs: 3 > 2
[AVFilterGraph @ 0000018faf2189c0] Error linking filters
FFmpeg error: Failed to set value '[0]crop=576:1080:698:0,scale=576:1080[v0];[0]crop=576:324:0:264,scale=576:324[v1];[0]crop=576:324:0:756,scale=576:324[v2];[v0][v1][v2]overlay=0:0:0:0:0:0[out]' for option 'filter_complex': Invalid argument
Error parsing global options: Invalid argument
我不知道如何构造正确的叠加命令。下面是我在我的电子应用程序中使用的js代码。
ipcMain.handle('export-video', async (_event, args) => {
const { videoFile, outputName, layers, newPositions } = args;
const ffmpegPath = path.join(__dirname, 'bin', 'ffmpeg');
const outputDir = checkOutputDir();
// use same video for each layer as input
// crop, scale, and position each layer
// overlay each layer on top of each other
// export video
console.log('layers', layers);
console.log('newPositions', newPositions);
let filtergraph = '';
for (let i = 0; i < layers.length; i++) {
const { top, left, width, height } = layers[i];
const { width: newWidth, height: newHeight } = newPositions[i];
const filter = `[0]crop=${width}:${height}:${left}:${top},scale=${newWidth}:${newHeight}[v${i}];`;
filtergraph += filter;
}
for (let i = 0; i < layers.length; i++) {
const filter = `[v${i}]`;
filtergraph += filter;
}
filtergraph += `overlay=`;
for (let i = 0; i < layers.length; i++) {
const { top: newTop, left: newLeft } = newPositions[i];
const overlay = `${newLeft}:${newTop}:`;
filtergraph += overlay;
}
filtergraph = filtergraph.slice(0, -1); // remove last comma
filtergraph += `[out]`;
console.log('filtergraph', filtergraph);
const ffmpeg = spawn(ffmpegPath, [
'-i', videoFile,
'-filter_complex', filtergraph,
'-map', '[out]',
'-c:v', 'libx264',
'-preset', 'ultrafast',
'-crf', '18',
'-y',
path.join(outputDir, `${outputName}`)
]);
ffmpeg.stdout.on('data', (data) => {
console.log(`FFmpeg output: ${data}`);
});
ffmpeg.stderr.on('data', (data) => {
console.error(`FFmpeg error: ${data}`);
});
ffmpeg.on('close', (code) => {
console.log(`FFmpeg process exited with code ${code}`);
// event.reply('ffmpeg-export-done'); // Notify the renderer process
});
});
任何建议都可能是有帮助的,文档很混乱,谢谢。
编辑我越来越接近这个输出:
layers [
{ top: 0, left: 677, width: 576, height: 1080 },
{ top: 240, left: 0, width: 576, height: 324 }
]
newPositions [
{ top: 0, left: 0, width: 576, height: 1080 },
{ top: 0, left: 0, width: 576, height: 324 }
]
filtergraph [0]crop=576:1080:677:0,scale=576:1080[v0];[0]crop=576:324:0:240,scale=576:324[v1];[0][v0]overlay=0:0[o0];[o0][v1]overlay=0:0[o1]
ipcMain.handle('export-video', async (_event, args) => {
const { videoFile, outputName, layers, newPositions } = args;
const ffmpegPath = path.join(__dirname, 'bin', 'ffmpeg');
const outputDir = checkOutputDir();
// use same video for each layer as input
// crop, scale, and position each layer
// overlay each layer on top of each other
// export video
console.log('layers', layers);
console.log('newPositions', newPositions);
let filtergraph = '';
for (let i = 0; i < layers.length; i++) {
const { top, left, width, height } = layers[i];
const { width: newWidth, height: newHeight } = newPositions[i];
const filter = `[0]crop=${width}:${height}:${left}:${top},scale=${newWidth}:${newHeight}[v${i}];`;
filtergraph += filter;
}
for (let i = 0; i < layers.length; i++) {
if (i === 0) {
filtergraph += `[0][v${i}]overlay=`;
} else {
filtergraph += `[o${i-1}][v${i}]overlay=`;
}
const { top: newTop, left: newLeft } = newPositions[i];
let overlay = '';
if (i !== layers.length - 1) {
overlay = `${newLeft}:${newTop}[o${i}];`;
} else {
overlay = `${newLeft}:${newTop};`;
}
filtergraph += overlay;
}
filtergraph = filtergraph.slice(0, -1); // remove last comma
filtergraph += `[o${layers.length-1}]`;
console.log('filtergraph', filtergraph);
const ffmpeg = spawn(ffmpegPath, [
'-i', videoFile,
'-filter_complex', filtergraph,
'-map', `[o${layers.length-1}]`,
'-c:v', 'libx264',
'-preset', 'ultrafast',
'-crf', '18',
'-y',
path.join(outputDir, `${outputName}`)
]);
ffmpeg.stdout.on('data', (data) => {
console.log(`FFmpeg output: ${data}`);
});
ffmpeg.stderr.on('data', (data) => {
console.error(`FFmpeg error: ${data}`);
});
ffmpeg.on('close', (code) => {
console.log(`FFmpeg process exited with code ${code}`);
// event.reply('ffmpeg-export-done'); // Notify the renderer process
});
});
我现在遇到的问题是,它覆盖了原始输入的区域,并保持了景观尺寸,而不是制作一个肖像视频。
2条答案
按热度按时间2eafrhcq1#
要垂直堆叠多个相同宽度的视频,请使用vstack过滤器。
sq1bmfud2#
想明白了
1区
2个区域
3个或更多地区
导出处理程序