Как правильно исправить ключевые кадры в FFmpeg для DASH?

39

При подготовке потока для воспроизведения DASH точки произвольного доступа должны быть в одно и то же время исходного потока во всех потоках. Обычный способ сделать это - принудительно установить фиксированную частоту кадров и фиксированную длину GOP (то есть ключевой кадр каждые N кадров).

В FFmpeg фиксированная частота кадров проста (-r НОМЕР).

Но для фиксированных местоположений ключевых кадров (длина GOP) есть три метода ... какой из них "правильный"? Документация FFmpeg разочаровывающе расплывчата по этому вопросу.

Способ 1: возиться с аргументами libx264

-c:v libx264 -x264opts keyint=GOPSIZE:min-keyint=GOPSIZE:scenecut=-1

Кажется, что есть некоторые споры, следует ли отключить сценарное отключение или нет, так как неясно, перезапускается ли «счетчик» ключевого кадра, когда происходит вырезка сцены.

Способ 2: установка фиксированного размера GOP:

-g GOP_LEN_IN_FRAMES

К сожалению, это только задокументировано в документации FFMPEG, и, следовательно, эффект этого аргумента очень неясен.

Способ 3: вставлять ключевой кадр каждые N секунд ( может быть? ):

-force_key_frames expr:gte(t,n_forced*GOP_LEN_IN_SECONDS)

Это является явным образом задокументировано. Но до сих пор неясно, перезапускается ли «счетчик времени» после каждого ключевого кадра. Например, в ожидаемой 5-секундной GOP, если scenecutключевой кадр введен через 3 секунды с помощью libx264, будет ли следующий ключевой кадр спустя 5 секунд или через 2 секунды?

Фактически, документация FFmpeg различает эту -gопцию и опцию, но на самом деле это не говорит о том, как эти две опции выше всего отличаются друг от друга (очевидно, -gдля этого потребуется фиксированная частота кадров).

Какой правильный?

Казалось бы, что -force_key_framesбудет лучше , так как это не потребует фиксированной частоты кадров. Однако для этого необходимо, чтобы

  • соответствует спецификации GOP в H.264 ( если есть )
  • он ГАРАНТИРУЕТ, что в фиксированной каденции будет ключевой кадр, независимо от ключевых scenecutкадров libx264 .

Также может показаться, что это -gне может работать без принудительной установки фиксированной частоты кадров ( -r) , поскольку нет гарантии, что несколько прогонов ffmpegс разными аргументами кодека обеспечат одинаковую мгновенную частоту кадров в каждом разрешении. Фиксированная частота кадров может снизить производительность сжатия (ВАЖНО в сценарии DASH!).

Наконец, метод только кажется , как взломать . Я надеюсь против надежды, что это не правильный ответ.keyint

Ссылки:

Пример использования -force_key_framesметода

Пример использования keyintметода

Раздел расширенных опций видео FFmpeg

Марк Геролиматос
источник

Ответы:

28

TL; DR

Я бы порекомендовал следующее:

  • libx264: (и при желании добавить )-g X -keyint_min X-force_key_frames "expr:gte(t,n_forced*N)"
  • libx265: -x265-params "keyint=X:min-keyint=X"
  • libvpx-vp9: -g X

где Xинтервал в кадрах и Nинтервал в секундах. Например, для 2-секундного интервала с видео 30 кадров в секунду X= 60 и N= 2.

Примечание о различных типах кадров

Чтобы правильно объяснить эту тему, мы сначала должны определить два типа I-кадров / ключевых кадров:

  • Кадры мгновенного обновления декодера (IDR): позволяют независимое декодирование следующих кадров без доступа к кадрам, предшествующим кадру IDR.
  • Не-IDR-кадры: для работы декодирования требуется предыдущий IDR-кадр. Кадры без IDR могут использоваться для вырезок сцены в середине GOP (группы изображений).

Что рекомендуется для потоковой передачи?

