ffmpeg 使用连接过滤器剪切视频片段时会产生不同步且有故障的音频

ffmpeg 使用连接过滤器剪切视频片段时会产生不同步且有故障的音频

我创建了一个人工测试案例,其中我希望将红色 + 中间 C、绿色 + 中间 D 和蓝色 + 中间 E 各持续 2.5 秒,缩短为各持续 1.5 秒。这是我的真实视频文件的简化版本,我无法分享。

ffmpeg 版本信息:

ffmpeg version 6.1.1 Copyright (c) 2000-2023 the FFmpeg developers
built with Apple clang version 15.0.0 (clang-1500.1.0.2.5)
configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/6.1.1_2 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags='-Wl,-ld_classic' --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopenvino --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon
libavutil      58. 29.100 / 58. 29.100
libavcodec     60. 31.102 / 60. 31.102
libavformat    60. 16.100 / 60. 16.100
libavdevice    60.  3.100 / 60.  3.100
libavfilter     9. 12.100 /  9. 12.100
libswscale      7.  5.100 /  7.  5.100
libswresample   4. 12.100 /  4. 12.100
libpostproc    57.  3.100 / 57.  3.100

此 bash 脚本在 MacOS 上执行所有必要的步骤:

#!/bin/bash

# generate red, green, blue video
rm -f r.mkv g.mkv b.mkv colors.mkv
ffmpeg -f lavfi -i "color=red:1920x1080:duration=2.5,format=rgb24" r.mkv
ffmpeg -f lavfi -i "color=green:1920x1080:duration=2.5,format=rgb24" g.mkv
ffmpeg -f lavfi -i "color=blue:1920x1080:duration=2.5,format=rgb24" b.mkv
ffmpeg -i r.mkv -i g.mkv -i b.mkv -filter_complex '[0:0][1:0][2:0]concat=n=3:v=1:a=0[out]' -map '[out]' colors.mkv

# re-encode with h264
rm -f video.mkv
ffmpeg -i colors.mkv -framerate 24 -c:v libx264 -profile:v high -pix_fmt yuv420p -crf 22 -an video.mkv

# generate C, D, E audio
rm -f c.wav d.wav e.wav audio.wav
ffmpeg -f lavfi -i "sine=frequency=261.63:sample_rate=48000:duration=2.5" -c:a pcm_s16le c.wav
ffmpeg -f lavfi -i "sine=frequency=293.66:sample_rate=48000:duration=2.5" -c:a pcm_s16le d.wav
ffmpeg -f lavfi -i "sine=frequency=329.63:sample_rate=48000:duration=2.5" -c:a pcm_s16le e.wav
ffmpeg -i c.wav -i d.wav -i e.wav -filter_complex '[0:0][1:0][2:0]concat=n=3:v=0:a=1[out]' -map '[out]' audio.wav

# re-encode to AAC
rm -f audio.mkv
ffmpeg -i audio.wav -c:a aac -b:a 384k audio.mkv

# combine audio + video
rm -f rgb.mkv
ffmpeg -i video.mkv -i audio.mkv -map 0:v:0 -map 1:a:0 -c copy rgb.mkv

# cut each segment to 1.5 seconds
rm -f concat.txt
echo "file rgb.mkv" >> concat.txt
echo "inpoint 00:00:00.000" >> concat.txt
echo "outpoint 00:00:01.500" >> concat.txt
echo "file rgb.mkv" >> concat.txt
echo "inpoint 00:00:02.500" >> concat.txt
echo "outpoint 00:00:04.000" >> concat.txt
echo "file rgb.mkv" >> concat.txt
echo "inpoint 00:00:05.000" >> concat.txt
echo "outpoint 00:00:06.500" >> concat.txt

rm -f rgb_cut.mkv
ffmpeg -f concat -safe 0 -i concat.txt -c copy rgb_cut.mkv

# try re-encoding while cutting
rm -f rgb_cut_re-encode.mkv
ffmpeg -f concat -safe 0 -i concat.txt -c:v libx264 -profile:v high -pix_fmt yuv420p -crf 22 -c:a aac -b:a 384k rgb_cut_re-encode.mkv

