我有一个包含20多个视频文件的文件夹,我需要将它们合并为一个长视频文件。如何在Python中使用FFMPEG实现这一目标?
我知道以下命令
ffmpeg -vcodec copy -isync -i \ "concat:file1.mp4|file2.mp4|...|fileN.mp4" \
outputfile.mp4
但我不想输入20多个文件的所有名称。
答案 0 :(得分:7)
这就是我最终使用的......
find *.mp4 | sed 's:\ :\\\ :g'| sed 's/^/file /' > fl.txt; ffmpeg -f concat -i fl.txt -c copy output.mp4; rm fl.txt
丑陋让我感到痛苦,但似乎工作正常,它处理文件名中的空格。另外,不确定OP为什么要问python - 当一些肮脏的老bash / sed会做伎俩时,不需要使用像python这样可爱的东西! ;)
ps:我知道这是一个古老的帖子,但如果谷歌搜索“ffmpeg concat”把我带到这里,它可能会带来其他可怜的灵魂。请注意,如果您的所有文件都具有相同的设置/编解码器,则上述内容可能会起作用。答案 1 :(得分:3)
可以是单行bash命令:
for f in *.mp4 ; do echo file \'$f\' >> list.txt; done && ffmpeg -f concat -safe 0 -i list.txt -c copy stitched-video.mp4 && rm list.txt
确保所有视频文件的帧大小和音频视频编解码器完全相同。
否则,您可以在连接时将它们转换:
for f in *.mp4 ; do echo file \'$f\' >> list.txt; done && ffmpeg -f concat -safe 0 -i list.txt -s 1280x720 -crf 24 stitched-video.mp4 && rm list.txt
答案 2 :(得分:1)
如果ffmpeg不喜欢* .mp4,你可以代替文件列表来执行此操作;
ls -1 *.mp4 | perl -0pe 's/\n/|/g;s/\|$//g'
但我认为你的示例不是关注specification,所以你可能想要这个:
for F in *.mp4 ; do
ffmpeg -i $F -c copy -bsf:v h264_mp4toannexb -f mpegts $(echo $F | perl -pe 's/mp4$/ts/g');
done
ffmpeg -i "concat:$(ls -1 *.ts | perl -0pe 's/\n/|/g;s/\|$//g')" -c copy -bsf:a aac_adtstoasc outputfile.mp4
也会看到类似的question
答案 3 :(得分:1)
这是Windows批处理文件,用于连接目录中的所有.avi
文件:
for %%f in (*.avi) do (
echo file %%f >> list.txt
)
ffmpeg -f concat -safe 0 -i list.txt -c copy output.avi
del list.txt
请参阅ffmpeg文档中的Concatenate。
答案 4 :(得分:0)
使用此:
cat *.mp4 | ffmpeg -i pipe: -c:a copy -c:v copy all.mp4
答案 5 :(得分:0)
我知道最初的问题是关于Python的,但是当我问起Google时,我就把我带到了这里。实际上我不记得确切的查询了。
首先,文件应具有以下格式:
file 'filename1.mp4'
file 'filename2.mp4'
file 'filename3.mp4'
以此类推。
然后是Java(Mac)解决方案:
public static void joinVideos(String folderPath) throws Exception {
File folderFile = new File(folderPath);
//File[] files = folderFile.listFiles();
//On Mac filter out .DS_Store
File[] files = folderFile.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return !name.equals(".DS_Store");
}
});
StringBuilder fileListBuilder = new StringBuilder();
for (File file : files) {
fileListBuilder.append("file '").append(file.getName()).append("'\n");
}
ReadWriteUtil.writeTxt(fileListBuilder.toString(), folderPath + File.separator + "list.txt");
ProcessBuilder processBuilder = new ProcessBuilder("/usr/local/bin/ffmpeg", "-f", "concat", "-i", "list.txt", "-c", "copy", "output.mp4");
File errorFile = new File(folderPath + File.separator + "error.txt");
processBuilder.redirectError(errorFile);
Process process = processBuilder.directory(new File(folderPath)).start();
int exitCode = process.waitFor();
String error = ReadWriteUtil.readFileAsString(errorFile);
System.out.println("error: " + error);
System.out.println("VideoJoiner Finished with exit code: " + exitCode);
System.out.println("videos joined");
}