Как разделить поток на части, которые можно воспроизводить с помощью Media Source API?

Я могу создавать фрагменты данных, записанные с помощью MediaRecorder API. Храните их и воспроизводите с помощью MediaSource API. Это нормально работает, если я добавляю все фрагменты в правильном порядке в sourceBuffer.

async function recordScreen() {
  recordedChunks = []
  stream = await navigator.mediaDevices.getDisplayMedia(getDisplayMediaOptions)
  mediaRecorder = new MediaRecorder(stream)

  mediaRecorder.ondataavailable = event => {
    if (event.data.size > 0) {
      recordedChunks.push(event.data)
    }
  }
  const interval = setInterval(() => {
    if (isRecording) {
      mediaRecorder.requestData()
    } else {
      clearInterval(interval)
    }
  }, 1000)
  mediaRecorder.start()
  isRecording = true
}

function replay(chunks) {
  const mediaSource = new MediaSource()
  video.src = URL.createObjectURL(mediaSource)

  mediaSource.addEventListener('sourceopen', () => {
    const sourceBuffer = mediaSource.addSourceBuffer()
    const appendChunk = chunk => chunk.arrayBuffer().then(data => sourceBuffer.appendBuffer(data))
    sourceBuffer.addEventListener('updateend', () => {
      if (chunks[i]) {
        appendChunk(chunks[i++])
      } else {
        mediaSource.endOfStream()
      }
    })
    appendChunk(chunks[i++])
  })
}

jsfidle

Однако проблемы начинаются, когда я пытаюсь не добавлять все куски.

  • Как я могу пропустить начало записанного видео?
  • Если фрагмент отсутствует, возможно ли, что видео будет пустым на секунду, пока не появится новый фрагмент?

Я знаю, что записанный носитель содержит не только необработанные видеоданные, но и какую-то информацию заголовка. Но на данный момент у меня нет плана, что я делаю. Может, вы мне поможете:

  • Как я могу проверить эту информацию заголовка (не видеоданные)?
  • Могу я их отредактировать или добавить? Есть ли какие-нибудь хорошие ресурсы о том, как это сделать?

Моя цель - просто захватить любой из записанных фрагментов и затем воспроизвести в нем видеоданные. И если какой-то кусок отсутствует, он должен просто продолжить воспроизведение следующих фрагментов.

Задний план

Я пытаюсь разработать решение для потоковой передачи в реальном времени, которое работает p2p с webRTC. Я знаю, что могу поместить поток прямо в RtcConnection. Но насколько мне известно, это означает, что каждый одноранговый узел может передавать другому узлу только 1 полный поток. Было бы неплохо, если бы каждый партнер был более гибким в участии в прямом эфире, например. совместное использование 1.5 потоков. Поэтому я подумал, что имеет смысл поделиться этими данными через RtcDataChannels, собрать их и воспроизвести через MediaSource API. Если у вас есть другие идеи, как это сделать, я был бы очень признателен.


person Buntel    schedule 18.03.2021    source источник
comment
например, совместное использование 1,5 потоков, что это значит? Почему вы не можете запустить несколько подключений RTC, если хотите поделиться несколькими потоками? Что касается Y вашей проблемы X-Y, вам может повезти, и вам понадобится только первый кусок, но я бы не стал делать ставку на то, что это будет работать везде и всегда.   -  person Kaiido    schedule 18.03.2021
comment
Мне нужно разделить 1 полный поток на каждое соединение. Но что, если у однорангового узла нет возможности обработать еще один полный? Поэтому я хочу разделить его, если возможно   -  person Buntel    schedule 18.03.2021
comment
Но что значит разделить поток? Нравится только половина видео, а в аудио только частоты выше 800 Гц?   -  person Kaiido    schedule 18.03.2021
comment
Я точно не знаю. Это часть моей проблемы. Моя идея заключалась в том, чтобы разделить поток на блоки данных, которые я мог бы передать одноранговым узлам, а затем воспроизвести их с помощью MediaSource API.   -  person Buntel    schedule 18.03.2021
comment
Давайте сделаем шаг назад, с какой реальной проблемой вы сталкиваетесь и пытаетесь решить?   -  person Kaiido    schedule 18.03.2021
comment
Вы смотрели на мою скрипку? Мне удалось записать и воспроизвести видео с моего экрана. Проблема в том, что я не могу просто воспроизвести только половину, иначе он перестанет воспроизводиться, если я не добавлю кусок данных в sourceBuffer. Я хочу, чтобы видео воспроизводило то, что есть.   -  person Buntel    schedule 18.03.2021
comment
Но это Y вашей проблемы XY. И снова, пока есть первый фрагмент, он может работать сейчас, но нет никаких указаний на то, что он должен , поэтому он вполне может перестать работать в будущем без каких-либо причин (на самом деле он работает только в FF). Но в любом случае, похоже, это не поможет вам с вашей неясной проблемой X. Это то, что я хочу, чтобы вы четко объяснили. Разделение потока для меня ничего не значит, если я попытаюсь понять ваше объяснение, все, что я вижу, это то, что вам нужно запустить несколько RTC параллельно. Не думаю, что этому что-то мешает.   -  person Kaiido    schedule 18.03.2021
comment
Ваша скрипка вообще не работает. Я нажимаю поток запросов, но ничего не происходит. Я думаю, что мне нужно получить необработанные данные своих фрагментов и каким-то образом проверить и обработать мета и информацию заголовка, чтобы затем я поместил эти фрагменты в sourceBuffer. Но я не знаю, как это сделать.   -  person Buntel    schedule 18.03.2021


Ответы (1)


Однако проблемы начинаются, когда я пытаюсь не добавлять все куски.

You Can't Do That ™.

Эти потоки MediaRecorder начинаются с набора информации заголовка, необходимой для инициирования декодирования в MediaSource. И они не повторяют эту информацию.

И эта информация заголовка плохо сочетается с фрагментами, переданными в ondataavailable. Вздох.

Более того, сжатое видео (то, что вы получаете из getDisplayMedia / MediaRecorder) состоит из ключевых кадров и межкадров. Без ключевого кадра межкадры не имеют смысла.

Можно было бы проанализировать поток, чтобы захватить информацию заголовка. В Matroska это EMBL head элемент и Segment пролог. Затем вы можете отправить только это в MediaSource, а затем последний элемент Cluster. Но я не знаю никого, кто это сделал.

И, если вы пытаетесь провести сеанс «многие ко многим» (так называемый рой), каждый из ваших клиентов должен будет отправить все свои данные каждому другому клиенту. Это быстро становится непозволительно высокой пропускной способностью.

mediasoup и другие так называемые модули выборочной пересылки предлагают для этого серверно-ориентированное решение WebRTC. WebRTC содержит все необходимое для обновления источников потоковых данных - для отправки ключевых кадров по запросу.

person O. Jones    schedule 18.03.2021
comment
Можно было бы проанализировать поток, чтобы захватить информацию заголовка, как я могу это сделать? - person Buntel; 18.03.2021
comment
Шаг первый. Понять Матроску (формат видео / веб-бокса). Шаг второй: используйте код ebml в своем браузере, чтобы проанализировать поток и записать то, что вы хотите. Объяснение этого далеко выходит за рамки ответа на вопрос о переполнении стека, если только кто-то еще не создал для этого пакет. Я нет. - person O. Jones; 18.03.2021