Для случая потоковой передачи вы хотите:

  • Убедитесь, что все кадры IDR находятся в обычных положениях (например, через 2, 4, 6, ... секунд), чтобы видео можно было разделить на сегменты одинаковой длины.
  • Включите обнаружение перехода сцены, чтобы улучшить эффективность / качество кодирования. Это означает, что I-кадры можно размещать между кадрами IDR. Вы все еще можете работать с отключенным определением обрыва сцены (но это все еще часть многих руководств), но это не обязательно.

Что делают параметры?

Чтобы настроить кодировщик, мы должны понять, что делают параметры ключевого кадра. Я сделал несколько тестов и обнаружил следующее, для трех датчиков libx264, libx265и libvpx-vp9в FFmpeg:

  • libx264:

    • -g устанавливает интервал ключевых кадров.
    • -keyint_min устанавливает минимальный интервал ключевых кадров.
    • -x264-params "keyint=x:min-keyint=y"так же, как -g x -keyint_min y.
    • Примечание. При установке обоих значений на одно и то же минимальное значение внутренне устанавливается равным половине максимального интервала плюс один, как показано в x264коде:

      h->param.i_keyint_min = x264_clip3( h->param.i_keyint_min, 1, h->param.i_keyint_max/2+1 );
      
  • libx265:

    • -g не реализовано.
    • -x265-params "keyint=x:min-keyint=y" работает.
  • libvpx-vp9:

    • -g устанавливает интервал ключевых кадров.
    • -keyint_min устанавливает минимальный интервал ключевых кадров
    • Примечание: из-за того, как работает FFmpeg, -keyint_minон передается кодеру только тогда, когда он совпадает с -g. В коде из libvpxenc.cFFmpeg мы можем найти:

      if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size)
          enccfg.kf_min_dist = avctx->keyint_min;
      if (avctx->gop_size >= 0)
          enccfg.kf_max_dist = avctx->gop_size;
      

      Это может быть ошибкой (или отсутствием функции?), Так как libvpxопределенно поддерживает установку другого значения для kf_min_dist.

Вы должны использовать -force_key_frames?

-force_key_framesПараметр принудительно вводит ключевые кадры на заданном интервале (выражение). Это работает для всех кодировщиков, но может нарушить механизм управления скоростью. Специально для VP9 я заметил серьезные колебания качества, поэтому не могу рекомендовать его в этом случае.

slhck
источник
Спасибо! Это отличная обратная связь. У меня один вопрос: как вы создали эту потрясающую таблицу? Я мог бы полностью использовать что-то подобное.
Марк Геролиматос
(Кажется, нет никакого способа написать вам напрямую) Не могли бы вы указать мне ссылки на какие-либо темы в этом обсуждении в МСЭ-Т? Благодарность!
Марк Геролиматос
2
Я только что сделал это в Excel, вставив выходные данные, которые я получил из трех прогонов ffprobe -i input.mp4 -select_streams v -show_frames -of csv -show_entries frame=pict_type, затем раскрасив ячейки. Боюсь, что нет публичных обсуждений, но я посмотрю, смогу ли я найти некоторые ссылки, которые я нашел тогда.
slhck
Не могли бы вы повторить эксперимент с -force_key_frames expr:gte(t,n_forced*GOP_LEN_IN_SECONDS)формой? Я только попробовал это и обнаружил, что, хотя в потоке были дополнительные I-кадры, он, похоже, соблюдал мое правило. Программа PERL будет следовать за «ответом», поскольку вы, очевидно, не можете использовать разметку в комментариях.
Марк Джеролиматос
Интересный. Я считаю, что стоит отдельный «реальный» ответ, если вы узнали, что это работает. (Сайты Stack Exchange не очень подходят для этого ответа в стиле обсуждения.) В прошлый раз, когда я проверял, -force_key_framesу меня ничего не получалось, и поэтому я больше никогда не пробовал. Это было больше года назад. Возможно, это была ошибка. Я попробую еще раз скоро.
slhck
12

Вот мои пятьдесят центов за дело.

Способ 1:

возиться с аргументами libx264

-c: v libx264 -x264opts keyint = GOPSIZE: min-keyint = GOPSIZE: scenecut = -1

Генерируйте фреймы только с желаемыми интервалами.

Пример 1:

