Видео / аудио потоки WebRTC не синхронизированы (MediaStream -> MediaRecorder -> MediaSource -> Video Element) - PullRequest
0 голосов
/ 02 сентября 2018

Я беру MediaStream и объединяю две отдельные дорожки (видео и аудио), используя холст и API WebAudio. Сам MediaStream, похоже, не выходит из строя, но после чтения его в MediaRecorder и буферизации его в элемент видео, звук всегда будет воспроизводиться намного раньше, чем видео. Вот код, который, кажется, имеет проблему:

let stream = new MediaStream();

// Get the mixed sources drawn to the canvas
this.canvas.captureStream().getVideoTracks().forEach(track => {
  stream.addTrack(track);
});

// Add mixed audio tracks to the stream
// https://stackoverflow.com/questions/42138545/webrtc-mix-local-and-remote-audio-steams-and-record
this.audioMixer.dest.stream.getAudioTracks().forEach(track => {
  stream.addTrack(track);
});

// stream = stream;
let mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm;codecs=opus,vp8' });

let mediaSource = new MediaSource();
let video = document.createElement('video');
video.src = URL.createObjectURL(mediaSource);
document.body.appendChild(video);
video.controls = true;
video.autoplay = true;

// Source open
mediaSource.onsourceopen = () => {
  let sourceBuffer = mediaSource.addSourceBuffer(mediaRecorder.mimeType);

  mediaRecorder.ondataavailable = (event) => {

    if (event.data.size > 0) {
      const reader = new FileReader();
      reader.readAsArrayBuffer(event.data);
      reader.onloadend = () => {
        sourceBuffer.appendBuffer(reader.result);
        console.log(mediaSource.sourceBuffers);
        console.log(event.data);
      }
    }
  }
  mediaRecorder.start(1000);
}

AudioMixer.js

export default class AudioMixer {

  constructor() {
    // Initialize an audio context
    this.audioContext = new AudioContext();

    // Destination outputs one track of mixed audio
    this.dest = this.audioContext.createMediaStreamDestination();

    // Array of current streams in mixer
    this.sources = [];
  }

  // Add an audio stream to the mixer
  addStream(id, stream) {
    // Get the audio tracks from the stream and add them to the mixer
    let sources = stream.getAudioTracks().map(track => this.audioContext.createMediaStreamSource(new MediaStream([track])));
    sources.forEach(source => {

      // Add it to the current sources being mixed
      this.sources.push(source);
      source.connect(this.dest);

      // Connect to analyser to update volume slider
      let analyser = this.audioContext.createAnalyser();
      source.connect(analyser);
      ...
    });
  }

  // Remove all current sources from the mixer
  flushAll() {
    this.sources.forEach(source => {
      source.disconnect(this.dest);
    });

    this.sources = [];
  }

  // Clean up the audio context for the mixer
  cleanup() {
    this.audioContext.close();
  }
}

Я предполагаю, что это связано с тем, как данные помещаются в буфер MediaSource, но я не уверен. Что я делаю, что десинхронизирует поток?

1 Ответ

0 голосов
/ 31 июля 2019

Поздний ответ на старый пост, но это может кому-то помочь ...

У меня была точно такая же проблема: у меня есть видеопоток, который должен быть дополнен аудиопотоком. В аудиопотоке время от времени воспроизводятся короткие звуки (AudioBuffer). Все это записывается через MediaRecorder. Все отлично работает на Chrome. Но в Chrome для Android все звуки воспроизводились в быстрой последовательности. Параметр «когда» для «play ()» был проигнорирован в Android. (audiocontext.currentTime продолжал увеличиваться с течением времени ... - это было не главное).

Мое решение похоже на комментарий Джейкоба 2 сентября 18 августа в 7:41: Я создал и подключил синусоидальный генератор с неслышимыми 48 000 Гц, который постоянно воспроизводился в аудиопотоке во время записи. По-видимому, это приводит к правильному прогрессу времени.

...