【问题标题】:WebRTC video/audio streams out of sync (MediaStream -> MediaRecorder -> MediaSource -> Video Element)WebRTC 视频/音频流不同步(MediaStream -> MediaRecorder -> MediaSource -> Video Element)
【发布时间】:2021-09-13 21:53:50
【问题描述】:

我正在使用一个 MediaStream 并使用画布和 WebAudio API 合并两个单独的轨道(视频和音频)。 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 缓冲区的方式有关,但我不确定。我在做什么使流不同步?

【问题讨论】:

  • 当您将录制的文件作为一个整体播放而不是将其块作为 MSE 的缓冲区播放时,它是否也会不同步?
  • 我根本不记录流,我只是使用 MediaRecorder 对象读取块以便稍后发送。我刚刚将它通过管道传输到一个文件并尝试它,它似乎仍然不同步。
  • 还要注意这个小提琴:jsfiddle.net/nthyfgvs 似乎保持同步,但这是使用单个 getUserMedia 调用,而不是我用来填充画布/audioMixer 的许多单独调用。
  • ;-) 你正在录制它。你不保存块是另一回事。现在我们发现 MSE 不是问题所在。因此,暂时不要使用它,直到您找到真正导致问题的原因。如果您只将流作为<video> 的 srcObject 传递(即没有记录)怎么办?如果你对你的录音机强制使用一个常量 bitsPerSecond 怎么办?
  • @JacobGreenway 你能提供你的解决方案的代码 sn-p 吗?

标签: webrtc web-audio-api media-source mediastream web-mediarecorder


【解决方案1】:

对旧帖子的回复较晚,但它可能对某人有所帮助......

我遇到了完全相同的问题:我有一个视频流,应该辅以音频流。在音频流中不时播放短声音(AudioBuffer)。整个过程是通过 MediaRecorder 记录的。 在 Chrome 上一切正常。但在 Android 版 Chrome 上,所有声音都会快速连续播放。 “play()”的“when”参数在 Android 上被忽略。 (audiocontext.currentTime 随着时间的推移继续增加...... - 这不是重点)。

我的解决方案类似于 Jacob 在 2018 年 9 月 2 日 7:41 发表的评论: 我创建并连接了一个 48,000 赫兹听不见的正弦波振荡器,它在录制过程中在音频流中永久播放。显然这会导致适当的时间进度。

【讨论】:

  • 在 Martin Luckow,正如您所说,我正在创建正弦波振荡器,例如:var ac = new AudioContext({ sampleRate: 48000}); var osc = ac.createOscillator(); var mediaRecorder = new MediaRecorder(stream); osc.connect(ac.destination);,仍然存在同步问题,我在上面的代码中做错了吗?您能否在答案中添加一些代码 sn-p ?
【解决方案2】:

发送多个相关 RTP 流的 RTP 端点 要求在其他端点同步必须使用相同的 要同步的所有流的 RTCP CNAME。这个 需要一个短期持久的 RTCP CNAME 几个 RTP 流,并且可能跨越几个相关的 RTP 会议。口型同步音频时会出现此类使用的常见示例 和多媒体会话中的视频流,其中单个参与者 必须为其音频 RTP 会话使用相同的 RTCP CNAME 视频 RTP 会话。另一个例子可能是同步 分层音频编解码器的层,其中必须具有相同的 RTCP CNAME 用于每一层。

https://datatracker.ietf.org/doc/html/rfc6222#page-2

【讨论】:

    【解决方案3】:

    Chrome 中存在一个错误,它会播放 44100KHz 的缓冲媒体流音频,即使它是用 48000 编码的(这会导致间隙和视频不同步)。所有其他浏览器似乎都可以正常播放。您可以选择将编解码器更改为支持 44.1KHz 编码的编解码器或从网络链接播放文件作为源(这样 Chrome 才能正确播放)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-11
      • 1970-01-01
      • 2021-11-08
      • 1970-01-01
      • 2012-03-16
      • 1970-01-01
      • 1970-01-01
      • 2018-10-13
      相关资源
      最近更新 更多