ffmpeg -i test.mp4 -codec:v libx264 \
-r 23.976 \
-x264opts "keyint=48:min-keyint=48:no-scenecut" \
-c:a copy \
-y test_keyint_48.mp4

Создайте фреймы, как и ожидалось, вот так:

Iframes     Seconds
1           0
49          2
97          4
145         6
193         8
241         10
289         12
337         14
385         16
433         18
481         20
529         22
577         24
625         26
673         28
721         30
769         32
817         34
865         36
913         38
961         40
1009        42
1057        44
1105        46
1153        48
1201        50
1249        52
1297        54
1345        56
1393        58

Способ 2 амортизируется. Пропущены.

Способ 3:

вставлять ключевой кадр каждые N секунд (МОЖЕТ БЫТЬ):

-force_key_frames expr: gte (t, n_forced * GOP_LEN_IN_SECONDS)

Пример 2

ffmpeg -i test.mp4 -codec:v libx264 \
-r 23.976 \
-force_key_frames "expr:gte(t,n_forced*2)"
-c:a copy \
-y test_fkf_2.mp4

Создайте iframes немного по-другому:

Iframes     Seconds
1           0
49          2
97          4
145         6
193         8
241         10
289         12
337         14
385         16
433         18
481         20
519         21.58333333
529         22
577         24
625         26
673         28
721         30
769         32
817         34
865         36
913         38
931         38.75
941         39.16666667
961         40
1008        42
1056        44
1104        46
1152        48
1200        50
1248        52
1296        54
1305        54.375
1344        56
1367        56.95833333
1392        58
1430        59.58333333
1440        60
1475        61.45833333
1488        62
1536        64
1544        64.33333333
1584        66
1591        66.29166667
1632        68
1680        70
1728        72
1765        73.54166667
1776        74
1811        75.45833333
1824        75.95833333
1853        77.16666667
1872        77.95833333
1896        78.95833333
1920        79.95833333
1939        80.75
1968        81.95833333

Как вы можете видеть, он помещает фреймы каждые 2 секунды И на сцену (секунды с плавающей частью), что, на мой взгляд, важно для сложности видеопотока.

Размеры сгенерированных файлов практически одинаковы. Очень странно, что даже с большим количеством ключевых кадров в методе 3 он генерирует иногда меньше файлов, чем стандартный алгоритм библиотеки x264.

Для генерации файлов с несколькими битрейтами для потока HLS мы выбираем метод три. Он идеально согласован с 2 секундами между чанками, у них есть iframe в начале каждого чанка, и у них есть дополнительные iframe на сложных сценах, что обеспечивает лучший опыт для пользователей, которые имеют устаревшие устройства и не могут воспроизводить высокие профили x264.

Надеюсь, это кому-нибудь поможет.

Ара Саахов
источник
Фантастика, спасибо за ваши 50 центов!
BrunoFenzl
7

Таким образом, ответ выглядит так:

  • Способ 1 проверен на libx264работоспособность , но он специфичен и стоит за счет исключения очень полезной scenecutопции в libx264.
  • Метод 3 работает с версией FFMPEG от апреля 2015 года, но вы должны проверить свои результаты с помощью сценария, включенного в нижней части этого поста, так как документация FFMPEG неясна относительно действия этого параметра. Если это работает, это лучший из двух вариантов.
  • НЕ ИСПОЛЬЗУЙТЕ Метод 2, -gкажется, не рекомендуется. Он не работает, не определен явно в документации, не найден в справке и не используется в коде. Проверка кода показывает, что эта -gопция, вероятно, предназначена для потоков MPEG-2 (есть даже разделы кода, ссылающиеся на PAL и NTSC!).

Также:

  • Файлы, созданные с помощью метода 3, могут быть немного больше, чем метод 1, так как разрешены промежуточные I-кадры (ключевые кадры).
  • Вы должны явно установить флаг "-r" в обоих случаях, даже несмотря на то, что метод 3 помещает I-кадр в следующий интервал кадров в указанное время или позже . Неспособность установить флаг "-r" ставит вас в зависимость от исходного файла, возможно, с переменной частотой кадров. Могут возникнуть несовместимые переходы DASH.
  • Несмотря на предупреждения в документации FFMPEG, метод 3 НЕ менее эффективен, чем другие. На самом деле, тесты показывают, что он может быть немного более эффективным, чем метод 1.

