我收集了一些使用各种不同设备和编解码器录制和编码的视频。我尝试用它们制作一部电影。我认为将它们全部转换为相同格式是个好主意,因此我对所有视频运行以下命令
ffmpeg -i "${input}" -c:v libx264 -c:a aac "${output}"
然后,将文件名放入列表中后,我尝试使用 concat demuxer
ffmpeg -f concat -safe 0 -i list.txt -c copy "${output}"
(我也尝试使用与上述相同的编解码器再次重新编码,但结果是一样的。)
但这个过程会出现很多错误 [1],输出的视频会来回跳动。在找出所有错误的原因之前,有没有更好的方法来合并不同来源、不同年代、不同编解码器、不同一切的不同视频?
[1] 错误很多,例如:
[mp4 @ 0x5588e448ec80] Non-monotonous DTS in output stream 0:1; previous: 1192126, current: 1160221; changing to 1192127. This may result in incorrect timestamps in the output file.
[h264 @ 0x5588e44d0b80] Reference 6 >= 4
[h264 @ 0x5588e44d0b80] error while decoding MB 53 1, bytestream 6271
答案1
#!/bin/bash
WID=1280
HEI=720
# WID="$(ffprobe -v error -show_entries stream=width -of default=noprint_wrappers=1:nokey=1 "$f")"
# HEI="$(ffprobe -v error -show_entries stream=height -of default=noprint_wrappers=1:nokey=1 "$f")"
INP=()
FCT=-1
PAD=""
FIL=""
for f in *.mp4; do
echo $f
INP+=("-i")
INP+=("$f")
((FCT+=1))
s="[${FCT}v0]"
PAD+="[${FCT}:v:0]pad=${WID}:${HEI}:(ow-iw)/2:(oh-ih)/2${s};"
FIL+="${s}[${FCT}:a:0]"
done
((FCT+=1))
ffmpeg -hide_banner "${INP[@]}" -filter_complex "${PAD}${FIL}concat=n=${FCT}:v=1:a=1[v][a]" -map [v] -map [a] -c:v h264_nvenc -cq 23 -c:a aac -y output.mkv
它工作得不太好,需要做很多改进。主要工作是填充黑色空间以使所有视频获得相同的分辨率。
怎么运行的:
- 找到视频的最大宽度和高度,将变量 WID=1280 和 HEI=720 替换为您的分辨率值
- 用你的扩展名或表达式替换 *.mp4
- 更改编解码器
- 在带有视频的目录中运行脚本,脚本将生成字符串,如下所示:
ffmpeg -i "输入 1.mp4" -i "输入 2.mp4" -filter_complex [0:v:0]pad=1280:720:(ow-iw)/2:(oh-ih)/2[0v0];[1:v:0]pad=1280:720:(ow-iw)/2:(oh-ih)/2[1v0];[0v0][0:a:0][1v0][1:a:0]concat=n=2:v=1:a=1[v][a]" -map [v] -map [a] -c:v h264_nvenc -cq 23 -c:a aac -y 输出.mkv
并运行它。过滤序列的每个部分都带有 pad:
[0:v:0]pad=1280:720:(ow-iw)/2:(oh-ih)/2[0v0];
将会填充视频周围的空白区域以对齐分辨率。