кадр появляется за 0,000057 секунды до pts_time с использованием ffmpeg

Это видео создается с помощью команды ffmpeg из серия изображений с номером и ожидаемой временной меткой (при постоянной частоте кадров 120 кадров в секунду):

ffmpeg -framerate 120 -i %03d.png -crf 0 -x264opts keyint=1:min-keyint=1 120.mp4

Предполагается, что частота кадров должна быть постоянной, а все кадры - это I-кадры. Я ожидаю, что кадр 6 появится точно в 0,05 секунды [0,05, 0,0583333), как pts_time, показанное в ffmpeg и ffprobe:

[Parsed_showinfo_0 @ 0x7fba11404080] n: 6 точек: 768 точек_время: 0,05 поз: 36021 fmt: yuv444p sar: 0/1 с: 1552x878 i: P iskey: 1 тип: I контрольная сумма: 2CDED07A plane_checksum: [A86DBAAD C4CB8CC86 163 133 121] stdev: [9.0 0.6 0.8]

[FRAME]
media_type=video
stream_index=0
key_frame=1
pkt_pts=768
pkt_pts_time=0.050000
pkt_dts=768
pkt_dts_time=0.050000
best_effort_timestamp=768
best_effort_timestamp_time=0.050000
pkt_duration=128
pkt_duration_time=0.008333
pkt_pos=36021
pkt_size=2531
width=1552
height=878
pix_fmt=yuv444p
sample_aspect_ratio=N/A
pict_type=I
coded_picture_number=6
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
color_range=unknown
color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=left
[/FRAME]

Но на самом деле он появляется с 0,049943 секунды. Я использую ffmpeg для извлечения этого времени с продолжительностью 0,0001 секунды

ffmpeg -ss 00:00:00.049943 -i 120_keyint_1.mp4 -t 00:00:00.0001 out.mp4

и получите это видео, в котором показан кадр 6.

Я также попытался воспроизвести это видео на Chrome и установить currentTime для videoNode. Он показывает кадр 5 на 0,049943, но показывает кадр 6 с 0,049968 (до 0,05!).

Однако я попробовал другой метод кодирования и получил еще один постоянный кадр оценить видео:

ffmpeg -framerate 120 -i %03d.png -vcodec libx264 -f mp4 -movflags faststart 120.mp4

теоретически кадр 6 также должен появиться во временном диапазоне [0,05, 0,0583333), но в Chrome кадр 6 не будет отображаться до currentTime ›= 0,051 секунды. Что еще более интересно, я получаю кадр 6 за 0,049943 секунды, используя ffmpeg, ту же команду извлечения, что и выше.

Означает ли это, что в видео MPEG4 h.264 мы не можем полагаться на pts_time из ffmpeg для определения точного времени показа определенного кадра и конкретного видеопроигрывателя?


person Lincolnhuj    schedule 17.09.2020    source источник
comment
Да, ожидается некоторое дрожание. Любопытно, какое ваше приложение требует точности в микросекундах?   -  person Gyan    schedule 17.09.2020
comment
Мое веб-приложение предназначено для онлайн-редактирования видео и требует точности кадра. Мы ищем видеоформат, который может иметь строгое сопоставление кадров и временных меток.   -  person Lincolnhuj    schedule 17.09.2020
comment
Фактическая неточность воспроизведения видео не влияет на то, как вы храните или управляете временными метками в программном обеспечении или структурах файловых данных.   -  person Gyan    schedule 17.09.2020


Ответы (1)


Я думаю, что проблема заключается в масштабе 1000 заголовка фильма в вашем файле, который является жестко подключенным по умолчанию для ffmpeg. (libavformat \ movenc.h, строка 32: #define MOV_TIMESCALE 1000)

Ваша частота кадров в 120 кадров в секунду не может быть выражена в 1/1000 с, поэтому ffmpeg выдает ошибки округления.

1000 в качестве шкалы времени по умолчанию - плохой выбор, и ее нельзя изменить без изменения исходного кода ffmpeg.

Я бы изменил #define MOV_TIMESCALE 1000 на #define MOV_TIMESCALE 600 или другое значение, кратное 120, и перекомпилировал бы ffmpeg.

person Markus Schumann    schedule 17.09.2020
comment
MOV / MP4 хранят длительность выборки для каждой выборки (фактически, фрагменты), поэтому частота кадров в нее не входит, не говоря уже о том, что PTS соответствующего кадра может быть точно представлен в масштабе 1000 как 50. OP жалуется на неточность во время воспроизведения, а не ffmpeg. - person Gyan; 17.09.2020
comment
Извлечение @Gyan ffmpeg также дает неверный результат. ffmpeg -ss 00:00:00.049943 -i 120_keyint_1.mp4 -t 00:00:00.0001 out.mp4 дает клип с кадром 6, но должен быть кадром 5 - person Lincolnhuj; 18.09.2020
comment
Почему это должен быть кадр 5? - person Gyan; 18.09.2020
comment
@Gyan Обратите внимание, что кадр начинается с 0. Согласно ffmpeg showinfo, pts_time кадра 6 составляет 0,05 секунды. Таким образом, на 0,049943 секунды это должен быть 5-й кадр. - person Lincolnhuj; 18.09.2020
comment
Поиск не работает. Относительные отметки времени и длительности пакетов будут демультиплексированы как сохраненные, без корректировки для промежуточных интервалов времени. Кроме того, поиск MP4 обычно выполняется в обратном направлении к ближайшему ключевому кадру. В вашем случае, однако, он стремится к кадру 6, который является KF. Это потому, что 0.049943 при преобразовании в базу времени потока (1/15360) составляет 767,12448, которое округляется до + бесконечности, что приводит к 768. И кадр 6 является KF точно на 768 баллах. - person Gyan; 18.09.2020
comment
Спасибо за объяснение! @Gyan Всегда ли округляется в сторону + бесконечности? Как мы можем получить этот метод округления из ffmpeg? - person Lincolnhuj; 18.09.2020
comment
Задал отдельный вопрос здесь stackoverflow.com/questions/63956476/ - person Lincolnhuj; 18.09.2020