Скрипт для -force_key_framesварианта

Вот короткая программа на Perl, которую я использовал для проверки частоты вращения I-кадров на основе вывода из предложения slhck's ffprobe. Кажется, чтобы убедиться, что -force_key_framesметод также будет работать, и имеет дополнительное преимущество учета scenecutкадров. Я абсолютно не представляю, как FFMPEG делает эту работу, или я просто так повезло, потому что мои потоки оказываются хорошо подготовленными.

В моем случае я кодировал со скоростью 30 кадров в секунду с ожидаемым размером GOP 6 секунд или 180 кадров. Я использовал 180 в качестве аргумента gopsize, чтобы эта программа проверяла I-кадр при каждом кратном 180, но установка его в 181 (или любое другое число, не кратное 180) заставила его жаловаться.

#!/usr/bin/perl
use strict;
my $gopsize = shift(@ARGV);
my $file = shift(@ARGV);
print "GOPSIZE = $gopsize\n";
my $linenum = 0;
my $expected = 0;
open my $pipe, "ffprobe -i $file -select_streams v -show_frames -of csv -show_entries frame=pict_type |"
        or die "Blah";
while (<$pipe>) {
  if ($linenum > $expected) {
    # Won't catch all the misses. But even one is good enough to fail.
    print "Missed IFrame at $expected\n";
    $expected = (int($linenum/$gopsize) + 1)*$gopsize;
  }
  if (m/,I\s*$/) {
    if ($linenum < $expected) {
      # Don't care term, just an extra I frame. Snore.
      #print "Free IFrame at $linenum\n";
    } else {
      #print "IFrame HIT at $expected\n";
      $expected += $gopsize;
    }
  }
  $linenum += 1;
}
Марк Геролиматос
источник
Просто примечание: поскольку это сайт вопросов и ответов, а не дискуссионный форум, где посты упорядочены в хронологическом порядке, лучше всего поместить всю информацию в один ответ, так что люди, ищущие решение, должны просто прочитать один пост, а не смотреть на то, кто что опубликовал, когда :) Я объединил ваши ответы и тоже дал вам +1. Поскольку перекрестная публикация запрещена , я бы посоветовал вам удалить свой вопрос на сайте Видео. Люди найдут ответ (ы) здесь.
Slhck
1
У меня просто была еще одна мысль (на самом деле она была поднята в списке рассылки FFmpeg). Когда вы используете force_key_frames, он как бы портит алгоритм распределения битов x264, поэтому он может дать вам худшее качество, чем просто установка фиксированного интервала ключевых кадров.
slhck
Святое дерьмо. Еще одна причина, по которой FFMPEG предоставляет кодек-неспецифичный способ сделать это, аргумент, который «сделает лучшее для рассматриваемого кодека». Я пытался отправить заявку на это с помощью трассы FFMPEG, но отскочил :-(
Марк Джеролиматос
@slhck: Не могли бы вы дать более подробную информацию, пожалуйста? Я просмотрел архивы списков рассылки в мае 2015 года, но ничего не смог найти. Суть в том, чтобы забыть о «методе 3» и придерживаться «метода 1».
schieferstapel
3
@MarkGerolimatos: о -g, вы говорите: «Кажется, он не работает, и не используется в коде». Я проверил и вход gхранится в avctx->gop_sizeи что libx264 использует его: x4->params.i_keyint_max = avctx->gop_size;. Когда я проверяю этот сгенерированный тестовый файл:, ffmpeg -i a-test-file.mp4 -g 37 -t 15 gtest.mp4я точно получаю ключевые кадры 0,37,74,111,148,185,222,259,296,333,370. GOP может быть прерван, если смена сцены вызвана, и для этого -sc_thresholdможет быть установлено, что также подхватывается x264.
Гьян
4

Я хотел добавить сюда некоторую информацию, так как мой поиск в Google потянул это обсуждение довольно много в моем стремлении найти информацию о попытке найти способ сегментировать мою DASH-кодировку так, как я хотел, и ни одна из найденных мной сведений не была полностью правильной.

Первые несколько заблуждений, чтобы избавиться от:

  1. Не все I-кадры одинаковы. Есть большие рамки "я" и маленькие рамки "я". Или использовать правильную терминологию, I-кадры IDR и I-кадры не-IDR. I-кадры IDR (иногда называемые «ключевыми кадрами») создадут новую GOP. Кадры без IDR не будут. Их удобно иметь внутри GOP, где происходит смена сцены.

  2. -x264opts keyint=GOPSIZE:min-keyint=GOPSIZE← Это не делает то, что вы думаете, что делает. Это заняло у меня некоторое время, чтобы понять. Оказывается, min-keyintэто ограничено в коде. Это не может быть больше, чем (keyint / 2) + 1. Таким образом, присвоение одного и того же значения этим двум переменным приводит к тому, min-keyintчто при кодировании значение будет сбито наполовину.

Вот в чем дело: вырезка сцены действительно великолепна, особенно в видео, где есть быстрые переходы. Он сохраняет его красивым и четким, поэтому я не хочу его отключать, но в то же время я не мог получить фиксированный размер GOP, пока он был включен. Я хотел включить вырезку сцены, но использовать только I-кадры без IDR. Но это не сработало. Пока я не выяснил (из большого количества чтения) о заблуждении № 2.

Оказывается, мне нужно keyintбыло удвоить желаемый размер GOP. Это означает, что min-keyintможно установить желаемый размер GOP (без внутреннего кода, обрезающего его пополам), что предотвращает обнаружение среза сцены от использования I-кадров IDR внутри размера GOP, поскольку количество кадров с момента последнего I-кадра IDR равно всегда меньше чем min-keyinit.

И, наконец, установка force_key_frameпараметра отменяет двойной размер keyint. Итак, вот что работает:

Я предпочитаю сегменты по 2 секунды, поэтому мой GOPSIZE = Framerate * 2

ffmpeg <other_options> -force_key_frames "expr:eq(mod(n,<GOPSIZE>),0)" -x264opts rc-lookahead=<GOPSIZE>:keyint=<GOPSIZE * 2>:min-keyint=<GOPSIZE> <other_options>

Вы можете проверить, используя ffprobe:

ffprobe <SRC_FLE> -select_streams v -show_frames -of csv -show_entries frame=coded_picture_number,key_frame,pict_type > frames.csv

В сгенерированном CSV-файле каждая строка сообщит вам frame, [is_an_IDR_?], [frame_type], [frame_number]:

frame,1,I,60  <-- frame 60, is I frame, 1 means is an IDR I-frame (aka KeyFrame)
frame,0,I,71  <-- frame 71, is I frame, 0 means not an IDR I_frame

В результате вы должны видеть I-кадры IDR только с фиксированными GOPSIZEинтервалами, в то время как все другие I-кадры являются I-кадрами не-IDR, вставленными по мере необходимости при обнаружении перехода сцены.

Рувим
источник
это было фантастически! Это было очень нелогично, спасибо, что приложили усилия. Подводя итог, я предполагаю, что ваше определение «I-кадров» и «i-кадров» является концептуальным (то есть не настраиваемым явно в libx264), и что «max * 2» было тем способом, которым вы его применяли?
Марк Геролиматос
Да, это было концептуально, хотя я видел, как люди используют «I» против «i», чтобы различать I-кадры IDR и не-IDR. И да, установка keyinit на желаемый размер gop * 2 - это способ заставить все I-кадры внутри gop быть не-IDR I-кадрами. Затем ffmpeg -force-key-frames перезаписывает key-init в x264opts. По сути, это действительно обратный способ получить желаемый результат, который был бы возможен, если бы код x264 позволял вам устанавливать min-keyinit и keyinit на одно и то же значение.
Рувим
... в то же время можно одновременно включать обнаружение обрезки сцены и получать фиксированный размер GOP.
Рувим
Еще раз спасибо за вашу потрясающую работу! Похоже, нам нужен менее «обратный» способ воздействия
Марк Джеролиматос
Нужен ли здесь rc-lookahead? Это влияет на mbtree и VBV, но влияет ли это на генерацию i-кадров?
Александр Светкин
0

Кажется, что этот синтаксис не всегда работает. Я довольно много тестировал наш VOD-контент, а также живой контент (дампы файлов), и иногда scenecut не работает и запускает промежуточный iframe:

Синтаксис для преобразования с повышением частоты i50-> p50, 2-х секундный переход / сегмент, IDR в начале, промежуточные фреймы при необходимости

ffmpeg.exe -loglevel verbose -i avc_50i.ts -pix_fmt yuv420p -filter_complex yadif=1,scale=1920:1080 -vcodec libx264 -preset fast -x264-params "rc-lookahead=100:keyint=200:min-keyint=100:hrd=1:vbv_maxrate=12000:vbv_bufsize=12000:no-open-gop=1" -r 50 -crf 22 -force_key_frames "expr:eq(mod(n,100),0)" -codec:a aac -b:a 128k -y target.ts
ТЭБ
источник
0

У Twitch есть пост об этом. Они объясняют, что решили использовать собственную программу по нескольким причинам; одна из них заключалась в том, что ffmpeg не позволяет запускать разные экземпляры x264 в разных потоках, а вместо этого посвящает все указанные потоки одному кадру в одном выводе, прежде чем переходить к следующему выводу.

Если вы не делаете потоковую передачу в реальном времени, у вас больше роскоши. «Правильный» способ - это, вероятно, кодировать в одном разрешении только с размером GOP, указанным с -g, а затем кодировать другие разрешения, заставляя ключевые кадры в тех же местах.

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

Но для большей части контента очень мало различий между наличием одного ключевого кадра каждые 5 секунд и двух ключевых кадров каждые 5 секунд (один принудительный, а другой из сцены). Это примерно средний размер I-кадра по сравнению с размером P-кадров и B-кадров. Если вы используете x264 с типичными настройками (единственная причина, по которой я думаю, что вы должны что-то сделать, чтобы повлиять на них, это если вы установите -qmin, как плохой способ запретить x264 использовать битрейт для простого контента; это ограничивает все типы кадров одним и тем же значением Я думаю) и получу такой результат, как средний размер I-кадра 46 кБ, P-кадр 24 кБ, B-кадр 17 кБ (в два раза меньше P-кадров), а затем дополнительный I-кадр каждую секунду со скоростью 30 кадров в секунду только 3% увеличение размера файла. Разница между h264 и h263 может состоять из 3% снижений, но одно не очень важно.

Для других типов контента размеры фреймов будут другими. Чтобы быть справедливым, речь идет о временной сложности, а не пространственной сложности, поэтому это не просто легкий контент против жесткого контента. Но, как правило, сайты потокового видео имеют ограничение по битрейту, а контент с относительно большими I-кадрами - это простой контент, который будет кодироваться с высоким качеством независимо от того, сколько дополнительных ключевых кадров добавлено. Это расточительно, но эти отходы обычно не будут замечены. Наиболее бесполезным случаем, вероятно, является видео, представляющее собой статичное изображение, сопровождающее песню, где каждый ключевой кадр точно такой же.

Одна вещь, в которой я не уверен, это то, как принудительные ключевые кадры взаимодействуют с ограничителем скорости, установленным с -maxrate и -bufsize. Я думаю, что даже у YouTube недавно были проблемы с правильной настройкой параметров буфера для обеспечения постоянного качества. Если вы просто используете настройки среднего битрейта, как это видно на некоторых сайтах (поскольку вы можете проверить параметры x264 в заголовке / атоме mov с помощью шестнадцатеричного редактора), тогда модель буфера не является проблемой, но если вы При работе с пользовательским контентом средняя скорость передачи битов побуждает пользователей добавлять черный экран в конце своего видео.

Параметр -g в Ffmpeg или любой другой используемый вами параметр кодировщика сопоставляется с параметром, специфичным для кодировщика. Таким образом, ключ -x264-params = GOPSIZE эквивалентен ключу -g GOPSIZE.

Одна из проблем, связанных с использованием обнаружения сцен, заключается в том, что вы предпочитаете ключевые кадры рядом с конкретными номерами по любой причине. Если вы определяете ключевые кадры каждые 5 секунд и используете обнаружение сцены, и происходит изменение сцены на 4,5, то это должно быть обнаружено, но тогда следующий ключевой кадр будет на 9,5. Если время будет увеличиваться, как это, вы можете получить ключевые кадры в 42,5, 47,5, 52,5 и т. Д. Вместо 40, 45, 50, 55. И наоборот, если в 5,5 произойдет изменение сцены, то будет ключевой кадр на 5 и 5,5 будет слишком рано для другого. Ffmpeg не позволяет вам указать «создайте ключевой кадр здесь, если в течение следующих 30 кадров не произойдет смена сцены». Однако тот, кто понимает C, может добавить эту опцию.

Для видео с переменной частотой кадров, когда вы не транслируете в прямом эфире, как Twitch, вы должны иметь возможность использовать изменения сцены без постоянного преобразования в постоянную частоту кадров. Если вы используете фильтр 'select' в ffmpeg и используете константу 'scene' в выражении, то вывод отладки (-v debug или несколько раз нажмите '+' во время кодирования) показывает номер изменения сцены. Вероятно, это отличается от числа, используемого x264, и не так полезно, но все же может быть полезным.

Процедура, вероятно, будет состоять в том, чтобы сделать тестовое видео, которое предназначено только для изменений ключевого кадра, но, возможно, может быть использовано для данных контроля скорости при использовании 2-проходного. (Не уверен, что сгенерированные данные вообще полезны для разных разрешений и настроек; данные дерева макроблоков не будут.) Преобразуйте их в видео с постоянной частотой кадров, но посмотрите эту ошибку о заикании вывода при уменьшении частоты кадров вдвое, если вы когда-нибудь решите использовать фильтр fps для других целей. Запустите его через x264 с нужным ключевым кадром и настройками GOP.

Затем просто используйте это время ключевого кадра с исходным видео с переменной частотой кадров.

Если вы допускаете совершенно сумасшедший пользовательский контент с 20-секундным промежутком между кадрами, то для кодирования с переменной частотой кадров вы можете разделить вывод, использовать фильтр fps, каким-то образом использовать фильтр выбора (возможно, создать действительно длинное выражение, которое имеет каждый ключевой кадр) ... или, возможно, вы можете использовать тестовое видео в качестве входных данных и либо декодировать только ключевые кадры, если эта опция ffmpeg работает, либо использовать фильтр выбора для выбора ключевых кадров. Затем масштабируйте его до нужного размера (для этого есть даже фильтр scale2ref) и наложите на него оригинальное видео. Затем используйте фильтр чередования, чтобы объединить эти обязательные ключевые кадры с исходным видео. Если это приводит к двум кадрам, которые находятся на расстоянии 0,001 секунды друг от друга, что не мешает фильтру чередования, то решите эту проблему самостоятельно с помощью другого фильтра выбора. Работа с ограничениями кадрового буфера для фильтра чередования может быть главной проблемой здесь. Все это может работать: использовать какой-то фильтр для буферизации более плотного потока (fifo filter?); обращайтесь к входному файлу несколько раз, чтобы он декодировался более одного раза, и кадры не нужно сохранять; использовать фильтр streamselect, который я никогда не делал, точно в моменты ключевых кадров; улучшить фильтр чередования, изменив его поведение по умолчанию или добавив опцию для вывода самого старого кадра в буфер вместо удаления кадра. что я никогда не делал, точно в моменты ключевых кадров; улучшить фильтр чередования, изменив его поведение по умолчанию или добавив опцию для вывода самого старого кадра в буфер вместо удаления кадра. что я никогда не делал, точно в моменты ключевых кадров; улучшить фильтр чередования, изменив его поведение по умолчанию или добавив опцию для вывода самого старого кадра в буфер вместо удаления кадра.

Misaki
источник