2

背景:

我正在开发一个系统,其中一部分是 WebRTC 视频(或音频)呼叫。该解决方案包括大量构建在getUserMediaRTCPeerConnection API-s 支持之上的业务逻辑。特别是因为 Firefox 和 Chrome 以不同的方式实现了一些 API-s(例如MediaStream#getAudioTracks,在 Firefox 上总是返回 [])。

测试要求示例:

两方正在进行音频-音频通话(双方都被询问并允许音频流(访问麦克风))。一方希望将呼叫升级为视频-视频。发生某些 UI 交互 - 与升级发起者对话以确认他的操作并向接收者提供升级提议,双方都允许相机访问。最终应该建立视频-视频通话。

问题:

如何检查 MediaStream 实例是否处于这样的状态,如果附加到<video>element src,那么将播放正确的信号(视频,音频)?

到目前为止的想法

最基本的测试是检查是否RTCPeerConnection#onstreamadded被调用。问题在于,有时回调会被MediaStream实例调用,但是当将它附加到<video>元素时,什么都不会显示。这很可能是我的一个错误,这就是测试应该告诉我的。

是否有一些好的属性或回调RTCPeerConnectionMediaStream对象可以告诉我何时正确设置通信并且数据何时通过流?

4

2 回答 2

0

视频元素是否显示黑色背景并在 src 属性中包含一个 blob?如果是这样,请注意视频元素在 FF 中也必须区别对待。在 Chrome 中,自动播放标签(例如<video src="blobIsHere" autoplay></video>)足以启动视频。在 FF 中,您需要调用元素的 .play() 方法。此外,视频元素必须在 FF 中以不同方式创建。它应该看起来像这样:

    var el = document.getElementById('my-video');
    if(el.mozSrcObject !== undefined) {
        el.mozSrcObject = remoteStream;
        el.play();
    }

如果你想添加 Firefox 支持,我建议使用adapter.js

要检查连接是否建立,您可以阅读 ICE 状态,即:

    con.onaddstream = function(e){
        if(e.srcElement.iceConnectionState === 'connected' &&
           e.srcElement.iceGatheringState === 'complete') {
            // attach to video-element
        }
    };

另一个原因可能是只发送了视频。要找出远程客户端正在流式传输的媒体类型,您必须检查远程 SDP 是否有此子字符串:'a=recvonly'。如果存在,则仅流式传输音频。例子:

con.onaddstream = function(e){
    if (e.target.remoteDescription.sdp.indexOf('a=recvonly') > -1) {
        // video and audio
    }
    else {
        // only audio
    }
}

注意:我刚刚发现了这一点,因为我正在尝试做类似的事情。我不确定这是否 100% 安全以及是否适合所有情况(音频和视频/仅音频/仅视频),但值得一试。

于 2013-08-26T14:50:14.797 回答
0

我实现了一个解决方案,其中使用了 RTCStatsReport 对象,可以通过在 RTCPeerConnection 上使用 getStats() 来检索该对象。

我用接收到的入站 rtp 字节设置了一个变量,并每隔 x 秒更新一次。如果接收到的字节停滞/不改变,则意味着流不再发送任何数据并且很可能已损坏。然后触发重新连接过程。

const x = 7000 // seven seconds
let bytesReceived = -1 // init to -1 so reconnect does not get triggered on launch

// Set up interval that checks every x ms
const interval = setInterval(() => {
  // load stats
  rtcConnections.getStats().then(
      (report: RTCStatsReport) => {
          const br = bytesReceived

          // loop through every possible report
          report.forEach(k => {
              // Here it is implemented for the inbound video
              // but of course you can do it analogeous for outbound and audio
              if (k.type === "inbound-rtp" && k.kind === "video") {

                  // if bytes did not change start reconnection procedure and reset interval
                  if (br === k.bytesReceived) {
                      console.log(`Stream does not send any data.`)
                      clearInterval(interval)
                      // Handle reconnection procedure
                  }
                  bytesReceived = k.bytesReceived
              }
          })
      }
  )
}, x)

在这里您可以找到 RTCStatsReport 的文档。

于 2021-11-10T11:21:20.860 回答