RTCDataChannel 的 "bufferedamountlow" 事件未在 Safari 中触发?

RTCDataChannel's "bufferedamountlow" event not firing in Safari?

我正在从事一个利用 WebRTC 进行文件传输的项目,最近有人报告说 an issue 说对于较大的文件传输会过早结束。我找到了问题所在,我解决这个问题的方法是依靠 bufferedamountlow 事件来协调块的发送。当发件人认为连接完成时,我也停止关闭连接。

但是,出于某种原因,在 Safari 中该事件不会触发。

相关代码如下:

const connection = new RTCPeerConnection(rtcConfiguration);

const channel = connection.createDataChannel('sendDataChannel');
channel.binaryType = 'arraybuffer';

channel.addEventListener('open', () => {
    const fileReader = new FileReader();
    let offset = 0;

    const nextSlice = (currentOffset: number) => {
        // Do asynchronous thing with FileReader, that will result in
        // channel.send(buffer) getting called.
        // Also, offset gets increased by 16384 (the size of the buffer).
    };

    channel.bufferedAmountLowThreshold = 0;
    channel.addEventListener('bufferedamountlow', () => nextSlice(offset));

    nextSlice(0);
});

The longer version of my code is available here.

在研究这个问题时,我意识到在 Safari 上,我的 connection.stcp 是未定义的。 (因为我的缓冲区大小已切换到 connection.sctp.maxMessageSize 而不是 16384。)我认为问题与此有关。

导致此问题的原因可能是什么?让我补充一点,在 Chrome 和 Firefox 上一切正常,没有任何问题。

我的代码的正常运行不需要 bufferedamountlow 事件,但我希望它能正常工作,以便更准确地估计文件发送端的当前进度和速度转让.

经过一番调查后,我发现 Safari 将 0 作为 bufferedAmountLowThreshold 属性.

的值存在问题

设置为非零值时,代码正常运行。

检查 nextSlice 函数内部的 bufferedAmount 也会提高发送块的速度:

const bufferSize = connection.sctp?.maxMessageSize || 65535;

channel.addEventListener('open', () => {
  const fileReader = new FileReader();
  let offset = 0;

  const nextSlice = (currentOffset: number) => {
    const slice = file.slice(offset, currentOffset + bufferSize);
    fileReader.readAsArrayBuffer(slice);
  };

  fileReader.addEventListener('load', e => {
    const buffer = e.target.result as ArrayBuffer;

    try {
      channel.send(buffer);
    } catch {
      // Deal with failure...
    }

    offset += buffer.byteLength;

    if (channel.bufferedAmount < bufferSize / 2) {
      nextSlice(offset);
    }
  });

  channel.bufferedAmountLowThreshold = bufferSize / 2;
  channel.addEventListener('bufferedamountlow', () => nextSlice(offset));

  nextSlice(0);
});