PyAV: форсировать новую частоту кадров при ремуксинге потока - PullRequest
0 голосов
/ 07 июня 2019

У меня есть программа Python, которая получает последовательность видеокадров H264 по сети, которую я хочу отобразить и, при необходимости, записать.Камера записывает со скоростью 30 кадров в секунду и отправляет кадры так быстро, как только может, что не всегда составляет 30 кадров в секунду из-за изменения состояния сети;иногда он отстает, а затем догоняет, и редко полностью сбрасывает кадры.

Часть «отображения» проста;Мне не нужно заботиться о синхронизации или потоковых метаданных, просто отображайте кадры так быстро, как они поступают:

input = av.open(get_video_stream())
for packet in input.demux(video=0):
  for frame in packet.decode():
    # A bunch of numpy and pygame code here to convert the frame to RGB
    # row-major and blit it to the screen

"Запись" часть выглядит как это должно быть легко:

input = av.open(get_video_stream())
output = av.open(filename, 'w')
output.add_stream(template=input.streams[0])
for packet in input.demux(video=0):
  for frame in packet.decode():
    # ...display code...
  packet.stream = output.streams[0]
  output.mux_one(packet)
output.close()

И действительно, это дает действительный файл MP4, содержащий все кадры, и если я воспроизведу его с mplayer -fps 30, он будет работать нормально.Но это -fps 30 абсолютно необходимо:

$ ffprobe output.mp4
Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 960x720,
                  1277664 kb/s, 12800 fps, 12800 tbr, 12800 tbn, 25600 tbc (default)

Обратите внимание, что 12 800 кадров в секунду.Он должен выглядеть примерно так (создается путем вызова mencoder -fps 30 и передачи в него кадров):

$ ffprobe mencoder_test.mp4
Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 960x720,
                  2998 kb/s, 30 fps, 30 tbr, 90k tbn, 180k tbc (default)

Проверка пакетов и кадров, которые я получаю из входного потока, я вижу:

stream: time_base=1/1200000
codec: framerate=25 time_base=1/50
packet: dts=None pts=None duration=48000 time_base=1/1200000
frame: dst=None pts=None time=None time_base=1/1200000

Итак, пакеты и кадры вообще не имеют временных меток;у них есть time_base, которая не совпадает ни с временной базой, которая заканчивается в конечном файле , ни с фактической частотой кадров камеры;кодек имеет частоту кадров и временную базу, которые не соответствуют конечному файлу, частоте кадров камеры или другим метаданным видеопотока!

Документация PyAV практически полностью отсутствует, когда речь идет о проблемах синхронизации и частоты кадров., но я попытался вручную установить различные комбинации потока, пакета и кадра time_base, dts и pts, но безуспешно.Я всегда могу повторно смешать записанные видео снова , чтобы получить правильную частоту кадров, но я бы предпочел писать видеофайлы, которые в первую очередь правильные.

Итак, как мне получить pyAV дляСкомпонуйте видео таким образом, чтобы вывод был правильно помечен как 30fps?

...