ffmpeg - 视频和音频不同步

ffmpeg - 视频和音频不同步

这似乎是一个常见的问题,但我找到的答案似乎并不适用于我的情况。

我正在将 6 个视频(其中一个是循环播放的短背景)合并为 1 个输出视频,音频和视频略有偏差(可能相差四分之一秒)。这是我的命令行:

ffmpeg -y
-ss 0.2 -i "One.MOV"
-ss 3.2 -i "Two.MOV"
-i "Three.mp4"
-ss 1.9 -i "Four.mp4"
-ss 1.9 -i "Five.MOV"
-stream_loop 180 -i "Background.mp4"
-filter_complex "
   nullsrc=size=1920x1080 [back];
   [5:v] scale=1920x1080 [fred];
   [back][fred] overlay=shortest=1:x=0:y=0 [base];
   [0:v] crop=1312:1080:290:0,scale=576x474 [clip0];
   [0:a]volume=1.7[aud0];
   [1:v] crop=1080:1056:0:864,scale=497x486 [clip1];
   [1:a]volume=4.8,aresample=async=1:first_pts=0[aud1];
   [2:v] scale=576x324 [clip2];
   [2:a]volume=2.0,aresample=async=1:first_pts=0[aud2];
   [3:v] crop=673:720:322:0,scale=454x486 [clip3];
   [3:a]volume=6.9,aresample=async=1:first_pts=0[aud3];
   [4:v] crop=720:921:0:359,scale=380x486 [clip4];
   [4:a]volume=4.9,aresample=async=1:first_pts=0[aud4];
   [base][clip0] overlay=shortest=1:x=32:y=83 [tmp0];
   [tmp0][clip1] overlay=shortest=1:x=711:y=27 [tmp1];
   [tmp1][clip2] overlay=shortest=1:x=1312:y=158 [tmp2];
   [tmp2][clip3] overlay=shortest=1:x=93:y=567 [tmp3];
   [tmp3][clip4] overlay=shortest=1:x=770:y=567 [tmp4];
   [aud0][aud1][aud2][aud3][aud4]amix=inputs=5[a]
" -map "[tmp4]" -map "[a]" -c:v libx264 "Output.mp4"

我猜这与 aresample 和 first_pts 有关,但我一直在阅读文档,却无法弄清楚我需要做些什么不同的事情。

我如何才能使音频和视频同步?

编辑

注:“Three.mp4”为钢琴伴奏;其他曲目均为个人歌手,在钢琴伴奏下加入自己的声音。

答案1

我建议制作一个脚本,以便您可以逐个包含文件,以找出哪个文件有故障。

在新文件夹中创建文件,结构如下:test1.mov test1.ss test1.filterv test1.filtera 等等。

test1.ss 带有“0.2”

test1.filterv 带有“crop=1312:1080:290:0,scale=576x474”

test1.filtera 的“volume=1.7”

ETC...

#!/bin/bash
SUM="$(ls test*.mov test*.mp4 | wc -l)"
echo inputs = $SUM
BOX=1
while [ "$((BOX*BOX))" -lt "$SUM" ]; do ((BOX=BOX+1)); done
echo boxsize = "${BOX}x${BOX}"
WID=640
HEI=360
POX=0
POY=0
INP=()
FCT=-1
FSC=""
FLV=""
FLA=""
AUD=""
BAK="bg"

IFS=$'\n'
for f in $(ls test*.mov test*.mp4); do
  echo $f
  SSI="${f%.*}.ss"
  echo $SSI
  if [[ -f "$SSI" ]]; then
    INP+=("-ss")
    INP+=($(<"${SSI}"))
  fi
  INP+=("-i")
  INP+=("$f")
  ((FCT+=1))

  if [ "$POX" -ge "$BOX" ]; then
    POX=0
    ((POY+=1))
  fi
  ((x=POX*WID))
  ((y=POY*HEI))
  ((POX+=1))

  SSI="${f%.*}.filterv"
  echo $SSI
  if [[ -f "$SSI" ]]; then
    FIL=($(<"${SSI}"))
  else
    FIL=""
  fi

  if [ "$FIL" != "" ]; then
    FSC+="[${FCT}:v:0]${FIL}"
    SC1="${FCT}sca"
    FSC+="[${SC1}]; "
  else
    SC1="${FCT}:v:0"
  fi

  FLV+="[${BAK}][${SC1}]overlay=x=${x}:y=${y}"
  if [ "$FCT" -eq 0 ]; then
    FLV+=":eof_action=endall"
  fi
  BAK="${FCT}v0"
  FLV+="[${BAK}]; "

  SSI="${f%.*}.filtera"
  echo $SSI
  if [[ -f "$SSI" ]]; then
    FIL=$(<"${SSI}")","
  else
    FIL=""
  fi

  FLA+="[${FCT}:a:0]${FIL}aresample=async=1:first_pts=0[${FCT}a0]; "
  AUD+="[${FCT}a0]"
done
((FCT+=1))
((POX=BOX*WID))
((POY=POY*HEI+HEI))
ffmpeg "${INP[@]}" -filter_complex "color=size=${POX}x${POY}[bg]; ${FSC} ${FLV} ${FLA} ${AUD} amix=inputs=${FCT}[a]" -map "[${BAK}]" -map [a] -c:v h264_nvenc -cq 20 -c:a aac -q:a 4 -y output.mkv

逐个添加文件。

答案2

我建议您使用一些具有舒适 GUI 的程序。

这是因为你似乎并不完全确定你的输出何时开始不同步。具有图形界面的程序,例如大胆,应该可以帮助您有效地解决问题。

关于您的具体问题,请注意:您是否考虑过可能存在不同的驱动程序和每秒帧数编码问题?如果这是原因,您很少能排除问题,方法是首先尝试使用相同的音频/视频编码(包括每秒帧数)转换它们,检查同步,然后将它们合并在一起...

相关内容