Подтвердить что ты не робот

Как сохранить поток видео в реальном времени MediaSource в синхронизации?

У меня есть серверное приложение, которое транслирует 30-скоростной видеопоток FPS, затем кодирует и мультиплексирует его в режиме реального времени в WebM Byte Stream.

На стороне клиента страница HTML5 открывает на сервере WebSocket, который начинает генерировать поток, когда соединение принимается. После доставки заголовка каждый последующий кадр WebSocket состоит из одного WebM SimpleBlock. Ключевой кадр происходит каждые 15 кадров, и когда это происходит, начинается новый кластер.

Клиент также создает MediaSource, а при получении кадра из WS добавляет содержимое в активный буфер. <video> начинает воспроизведение сразу после добавления первого кадра.

Все работает достаточно хорошо. Моя единственная проблема заключается в том, что сетевой джиттер заставляет позицию воспроизведения дрейфовать с фактического времени через некоторое время. Мое текущее решение - подключиться к событию updateend, проверить разницу между video.currentTime и временным кодом входящего кластера и вручную обновить currentTime, если оно выходит за допустимый диапазон. К сожалению, это вызывает заметную паузу и скачок в воспроизведении, что довольно неприятно.

Решение также немного странно: я точно знаю, где находится последний ключевой кадр, но я должен преобразовать его в целую секунду (как по спецификации W3C), прежде чем я смогу передать его в currentTime, где браузер предположительно, должен затем обойти и найти ближайший ключевой кадр.

Мой вопрос заключается в следующем: есть ли способ сообщить Media Element всегда искать доступный последний ключевой кадр или синхронизировать время воспроизведения с системным часовым временем?

4b9b3361

Ответ 1

джиттер сети приводит к дрейфу позиции воспроизведения

Это не твоя проблема. Если вы столкнулись с отсева в потоке, вы не буферизуете достаточно до начала воспроизведения, а воспроизведение имеет буфер соответствующего размера, даже если на несколько секунд отстает от реального времени (что нормально).

Мое текущее решение - подключиться к событию updateend, проверить разницу между video.currentTime и временным кодом входящего кластера

Это близко к правильному методу. Я предлагаю вам игнорировать временный код входящего кластера и вместо этого проверять ваши буферизированные диапазоны времени. То, что вы получили в кластере WebM, и то, что было декодировано, - это две разные вещи.

К сожалению, это вызывает заметную паузу и скачок в воспроизведении, что довольно неприятно.

Как еще вы это сделаете? Вы можете либо перейти в реальном времени, либо увеличить скорость воспроизведения, чтобы догнать до реального времени. В любом случае, если вы хотите догнать в реальном времени, вам нужно пропустить это время.

Решение также немного странно: я точно знаю, где находится последний ключевой кадр

Вы можете, но игрок не делает это, пока этот носитель не будет декодирован. В любом случае ключевой кадр не имеет значения... вы можете искать места без ключевых кадров. Браузер будет декодировать перед P/B-кадрами по мере необходимости.

Мне нужно преобразовать его в целую секунду (по спецификации W3C), прежде чем я смогу передать его в currentTime

Это абсолютно неверно. currentTime указывается как double. https://www.w3.org/TR/2011/WD-html5-20110113/video.html#dom-media-currenttime

Мой вопрос заключается в следующем: есть ли способ сообщить Media Element всегда искать доступный последний ключевой кадр или синхронизировать время воспроизведения с системным часовым временем?

Он будет автоматически воспроизводить последний буфер. Вам не нужно ничего делать. Вы выполняете свою работу, гарантируя, что медиаданные попадают в буфер и устанавливают воспроизведение как можно ближе к этому. Вы всегда можете продвигать его вперед, если меняется состояние сети, что позволяет вам это делать, но, откровенно говоря, это звучит так, как будто вы просто сломали код и сломанную стратегию буферизации. В противном случае воспроизведение будет простым.

Захват, если он отстает, не будет происходить автоматически, и не должен. Если игрок делает паузу из-за слива буфера, буфер необходимо снова создать резервную копию до возобновления воспроизведения. То, что вся точка буфера.

Кроме того, ваше ожидание сохранения чего-либо вовремя с системными часами не является хорошей идеей и необоснованно. Различные устройства имеют разные частоты обновления, будут обрабатывать видео по разным скоростям. Просто нажмите на игру и дайте ей поиграть. Если вы закончите несколько секунд, продолжайте и установите currentTime, но будьте очень уверены в том, что вы забуферили, прежде чем это сделать.