Что означает "Прошлая продолжительность X.XXX слишком большая"?

При кодировании H.264 с использованием ffmpeg я получаю следующие типы предупреждений в массе:

Past duration 0.603386 too large
Past duration 0.614372 too large
Past duration 0.606377 too large

Что они означают? Я не нашел ничего в Интернете или в документации ffmpeg.

Ответ 1

Я получал тысячи этих предупреждений с определенным кодированием. Я уменьшал разрешение 1080p до 480p. В точке редактирования, где было какое-то унылое видео из-за дефекта в лазерном диске источника, эти сообщения начали появляться и затем появлялись, я думаю, для каждого кадра после. Они продолжались, как этот короткий отрывок:

Past duration 0.901115 too large=  535031kB time=00:54:15.06 bitrate=1346.5kbits/s dup=0 drop=19 speed=1.15x    
    Last message repeated 31 times
Past duration 0.901115 too large=  535031kB time=00:54:15.62 bitrate=1346.3kbits/s dup=0 drop=19 speed=1.15x    
    Last message repeated 34 times
Past duration 0.901115 too large=  535031kB time=00:54:16.21 bitrate=1346.0kbits/s dup=0 drop=19 speed=1.15x    
    Last message repeated 36 times
Past duration 0.901115 too large=  535338kB time=00:54:16.83 bitrate=1346.5kbits/s dup=0 drop=19 speed=1.15x    
    Last message repeated 39 times

Первоначальный вызов ffmpeg был следующим:

ffmpeg -i input.mp4 -s 720x480 -c:v libx264 -preset slower -crf 17 -c:a copy -y output.mkv

Следуя рекомендациям, я впервые добавил -framerate 60000/1001 к входу. Это ничего не улучшило. Я сохранил -framerate и добавил -r 60000/1001 к выходу. Это все еще ничего не улучшило. Сохраняя оба, я наконец добавил -async 1 -vsync 1. Это привело к тому, что я получил одно предупреждение, и все. Этот вызов был:

ffmpeg -i input.mp4 -framerate 60000/1001 -s 720x480 -c:v libx264 -preset slower -crf 17 -c:a copy -y output.mkv -r 60000/1001 -async 1 -vsync 1

Единственное отличие, которое я обнаружил в подробном дампе из MediaInfo, заключалось в удалении этой строки, найденной в исходном вызове, но не во втором:

Delay relative to video                  : -33ms

Однако я проверил A/V-синхронизацию около начала файлов и около конца, и между этими двумя файлами не было заметной разницы в синхронизации. Время их работы также было одинаковым, но оно измерялось только с точностью до секунды в VLC. Итак, я проверил количество кадров с помощью ffmpeg следующим образом:

ffmpeg -i output.mkv -map 0:v:0 -c copy -f null -

и ищем "frame = #" в конце вывода.

Оказывается, исходное видео было длиной 375226 кадров, исходный вызов дал 375195 кадров, а второй вызов - 375200. Таким образом, второй вызов с гораздо меньшим количеством предупреждающих сообщений также отбрасывал на 5 кадров меньше.

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

ffmpeg -i input.mp4 -s 720x480 -c:v libx264 -preset slower -crf 17 -c:a copy -y output.mkv -async 1 -vsync 1

И еще один файл впоследствии выдал кучу этих предупреждений даже с флагами синхронизации, но добавив обратно флаги скорости, "исправил" его (выдало только два вместо тысяч предупреждений). Поэтому иногда второй вызов работает, а третий - нет. Для моих непосредственных целей я собираюсь остановиться на втором вызове и надеюсь, что он решит большинство из этих проблем.

Это было все с версией ffmpeg 4.0.

Ответ 2

Один из сопровождающих проекта DVDStyler на SourceForge сказал об этом об этом:

Версии FFMpeg после 15 января 2015 года часто отображают это предупреждение. В нем есть добавлено предупреждение о возможном искажении контроля скорости, в противном случае это не приносит никакого вреда.

Ответ 3

Это предупреждающее сообщение появляется при попытке кодировать источник с высокой частотой кадров на выход с низкой частотой кадров, что означает, что кадры должны быть отброшены.


У меня была эта ошибка, потому что я хотел преобразовать серию изображений в видео:

ffmpeg -i %05d.png -r 24 -c:v libx264 -crf 5 out.mkv

Похоже, проблема в том, что если для входа не задана частота кадров, то предполагается частота кадров 25 кадров в секунду:

Input #0, image2, from 'frames/%04d.bmp':
  Duration: 00:00:15.96, start: 0.000000, bitrate: N/A
    Stream #0:0: Video: bmp, bgra, 920x650, 25 fps, 25 tbr, 25 tbn, 25 tbc

Это также видно по общему количеству закодированных кадров. У меня было 400 изображений, но указанная выше команда кодировала только 384:

frame=  384 fps= 68 q=-1.0 Lsize=   10931kB time=00:00:15.91 bitrate=5626.1kbits/s dup=0 drop=15    
video:10928kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.033807%

Сообщения об ошибках исчезают, если вместо этого установить частоту кадров на выходе. Выходная частота кадров будет автоматически выбрана равной входной. Кроме того, в более новых версиях ffmpeg вы должны остерегаться, поскольку при использовании изображений PNG с опцией -i или, скорее, форматом ввода image2 или v4l2, вы должны использовать -framerate вместо -r, см. документация для опции -r.

ffmpeg -framerate 24 -i %05d.png -c:v libx264 -crf 5 out.mkv

Также можно указать частоту кадров для ввода и вывода отдельно:

ffmpeg -framerate 25 -i %05d.png -r 10 -c:v libx264 -crf 5 out.mkv

В этом случае будет закодировано только 161/400 кадров. Другие промежуточные кадры будут удалены. Также сообщение об ошибке исчезает, я полагаю, чтобы не замедлять ffmpeg путем спама в stdout, смотрите:

Ответ 4

Глядя на исходный код, кажется, что разница между временем представления (pts) во входном потоке отличается от того, что в выходном потоке больше чем фиксированный предел, установленный на 0,6.

Фрагменты из источника:

    delta0 = sync_ipts - ost->sync_opts;
    delta  = delta0 + duration;

...

        if (delta0 < 0 &&
        delta > 0 &&
        format_video_sync != VSYNC_PASSTHROUGH &&
        format_video_sync != VSYNC_DROP) {
        double cor = FFMIN(-delta0, duration);
        if (delta0 < -0.6) {
            av_log(NULL, AV_LOG_WARNING, "Past duration %f too large\n", -delta0);
        } else
            av_log(NULL, AV_LOG_DEBUG, "Cliping frame in rate conversion by %f\n", -delta0);
        sync_ipts += cor;
        duration -= cor;
        delta0 += cor;
    }

Это только быстрый взгляд, поэтому, пожалуйста, не стесняйтесь копать глубже.

Ответ 6

Команда должна быть на самом деле:

ffmpeg -loglevel quiet -i input_file.xyz ...

Для параметра "quiet" нет префикса "-", так как он не является параметром, скорее, это значение для параметра "-loglevel".