Редактировать: Добавлен другой метод, который учитывает аудио, а также перезаписанные кадры из-за начального метода, который показан внизу.
ffmpeg -i input.mp4 -filter_complex \
"[0:v]split=4[v0][v1][v2][v3]; \
[v0]trim=start_frame=0:end_frame=1,loop=90:1:0,setpts=N/FRAME_RATE/TB[0v]; \
[v1]trim=start_frame=1:end_frame=301,loop=90:1:299,setpts=N/FRAME_RATE/TB[1v]; \
[v2]trim=start_frame=301:end_frame=601,loop=90:1:299,setpts=N/FRAME_RATE/TB[2v]; \
[v3]trim=start_frame=601:end_frame=900,loop=90:1:298,setpts=N/FRAME_RATE/TB[3v]; \
aevalsrc=0:d=3[0a]; \
[0:a]asplit=3[a1][a2][a3]; \
[a1]atrim=0:10,asetpts=N/SR/TB[1a]; \
[a2]atrim=10:20,asetpts=N/SR/TB[2a]; \
[a3]atrim=20:30,asetpts=N/SR/TB[3a]; \
[0v][0a][1v][1a][2v][2a][3v][3a]concat=n=4:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" outva.mp4
Это может быть сделано, используя последовательный фильтр цикла.
ffmpeg -i input.mp4 \
-vf loop=90:1:0,setpts=N/FRAME_RATE/TB, \
loop=90:1:390,setpts=N/FRAME_RATE/TB, \
loop=90:1:780,setpts=N/FRAME_RATE/TB, \
loop=90:1:1169,setpts=N/FRAME_RATE/TB
stuttered.mp4
Команда выше для видео 30 кадров в секунду. Каждый фильтр петли устанавливает петлю на 90 кадров, то есть на 3 секунды при 30 кадрах в секунду с циклом из 1 кадра, который должен быть зациклен. Третий аргумент - это индекс кадра, который должен быть зациклен. Индекс для всех фильтров цикла после первого должен быть смещен, так как их входной канал содержит вставленные ранее циклы, например, 2-й цикл при 10 секундах обычно будет 300
для видео 30 кадров в секунду, но так как самый первый цикл был зациклен в течение 3 секунд это 3x30 + 10x30 = 390
.
Setpts генерирует монотонный набор новых временных меток после каждого цикла, так как в противном случае команда не будет работать правильно.
Аудио было полностью проигнорировано.