我遇到过一种情况,我想将我用相机拍摄的多个视频合并起来。这些视频如下:
Video 1: 10:00 am - 10:10 am (10 min long)
Video 2: 10:30 am - 11:00 am (30 min long)
Video 3: 11:30 am - 11:45 am (15 min long)
本质上,我想将它们组合在一起,这样我就能得到一个 1 小时 45 分钟的视频文件,中间有未录制的空白。这是为了便于音频与单独录制的音轨同步。因此目标视频将是:
0:00 - 0:10 Video 1
0:10 - 0:30 Black screen
0:30 - 1:00 Video 2
1:00 - 1:30 Black screen
1:30 - 1:45 Video 3
我想到的一个方法是提取每个视频的时间戳及其持续时间,计算拼接所需的空白视频的长度,然后使用它concatenate
来合并所有视频。有没有更简单的方法可以直接使用 ffmpeg 来做到这一点?
答案1
脚本:从输入文件中获取修改的时间戳,获取持续时间,创建空白视频,将它们连接起来。
#!/bin/bash
LST=($(ls -1tr video*.mp4))
TOT=${#LST[*]}
f="${LST[0]}"
AGE=$(stat -c %y $f)
SEC=$(date +%s -d"$AGE")
#WID="$(ffprobe -v error -show_entries stream=width -of default=noprint_wrappers=1:nokey=1 "$f" | head -1)"
#HEI="$(ffprobe -v error -show_entries stream=height -of default=noprint_wrappers=1:nokey=1 "$f" | head -1)"
WID=576
HEI=1024
DUR="$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$f")"
DUR="${DUR%.*}"
echo $f $AGE $SEC $DUR "${WID}x${HEI}"
INP=("-i" "$f")
FCT=0
FIL="[0:v][0:a]"
for (( i=1; i<=$(( $TOT -1 )); i++ )); do
f="${LST[$i]}"
AGE=$(stat -c %y $f)
TIM=$(date +%s -d"$AGE")
((OFS=TIM-SEC-DUR))
SEC=$TIM
BLA="/tmp/blank${i}.mkv"
ffmpeg -hide_banner -f lavfi -i "color=s=${WID}x${HEI}" -f lavfi -i anullsrc=r=48000 -c:v h264_nvenc -cq 20 -c:a aac -b:a 156k -t "$OFS" -y "$BLA"
DUR="$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$f")"
DUR="${DUR%.*}"
echo $f $AGE $TIM $DUR
((FCT+=1))
INP+=("-i" "$BLA")
FIL+="[${FCT}:v][${FCT}:a]"
((FCT+=1))
INP+=("-i" "$f")
FIL+="[${FCT}:v][${FCT}:a]"
done
((FCT+=1))
ffmpeg -hide_banner "${INP[@]}" -filter_complex "
${FIL}concat=n=${FCT}:v=1:a=1[v][a]
" -map [v] -map [a] -c:v h264_nvenc -cq 23 -c:a aac -q:a 4 -y /tmp/output.mkv
vlc /tmp/output.mkv