rgb.mkv 按预期生成,但 rgb_cut.mkv 和 rgb_cut_re-encode.mkv 的音频不同步且有故障,甚至在第一次剪辑之前就存在。 如何使用 ffmpeg 连接现有视频中的各种剪辑而不会出现这些问题?

答案1

更新:我从来不喜欢用“奇数”输入进行编码。半秒或分辨率WxH。我使用图像进行视频。生成很好,但使用3而不是2.5

我知道-framerate 1/3加上去-r 30正好是3秒。

#!/bin/bash

make_video() {
wget -O red.png "https://htmlcolorcodes.com/assets/images/colors/red-color-solid-background-1920x1080.png"
wget -O green.png "https://htmlcolorcodes.com/assets/images/colors/green-color-solid-background-1920x1080.png"
wget -O blue.png "https://htmlcolorcodes.com/assets/images/colors/blue-color-solid-background-1920x1080.png"

ffmpeg -hide_banner -framerate 1/3 -i red.png -pix_fmt yuv420p -c:v libx264 -r 30 -crf 22 -avoid_negative_ts make_zero red.mkv
ffmpeg -hide_banner -framerate 1/3 -i green.png -pix_fmt yuv420p -c:v libx264 -r 30 -crf 22 -avoid_negative_ts make_zero green.mkv
ffmpeg -hide_banner -framerate 1/3 -i blue.png -pix_fmt yuv420p -c:v libx264 -r 30 -crf 22 -avoid_negative_ts make_zero blue.mkv

ffmpeg -hide_banner -i red.mkv -to 00:00:01.500 -c copy r.mkv
ffmpeg -hide_banner -i green.mkv -to 00:00:01.500 -c copy g.mkv
ffmpeg -hide_banner -i blue.mkv -to 00:00:01.500 -c copy b.mkv

rm red.mkv green.mkv blue.mkv red.png green.png blue.png
}

make_audio() {
ffmpeg -f lavfi -i "sine=frequency=261.63:sample_rate=48000:duration=3" -c:a aac -b:a 384k -ar 48000 c-3s.aac
ffmpeg -f lavfi -i "sine=frequency=293.66:sample_rate=48000:duration=3" -c:a aac -b:a 384k -ar 48000 d-3s.aac
ffmpeg -f lavfi -i "sine=frequency=329.63:sample_rate=48000:duration=3" -c:a aac -b:a 384k -ar 48000 e-3s.aac

ffmpeg -hide_banner -i c-3s.aac -to 00:00:01.500 -c copy c.aac
ffmpeg -hide_banner -i d-3s.aac -to 00:00:01.500 -c copy d.aac
ffmpeg -hide_banner -i e-3s.aac -to 00:00:01.500 -c copy e.aac

rm c-3s.aac d-3s.aac e-3s.aac
}

make_video
make_audio

ffmpeg -hide_banner -i r.mkv -i c.aac -pix_fmt yuv420p -c:v libx264 -crf 22 -avoid_negative_ts auto -c:a copy -shortest mux_c_r.mkv
ffmpeg -hide_banner -i g.mkv -i d.aac -pix_fmt yuv420p -c:v libx264 -crf 22 -avoid_negative_ts auto -c:a copy -shortest mux_d_g.mkv
ffmpeg -hide_banner -i b.mkv -i e.aac -pix_fmt yuv420p -c:v libx264 -crf 22 -avoid_negative_ts auto -c:a copy -shortest mux_e_b.mkv

rm {r,g,b}.mkv {c,d,e}.aac

ls --quoting-style=shell-always -1v mux_*.mkv > tmp.txt
sed 's/^/file /' tmp.txt > list.txt && rm tmp.txt

ffmpeg -hide_banner -f concat -safe 0 -i list.txt -c copy rgb_complete.mkv

rm mux_*.mkv list.txt

exit 0

这会产生您想要的输出吗?

相关内容