Я хочу выполнить кодирование после перехода к определенной позиции и сделать первый кадр ключевым. Вот команда, которую я использовал:
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).
решение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,
....