Уже есть вопросы по поводу ускорения видео с помощью FFmpeg, напримерВот этот.
У меня такой вопрос: есть ли способ указать несколько разделов, которые следует ускорить с помощью внешнего CSV.
Мой CSV-файл выглядит так:
start, end
00:00:03.296, 00:00:14.372,
00:00:16.388, 00:00:33.635,
00:00:33.693, 00:00:39.428,
00:00:39.460, 00:00:50.355,
00:00:50.355, 00:01:17.892,
00:01:17.892, 00:01:19.845,
00:01:19.845, 00:01:47.616,
Это точные разделы (один раздел на строку, две временные метки, определяющие начало и конец каждого раздела), которые должны быть ускорены в 10 раз. Остальное должно быть сохранено с исходной скоростью воспроизведения.
Есть какой-либо способ сделать это?
решение1
Мы можем установить желаемую временную метку PTS для каждого видеокадра, используянастройкифильтр с развитым вложенным if
выражением.
Следующий ответ — это просто «доказательство концепции», предполагающее, что у вас есть знания, позволяющие создать более сложное выражение, которое вам нужно, программным путем. Решение предполагает, что входное видео имеет фиксированную частоту кадров, и что просто вычислить входную временную метку из номера входного кадра.
Примечание:
Ускорение частей видео путем установки временных меток создает видео с переменной частотой кадров (VFR), которое может не воспроизводиться должным образом во всех видеоплеерах.
Возможно, лучше создать видео с фиксированной частотой кадров, ускорив все видео в 10 раз, и дублировать каждый кадр 10 раз в частях с исходной частотой.
Обратите внимание, что с помощью скрипта Python, который считывает кадр с помощью OpenCV и записывает с помощью OpenCV (или лучше передает в FFmpeg), дублировать кадры относительно просто.
Предположим, у нас есть следующий входной файл (40 кадров со скоростью 1 кадр/с):
ffmpeg -y -f lavfi -i testsrc=size=192x108:rate=1:duration=40 -c:v libx264 -g 1 input.mp4
Временные метки входного видео:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
Предположим, мы хотим измерить скорость в диапазоне [0, 19] и [30, 39] и получить следующие выходные временные метки:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 21.1, 21.2, 21.3, 21.4, 21.5, 21.6, 21.7, 21.8, 21.9,
Мы можем использовать следующую команду FFmpeg:
ffmpeg -y -r 100 -i input.mp4 -fps_mode:v passthrough -vf "setpts='(if(lt(N,10), N, if(lt(N,20), ((N-10)/10)+10, if(lt(N,30), 11+(N-20), 21+(N-30)/10))))/TB'" -c:v libx264 -g 1 output.mp4
-r 100
используется для установки длительности пакета на 10 мс (короткая длительность пакета обеспечивает более высокое разрешение временных меток).-fps_mode:v passthrough
- передает каждый входной кадр со входа на выход (без дублирования кадров из-за частоты 100 кадров в секунду).-vf "setpts='(if(lt(N,10), N, if(lt(N,20), ((N-10)/10)+10, if(lt(N,30), 11+(N-20), 21+(N-30)/10))))/TB'"
- Используетif
выражения и немного математики для настройки временных меток.
Выражениеif
применяется, если (условие, значение, если истинно, значение, если ложно).
N
— номер входного кадра, отсчет начинается с нуля.
if(lt(N,10), N, ...
устанавливает PTSN
для первых 10 кадров...
/TB
делит на время в секундах по временной базе.-g 1
- Установите размер GOP на 1 для тестирования (удалите его). Это сохраняет сортировку PTS при использовании FFprobe.
Проверка выходных временных меток с помощью FFprobe:
ffprobe -select_streams v:0 -of default=noprint_wrappers=1 -show_entries packet=pts_time output.mp4
Вывод такой, как и ожидалось:
pts_time=0.000000
pts_time=1.000000
pts_time=2.000000
pts_time=3.000000
pts_time=4.000000
pts_time=5.000000
pts_time=6.000000
pts_time=7.000000
pts_time=8.000000
pts_time=9.000000
pts_time=10.000000
pts_time=10.100000
pts_time=10.190000
pts_time=10.300000
pts_time=10.400000
pts_time=10.500000
pts_time=10.600000
pts_time=10.700000
pts_time=10.800000
pts_time=10.900000
pts_time=11.000000
pts_time=12.000000
pts_time=13.000000
pts_time=14.000000
pts_time=15.000000
pts_time=16.000000
pts_time=17.000000
pts_time=18.000000
pts_time=19.000000
pts_time=20.000000
pts_time=21.000000
pts_time=21.100000
pts_time=21.200000
pts_time=21.300000
pts_time=21.400000
pts_time=21.500000
pts_time=21.600000
pts_time=21.700000
pts_time=21.800000
pts_time=21.900000
Анимированный GIF, демонстрирующий результат:
(Создано с помощью ffmpeg -y -i output.mp4 -filter_complex "[0:v]split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -r 1 output.gif
)