Видео H2R WebRTC, передаваемое с ffmpeg через Janus, очень прерывисто при воспроизведении - PullRequest
1 голос
/ 27 июня 2019

Попытка потокового видео по следующей цепочке: файл h264 / mp4 в локальном хранилище экземпляров (AWS) -> ffmpeg-> rtp-> Janus в том же экземпляре-> воспроизведение WebRTC (Chrome / mac). Результирующее видео нестабильно, даже если ни один из ресурсов не выглядит перегруженным (процессор / память / пропускная способность сети в любой из задействованных систем). Я также использую сервер Coturn TURN, он также вообще не загружен и пропускная способность достаточна.

Попробовал переключение кодеков, и это не помогло, кроме vp8, который хотя и работал (вроде - хаотичность все еще была, но очень редкая и приемлемая), приводила к такому высокому потреблению процессора, что практически это недопустимо.

ffmpeg -re -stream_loop -1 -i ./short.mp4 -s 426x240 -c:v libx264 -profile:v baseline -b:v 1M -r 24 -g 60 -an -f rtp rtp://127.0.0.1:5004

результирующий SDP:

o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 127.0.0.1
t=0 0
a=tool:libavformat 58.20.100
m=video 5004 RTP/AVP 96
b=AS:1000
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1

поток настроен с помощью Janus API как

            "janus" : "message",
            "transaction" : 'Transaction',
        "body": {
                "request" : "create",
                "type" : "rtp",
                "id" : newId,
                "name": streamId+newId,
                "audio": false,
                "video": true,
                "description" : streamId+newId,
                "videoport" : 5000+newId*4,
                "videopt" : 96,
                "videortpmap": "H264/90000",
                "secret" : "adminpwd"
            }
        }

Пробовал разные варианты bw, совсем не помогает. Изменение -g (размер GOP) на более низкие значения может сделать прерывистость более короткой по продолжительности, но более частой. При -g 3 или 4 это приемлемо, но битрейт для приемлемого качества, как и ожидалось, становится безумным.

Ожидаемый результат: видео воспроизводится без помех.

Моя теория об этом может быть одной из следующих:

  • Либо ffmpeg предоставляет данные в том виде, в каком буфер слишком мал, поэтому иногда Janus нужно отправить следующий пакет, пока он еще не готов, из-за недостатка буфера и, как следствие, к прерыванию - так что, возможно, есть способ заставить ffmpeg кодировать в какой-то короткий (полсекунды или около того - буфер для регулирования потока). Как?

  • Или H264 работает слишком плохо по UDP, как есть, и я ничего не мог сделать. Затем мне нужно было переключиться на TCP, но пока попытки сделать это были безуспешными.

Ответы [ 2 ]

1 голос
/ 30 июня 2019

Решение оказалось прекрасным в своей очевидности. ffmpeg отправил поток Янусу как RTP, Янус отправил его зрителям далее, очевидно, как SRTP, потому что это WebRTC и он всегда зашифрован. Который добавил кучу байтов к каждому пакету в качестве издержек шифрования. В некоторых случаях это означало, что пакеты проходили через MTU и отбрасывались - каждый раз, когда это происходило, в видео был заметный рывок.

Простое добавление? Pkt_size = 1300 для вывода RTP URL-адреса ffmpeg устранило проблему.

Спасибо Лоренцо Миньеро из Meetecho за это.

0 голосов
/ 27 июня 2019

ffmpeg оптимизирован для вывода кадров в блоках, а не для вывода отдельных кодированных кадров. Мультиплексор, в вашем случае мультиплексор rtp, обычно буферизует данные перед сбросом на выход. Таким образом, ffmpeg не оптимизирован для потоковой передачи в реальном времени, которая требует более или менее покадрового вывода. Однако для WebRTC действительно нужны кадры, поступающие в режиме реального времени, поэтому, если кадры отправляются в виде пакетов, он может отбрасывать «поздние» кадры, что приводит к изменчивости.

Однако в ffmpeg есть опция для установки размера буфера муксера в 0, которая работает хорошо. Это:

-max_delay 0

Кроме того, для WebRTC вы хотите отключить b-кадры и добавить SPS-PPS к каждому ключевому кадру:

-bf 0 + global_header -bsf: v "dump_extra = freq = keyframe"

...