MediaSource Buffer работает только на одном клиенте - PullRequest
0 голосов
/ 07 мая 2018

Итак, я пытаюсь создать приложение для прямой трансляции и столкнулся со странной проблемой.

Так что я использую getUserMedia для захвата видео от пользователя, затем пользователь помечается как вещатель. Затем я использую MediaRecorder, чтобы получить фактические видеоданные от MediaStream и отправить их через веб-сокет.

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

Uncaught DOMException: Failed to execute 'appendBuffer' on 'SourceBuffer': This SourceBuffer has been removed from the parent media source.

Когда я смотрю в chrome: // media-internals Я вижу эту ошибку:

00:00:00 94 error Unexpected element ID 0x8c 00:00:00 94 error Append: stream parsing failed. Data size=33926 append_window_start=0 append_window_end=inf 00:00:00 94 pipeline_error CHUNK_DEMUXER_ERROR_APPEND_FAILED

Сценарии и все, конечно, одинаково на обоих клиентах. Единственное, что отличается, и я думал, что виновником может быть тот факт, что поток вещателя начался не сразу, так как вещателю сначала нужно отправить видеоданные на сервер веб-сокетов, чтобы сервер мог что-то ретранслировать. Однако клиенты, не являющиеся вещателями, как бы прыгают в «середину» потока.

Единственное другое отличие состоит в том, что трансляция загружает и загружает видеоданные через один и тот же разъем, но я не понимаю, как это отразится на проблеме.

РЕДАКТИРОВАТЬ: после запуска теста, когда оба клиента были подключены к веб-сокету БЕЗ потокового видео, а затем запускался поток после того, как оба клиента работали, это означает, что проблема связана с тем, что другие клиенты прыгают в поток в середине Кстати, как бы это исправить?

Однако я новичок во всем этом, поэтому я не уверен, насколько это обоснованно. Для справки, это скрипт:

var socket = new WebSocket('websocket');
socket.binaryType = 'arraybuffer';

var broadcastMs = new MediaSource();

var video = document.querySelector("#broadcast");
video.src = window.URL.createObjectURL(broadcastMs);

var msReady = false;
var sourceBuffer = false;
var queue = [];

broadcastMs.addEventListener('sourceopen', function(e)
{
    sourceBuffer = broadcastMs.addSourceBuffer('video/webm; codecs="opus,vp8"');

    sourceBuffer.addEventListener('update', function()
    {
        if ( queue.length > 0 && !sourceBuffer.updating )
            sourceBuffer.appendBuffer(queue.shift());
    });

    msReady = true;     
});

socket.onmessage = function(ev)
{
    setTimeout(function()
    {
        if ( msReady )
        {
            if ( sourceBuffer.updating )
                queue.push(ev.data);
            else
                sourceBuffer.appendBuffer(ev.data);
        }
    }, 50);
};

1 Ответ

0 голосов
/ 08 мая 2018

Вы не можете просто войти в поток WebM. Сначала вы должны отправить несколько частей для инициализации потока.

Получить копию EBML Viewer. https://code.google.com/archive/p/ebml-viewer/downloads (EBML - это стандартный двоичный формат, на котором основан Matroska. WebM является подмножеством Matroska.) Откройте файл WebM. Вы увидите элемент Segment, который будет содержать набор данных, которые настраивают поток. (Треки, кодеки и т. Д.) Все эти данные, вплоть до начала первого кластера, должны быть сначала отправлены в MediaSource. После этого вы можете начать с любого сегмента, содержащего ключевой кадр.

Я должен отметить, что то, что вы делаете, это решенная проблема. Посмотрите в WebRTC гораздо более эффективный способ сделать это. Вы получаете меньше контроля ... но много вещей бесплатно.

...