Как сделать первый кадр ключевым?

Как сделать первый кадр ключевым?

Я хочу выполнить кодирование после перехода к определенной позиции и сделать первый кадр ключевым. Вот команда, которую я использовал:

ffmpeg -ss 300  -i howimet.mp4 -acodec libfaac -ar 48000 -ab 128k -ac 2  -vcodec libx264 -vf "scale=480:270" -f mpegts -force_key_frames 300 -t 120 howimet2.ts

-force_key_frames настроен на поиск позиции для создания ключевого кадра. Я использую следующий скрипт (изздесь) для проверки, является ли первый кадр ключевым

ffprobe -show_frames -v quiet howimet2.ts | awk -F= '   /pict_type=/ { if (index($2, "I")) { i=1; } else { i=0; } } 
  /pkt_pts_time/ { if (i && ($2 >= 0)) print $2; }  
' | head -n 1

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

Думаю, моя команда неверна. Что я упускаю?

решение1

При кодировании видео первый кадримеетбыть ключевым кадром. Он будет первым полностью закодированным, и последующие кадры могут использовать его для межкадрового предсказания. Также в начале закодированной видеопоследовательности у вас будет блок доступа H.264, который сообщает декодеру о необходимости обновления.

Итак, независимо от того, что вы делаете: если вы просто не копируете битовый поток, вы перекодируете видео, и ваш первый кадр должен быть ключевым.

Теперь, по какой-то причине ваш поток имеет смещение в своем начальном времени. Это означает, что все временные метки представления также смещены в соответствии с этим смещением. Если вы проверите заголовок вывода ffprobe -show_frames, вы увидите, что кадр 0 действительно будет ключевым кадром, но с другим PTS.

Чтобы компенсировать это, вы можете вычесть время начала из всех PTS.

решение2

Как уже упоминалось, первый кадр вашего видео должен быть I-Frame. Ваша проблема связана не с кодированием (или копированием, если вам это по вкусу), а с декодированием. Наличие -ss перед входом неточно, поэтому ffmpeg делает все возможное, чтобы вы попали туда, куда вам нужно. Ffmpeg прошел это местоположение и, таким образом, сообщает вам ненулевую первую временную метку.

Я бы рекомендовал попробовать второй -ss после вашего -i. По типу -ss 299 -i input -ss 1.

Это говорит, что нужно перейти примерно в то место, которое вы хотели, затем декодировать в течение 1 секунды перед обработкой. Я не уверен, исправит ли это вашу проблему с pts, но надеюсь, что это направит вас в правильном направлении.

Хочу отметить, что я не думаю, что команда force_key_frames делает то, что вы думаете. Если она что-то делает, то, скорее всего, просто говорит ей добавлять ключевой кадр в вывод каждые 300 секунд, но это всего лишь предположение. То есть только первый кадр вашего вывода будет ключевым (t=120).

https://ffmpeg.org/ffmpeg.html

решение3

Установите размер GOP с помощью «-g»

Чтобы продемонстрировать точность, вот отрезки длительностью 1 секунда.

ffmpeg -i  in.mkv -g 30  -hls_time 1 -hls_list_size 0 index.m3u8

Вот как выглядит m3u8:

    #EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:1.001000,
index0.ts
#EXTINF:1.001000,
index1.ts
#EXTINF:1.001000,
index2.ts
#EXTINF:1.001000,
index3.ts
#EXTINF:1.001000,
index4.ts
#EXTINF:1.001000,
index5.ts
#EXTINF:1.001000,
index6.ts
#EXTINF:1.001000,
index7.ts
#EXTINF:1.001000,
index8.ts
#EXTINF:1.001000,
index9.ts
#EXTINF:1.001000,
index10.ts
#EXTINF:1.001000,
index11.ts
#EXTINF:1.001000,
index12.ts
#EXTINF:1.001000,
index13.ts
#EXTINF:1.001000,
....

Связанный контент