Ffmpeg: конкатенация видео и сохранение частоты кадров одинаковой

Вопрос или проблема

У меня есть следующая команда, составленная на данный момент:

ffmpeg -i input.mp4 -filter_complex "\
    [0:v]trim=start=175.2:end=200.9,setpts=PTS-STARTPTS[v1]; \
    [0:a]atrim=start=175.2:end=200.9,asetpts=PTS-STARTPTS[a1]; \
    [0:v]trim=start=214.3:end=324,setpts=PTS-STARTPTS[v2]; \
    [0:a]atrim=start=214.3:end=324,asetpts=PTS-STARTPTS[a2]; \
    [v1][a1][v2][a2]concat=n=2:v=1:a=1[outv][outa]" \
    -map "[outv]" -map "[outa]" output.mp4

Извлечение клипов и объединение их в одно видео работает хорошо. Однако эта команда перекодирует видео в 25fps, о чем свидетельствует предупреждение:

[fc#0 @ 0000029e38732840] [vo0->#0:0 @ 0000029e38739b80] Нет информации о частоте кадров входного потока. Переход на значение по умолчанию 25fps. Используйте опцию -r, если хотите другую частоту кадров.

Я хочу, чтобы она сохраняла частоту кадров оригинального видео, независимо от того, какая она, и не сбрасывала или не вставляла кадры для изменения частоты кадров. Если я использую несколько входных файлов, я хочу, чтобы она просто использовала частоту кадров первого (поскольку они все равно будут одинаковыми).

Как мне это добиться?

Похоже, это ошибка в версии FFmpeg 7.0

Мы можем исправить это, добавив аргумент -fps_mode passthrough.
Согласно документации:

passthrough (0) Каждый кадр передается с его временной меткой от демультиплексора к мультиплексору.


Тестирование:

Создайте синтетический видеофайл 5fps (для тестирования):
ffmpeg -y -f lavfi -i testsrc=size=192x108:rate=5 -f lavfi -i sine=frequency=400 -vcodec libx264 -acodec aac -pix_fmt yuv420p -t 400 input.mp4

Выполняем оригинальную команду с FFmpeg 5.1.2:
ffmpeg -y -i input.mp4 -filter_complex "[0:v]trim=start=175.2:end=200.9,setpts=PTS-STARTPTS[v1];[0:a]atrim=start=175.2:end=200.9,asetpts=PTS-STARTPTS[a1];[0:v]trim=start=214.3:end=324,setpts=PTS-STARTPTS[v2];[0:a]atrim=start=214.3:end=324,asetpts=PTS-STARTPTS[a2];[v1][a1][v2][a2]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output.mp4

С предупреждающим сообщением с FFmpeg 5.1.2 нет.

Проверяем частоту кадров файла output.mp4 с помощью MediaInfo:

Режим частоты кадров                       : Постоянный
Частота кадров                             : 5.000 FPS

Выполняем оригинальную команду с FFmpeg 7.0:
./ffmpeg-7.0-full_build/bin/ffmpeg -y -i input.mp4 -filter_complex "[0:v]trim=start=175.2:end=200.9,setpts=PTS-STARTPTS[v1];[0:a]atrim=start=175.2:end=200.9,asetpts=PTS-STARTPTS[a1];[0:v]trim=start=214.3:end=324,setpts=PTS-STARTPTS[v2];[0:a]atrim=start=214.3:end=324,asetpts=PTS-STARTPTS[a2];[v1][a1][v2][a2]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output.mp4

Существует предупреждающее сообщение “Нет информации о частоте кадров входного потока”.

Проверяем частоту кадров файла output.mp4 с помощью MediaInfo:

Режим частоты кадров                       : Постоянный
Частота кадров                             : 25.000 FPS

FFmpeg 7.0 изменил частоту кадров на 25 fps.


Выполняем обновленную (с -fps_mode passthrough) команду с FFmpeg 7.0:
./ffmpeg-7.0-full_build/bin/ffmpeg -y -i input.mp4 -fps_mode passthrough -filter_complex "[0:v]trim=start=175.2:end=200.9,setpts=PTS-STARTPTS[v1];[0:a]atrim=start=175.2:end=200.9,asetpts=PTS-STARTPTS[a1];[0:v]trim=start=214.3:end=324,setpts=PTS-STARTPTS[v2];[0:a]atrim=start=214.3:end=324,asetpts=PTS-STARTPTS[a2];[v1][a1][v2][a2]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output.mp4

Существует новое предупреждающее сообщение: “MB rate (84000000) > уровень ограничения (16711680)” (другая ошибка?).

Проверяем частоту кадров файла output.mp4 с помощью MediaInfo:

Профиль формата                         : [email protected]
...
Режим частоты кадров                       : Постоянный
Частота кадров                             : 5.000 FPS

Большинство видеоплееров игнорируют “уровень”, но если уровень 6.2 проблематичен, попробуйте использовать другую версию FFmpeg.

Я считаю, что фильтр setpts=PTS-STARTPTS является виновником.

Пример:

ffmpeg \
    -i input.mp4 -filter_complex "\
    [0:v]scale=640x360,trim=start=13:end=14,setpts=PTS-STARTPTS[v1];\
    [0:a]atrim=start=13:end=14,asetpts=PTS-STARTPTS[a1];\
    [0:v]scale=640x360,trim=start=16:end=17,setpts=PTS-STARTPTS[v2];\
    [0:a]atrim=start=16:end=17,asetpts=PTS-STARTPTS[a2];\
    [v1][a1][v2][a2]concat=n=2:v=1:a=1[outv][outa]" \
    -map "[outv]" -map "[outa]" \
    -c:v:0 libsvtav1 output1.mp4

Это приведет к

Svt[error]: Instance 1: Максимально разрешенная частота кадров составляет 240 fps

Это говорит нам о том, что кодировщик не получает информации о fps/pts. Почему она потеряна?
Теперь, если вы пропустите все эти setpts=PTS-STARTPTS и asetpts=PTS-STARTPTS, кодировщик будет работать, но результат будет неаккуратным, не тем, что вы хотите.
Существует обходной путь:

ffmpeg \
    -ss 13 -t 1 -i input.mp4 \
    -ss 16 -t 1 -i input.mp4 \
    -filter_complex "\
    [0:v:0]scale=640x360[v1];\
    [0:a:0]aresample=async=1[a1];\
    [1:v:0]scale=640x360[v2];\
    [1:a:0]aresample=async=1[a2];\
    [v1][a1][v2][a2]concat=n=2:v=1:a=1[outv][outa]" \
    -map "[outv]" -map "[outa]" \
    -c:v:0 libsvtav1 output2.mp4

удваивайте свой ввод, используйте -ss и -t, чтобы обрезать ваш ввод вместо этого
-ss 13 сообщает ffmpeg начать чтение ввода с 00:00:13.
-t 1 сообщает ffmpeg, что продолжительность этого ввода составляет одну секунду.

Использование “-fps_mode passthrough” с libx264, давая предупреждение, работает на моей машине, но libsvtav1 – нет.
И избегание использования фильтра сэкономит много времени и памяти.

Ответ или решение

Как конкатенировать видео с помощью FFmpeg, сохраняя частоту кадров прежнего видео

При использовании FFmpeg для соединения видеороликов возникла ситуация, когда команда, создающая новое видео, переустанавливает частоту кадров в 25 кадров в секунду. Это часто вызвано отсутствием четкой информации о частоте кадров исходного видеофайла. В данной статье мы рассмотрим правильные методы конкатенации видео, сохраняя исходную частоту кадров, а также возможные ошибки и способы их устранения.

Проблема

Как указывалось, при выполнении следующей команды в FFmpeg 7.0 появилась ошибка:

[fc#0 @ 0000029e38732840] [vo0->#0:0 @ 0000029e38739b80] No information about the input framerate is available. Falling back to a default value of 25fps.

Это происходит, потому что FFmpeg не получает информацию о частоте кадров из исходного видеопотока и применяет значение по умолчанию.

Решения

1. Использование флага -fps_mode passthrough

Для решения проблемы с частотой кадров можно воспользоваться флагом -fps_mode passthrough. Этот параметр позволяет сохранить временные метки кадров без изменений.

Вот как будет выглядеть ваша команда с учетом этого флага:

ffmpeg -y -i input.mp4 -fps_mode passthrough -filter_complex "\
    [0:v]trim=start=175.2:end=200.9,setpts=PTS-STARTPTS[v1];\
    [0:a]atrim=start=175.2:end=200.9,asetpts=PTS-STARTPTS[a1];\
    [0:v]trim=start=214.3:end=324,setpts=PTS-STARTPTS[v2];\
    [0:a]atrim=start=214.3:end=324,asetpts=PTS-STARTPTS[a2];\
    [v1][a1][v2][a2]concat=n=2:v=1:a=1[outv][outa]" \
    -map "[outv]" -map "[outa]" output.mp4

2. Избегание изменения PTS

Другим методом решения может быть избегание использования фильтров setpts и asetpts, что может привести к потере информации о частоте кадров. Вместо этого можно использовать -ss и -t, чтобы обрезать видео:

ffmpeg -ss 175.2 -t 25.7 -i input.mp4 -ss 214.3 -t 109.7 -i input.mp4 -filter_complex "\
    [0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[outv][outa]" \
    -map "[outv]" -map "[outa]" output.mp4

Проверка результата

Для проверки частоты кадров выходного файла рекомендуется использовать утилиту MediaInfo. Это позволит убедиться, что частота кадров сохранена корректно. Вы можете выполнить следующую команду:

mediainfo output.mp4

Итог

При конкатенации видео с помощью FFmpeg важно сохранять исходную частоту кадров, чтобы обеспечить качественное воспроизведение без нежелательных артефактов. Использование флага -fps_mode passthrough или правильно сформированные команды с опциями -ss и -t поможет вам добиться необходимого результата. Если после применения данных методов возникнут новые ошибки, возможно, стоит обратиться к другой версии FFmpeg, так как в некоторых версиях могут наблюдаться баги, влияющие на производительность.

Оцените материал
Добавить комментарий

Капча загружается...