MediaSource Buffer работает только на одном клиенте

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

Итак, я использую 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);
};

person CristianHG    schedule 07.05.2018    source источник
comment
Итак, я попытался отправить начальные кадры, которые изначально, казалось, решили проблему, но затем они зависали, когда сервер отправлял кадры после этих двух начальных кадров, а это означает, что для правильной работы видео должна быть какая-то временная шкала. .   -  person CristianHG    schedule 07.05.2018
comment
ты решил эту проблему?   -  person Tarun Rawat    schedule 14.05.2020
comment
Нет, в итоге я отказался от проекта. Однако в настоящее время доступно множество сторонних приложений, которые вы можете использовать, чтобы упростить этот процесс! Изучите стек сервисов AWS Livestreaming, он укажет вам правильный путь.   -  person CristianHG    schedule 18.05.2020


Ответы (1)


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

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

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

person Brad    schedule 08.05.2018
comment
Благодарю вас! Как бы я применил это в среде прямой трансляции? Я транслирую напрямую из MediaStream, используя оборудование одного пользователя, в веб-сокет; сегмент конфигурации всегда один и тот же или есть какая-то закономерность? Я пытался изучить WebRTC, но не смог найти простого решения для ретрансляции видеоданных с сервера. Есть ли какая-либо документация, которую вы бы порекомендовали мне прочитать, чтобы понять, как это сделать? - person CristianHG; 09.05.2018