Объединение двух живых RTMP-потоков в другой RTMP-поток, проблемы с синхронизацией (с FFMPEG)

Я пытаюсь объединить (бок о бок) два живых видеопотока, поступающих через RTMP, используя следующую команду ffmpeg:

ffmpeg -i "rtmp://first" -i "rtmp://first" -filter_complex "[0v][1v]xstack=inputs=2:layout=0_0|1920_0[stacked]" -map "[stacked]" -preset ultrafast -vcodec libx264 -tune zerolatency -an -f flv output.flv

В этом примере я фактически использую один и тот же входной поток два раза, потому что так проблема более заметна. И проблема в том, что два потока на выходе рассинхронизированы примерно на 2-3 секунды. То есть - я ожидаю (поскольку у меня два одинаковых входа), чтобы на выходе были точно такие же левая и правая стороны. Вместо этого левая сторона отстает от правой на 2-3 секунды.

Я считаю, что происходит то, что ffmpeg подключается к входам по порядку (я вижу это в журнале вывода), и подключение к каждому из них занимает 2-3 секунды (возможно, он ждет I-кадр, эти потоки имеют интервал I-кадра 3 секунды) . Затем, вероятно, он буферизует кадры, полученные с первого (уже подключенного) входа, при подключении ко второму. Когда подключен второй и кадры с обоих входов готовы к прохождению через фильтр - буфер первого входа уже содержит 2-3 секунды видео - и результат рассинхронизирован.

Опять же, это только мои предположения. Итак, как я могу достичь своей цели? В основном я хочу, чтобы ffmpeg отбрасывал все «старые» кадры, полученные до того, как ОБА входа будут подключены ИЛИ каким-то образом поместили «пустые» (черные?) кадры для второго ввода, ожидая, пока этот второй ввод станет доступным. Пробовал играть с разными флажками, с PTS (фильтр настроек), но безрезультатно.

Можете ли вы раскрыть или поделиться одним из этих URL-адресов?
@Gyan Я не могу поделиться таким URL-адресом, но он создается путем потоковой передачи моего рабочего стола через OBS Studio на конечную точку rtmp на сервере (которая является частной, поэтому я не могу ею поделиться) и использует эту конечную точку. Сервер не обрабатывает этот поток RTMP, поэтому я думаю, что его можно воспроизвести. То же самое происходит, когда я транслирую свою камеру (или любой другой «живой» источник). В моем рассматриваемом примере я использую один и тот же поток 2 раза, поэтому проблема синхронизации очень заметна.
Я пытаюсь сделать что-то подобное и пробовал различные комбинации -vsync, и -max_delay, но пока не удалось синхронизировать два моих прямых потока. -copyts-start_at_zero
@RichardWiseman да, я отказался от этого, и мне пришлось вручную смешивать кадры с помощью C ++ (все еще с помощью ffmpeg, но не с помощью утилиты командной строки).

Ответы (2)

Я заработал, добавив -fflags nobuffer -flags low_delay -strict experimentalперед всеми входами. Помогло прочитать эту тему

-vsyncпараметр

Метод синхронизации видео.

  • 0: каждый кадр передается с отметкой времени от демультиплексора к мультиплексору.
  • 1: Кадры будут дублироваться и отбрасываться для достижения требуемой постоянной частоты кадров.
  • 2: кадры передаются с отметкой времени или отбрасываются, чтобы не допустить, чтобы 2 кадра имели одну и ту же отметку времени.
  • -1: Выбор между 1 и 2 в зависимости от возможностей мультиплексора. Это метод по умолчанию.

С помощью -mapвы можете выбрать, из какого потока следует брать метки времени. Вы можете оставить видео или аудио без изменений и синхронизировать оставшиеся потоки с неизмененным.

-async samples_per_second

Метод синхронизации звука. «Растягивает/сжимает» аудиопоток, чтобы он соответствовал временным меткам, параметр — максимальное количество отсчетов в секунду, на которое изменяется звук. -async 1является особым случаем, когда корректируется только начало аудиопотока без какой-либо последующей коррекции.

-copyts

Копировать временные метки с входа на выход.