FFmpeg:一起使用xfade和crossfade时音频不同步

时间:2020-11-05 11:36:19

标签: javascript node.js ffmpeg fluent-ffmpeg

在同时使用xfade和crossfade将12个视频连接在一起并保留音频时,我遇到了问题。当我忽略音频流并仅应用xfade过滤器时,视频编码就很好。否则过渡会挂起,并且音频会提早开始播放。

这是我的filter_complex:

[0:v][1:v]xfade=transition=pixelize:duration=0.5:offset=3.042[V1];
[0:a][1:a]acrossfade=d=0.5[A1];
[V1][2:v]xfade=transition=pixelize:duration=0.5:offset=6.084[V2];
[A1][2:a]acrossfade=d=0.5[A2];
[V2][3:v]xfade=transition=pixelize:duration=0.5:offset=9.108[V3];
[A2][3:a]acrossfade=d=0.5[A3];
[V3][4:v]xfade=transition=pixelize:duration=0.5:offset=23.619[V4];
[A3][4:a]acrossfade=d=0.5[A4];
[V4][5:v]xfade=transition=pixelize:duration=0.5:offset=38.13[V5];
[A4][5:a]acrossfade=d=0.5[A5];
[V5][6:v]xfade=transition=pixelize:duration=0.5:offset=52.641[V6];
[A5][6:a]acrossfade=d=0.5[A6];
[V6][7:v]xfade=transition=pixelize:duration=0.5:offset=67.152[V7];
[A6][7:a]acrossfade=d=0.5[A7];
[V7][8:v]xfade=transition=pixelize:duration=0.5:offset=70.176[V8];
[A7][8:a]acrossfade=d=0.5[A8];
[V8][9:v]xfade=transition=pixelize:duration=0.5:offset=84.687[V9];
[A8][9:a]acrossfade=d=0.5[A9];
[V9][10:v]xfade=transition=pixelize:duration=0.5:offset=99.198[V10];
[A9][10:a]acrossfade=d=0.5[A10];
[V10][11:v]xfade=transition=pixelize:duration=0.5:offset=113.709[video];
[A10][11:a]acrossfade=d=0.5[audio];  

转换持续时间为0.5秒,输入长度从ffprobe读取(格式持续时间):

0: 3.542
1: 3.542
2: 3.524
3: 15.011
4: 15.011
5: 15.011
6: 15.011
7: 3.524
8: 15.011
9: 15.011
10: 15.011
11: 15.011

据我了解,xfade滤镜的偏移量应该是视频时长加上之前的偏移量减去过渡时长,对吗?那么这里出了什么问题?

        3.542 - 0.5 = 3.042
3.042 + 3.542 - 0.5 = 6.084
6.084 + 3.524 - 0.5 = 9.108
...

1 个答案:

答案 0 :(得分:1)

尝试下一个变体:

#!/bin/bash
ffmpeg -hide_banner -i "test01.mkv" -i "test02.mkv" -i "test03.mkv" -filter_complex "
[0:v][1:v]xfade=transition=pixelize:duration=0.5:offset=3.042[1v];
[1v][2:v]xfade=transition=pixelize:duration=0.5:offset=6.084[2v];

[0:a]atrim=0:3.542[0a];
[1:a]atrim=0:3.542[1a];
[2:a]apad,atrim=0:3.524[2a];

[0a][1a]acrossfade=d=0.5[01a];
[01a][2a]acrossfade=d=0.5[02a]
" -map [2v] -map [02a] -c:v h264_nvenc -cq 23 -c:a aac -q:a 4 -y output.mkv

也许,需要减少对齐视频和音频的时间。

[更新1]添加了apad(感谢Gyan)

太懒了,无法手动完成:

#!/bin/bash
LST=($(ls -1 test*.mkv))
TOT=${#LST[*]}
f="${LST[0]}"
DUR="$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$f")"
INP=("-i" "$f")

PDV="[0:v]"
PDC="[0a]"
FLA="[0:a]aresample=async=1,apad,atrim=0:${DUR}${PDC};"

OFS=$(echo $DUR -0.5 | bc -l)
echo $f $DUR $OFS

for (( i=1; i<=$(( $TOT -2 )); i++ )); do
  f="${LST[$i]}"
  INP+=("-i" "$f")
  DUR="$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$f")"

  FLV+="${PDV}[${i}:v]xfade=transition=pixelize:duration=0.5:offset=${OFS}"
  PDV="[${i}v]"
  FLV+="${PDV};"

  PDA="[${i}a]"
  FLA+="[${i}:a]aresample=async=1,apad,atrim=0:${DUR}${PDA};"

  FLC+="${PDC}[${i}a]acrossfade=d=0.5"
  PDC="[0${i}a]"
  FLC+="${PDC};"

  OFS=$(echo $OFS + $DUR -0.5 | bc -l)
  echo $f $DUR $OFS
done

f="${LST[-1]}"
INP+=("-i" "$f")
DUR="$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$f")"

FLV+="${PDV}[${i}:v]xfade=transition=pixelize:duration=0.5:offset=${OFS}"
PDV="[${i}v]"
FLV+="${PDV};"

PDA="[${i}a]"
FLA+="[${i}:a]aresample=async=1,apad,atrim=0:${DUR}${PDA};"

FLC+="${PDC}[${i}a]acrossfade=d=0.5"
PDC="[0${i}a]"
FLC+="${PDC}"

echo $f $DUR
echo $FLV
echo $FLA
echo $FLC
echo ""
ffmpeg "${INP[@]}" -filter_complex "$FLV $FLA $FLC" -map $PDV -map $PDC -c:v h264_nvenc -cq 20 -c:a aac -q:a 4 -y output.mp4 -hide_banner

[更新2]添加了aresample=async=1

[更新3]只是代码优化

相关问题