2

我正在将 AttachMediaStream 集成到使用 React 的程序中。

我可以将媒体流附加到这样的元素:

var vid = document.getElementById("myVideo");
attachMediaStream(vid, stream);

但这不在 React Render 方法之外,我认为应该发生这样的事情。

如果我把它按原样放在React Render 方法中,它会在每次 Render 方法运行时运行。

这是我想到的一种方法:

  • 向组件添加两个变量:
    • this.mediaStreamNeedsToBeAttached
    • this.props.mediaStream
  • 请注意,this.mediaStreamNeedsToBeAttached它不是this.stateor的一部分this.props。如果是,在 Render 方法中切换它是不合法的。
  • 获取媒体流时,组件:
    • 设置this.mediaStreamNeedsToBeAttached为真;
    • 运行this.setProps({ mediaStream: newlyObtainedMediaStream });导致 Render 方法运行。
  • 渲染方法:
    • 检查是否this.mediaStreamNeedsToBeAttached为真
    • 如果是这样,运行attachMediaStream(vid, this.props.mediaStream)并切换this.mediaStream

这会起作用,但我想我会在这里查看是否有其他人有更优雅的解决方案。

任何想法或意见将不胜感激!

4

2 回答 2

1

2018 年 10 月更新

根据这篇文章,我了解到 React 目前与领先的 WebRTC 服务提供商 100% 不兼容。到目前为止,我与两个 WebRTC 服务提供商合作过,它们都需要 dom 元素的 ID,并将视频流附加到它,而不是通过 React,而是通过直接 dom 操作。在 React 渲染中,这些流会间歇性地从完成的渲染中丢失。

它间歇性的原因是因为存在竞争条件。React 将运行渲染函数,并且您的 WebRTC 代码独立地订阅视频流并尝试将其附加到渲染创建的元素。如果订阅尝试将视频流附加到元素,则在渲染函数创建它之前,完成的渲染中缺少流。

根据同一篇文章,解决方案是通过 dom 操作插入所有与 WebRTC 相关的 dom 元素,从而将 React 与 WebRTC 完全分离,例如:

        let elDialUIContainer = document.querySelector('#dialComponentUIContainer');

        if (!elDialUIContainer) {
            elDialUIContainer = document.createElement('div');
            elDialUIContainer.setAttribute('id', 'dialComponentUIContainer');
            elDialUIContainer.setAttribute('style', this.styleObjectToString(styles.dialComponentUIContainer));
            elContentContainer.prepend(elDialUIContainer);
        }

       [.....]

        if (localThis.applicationState.remoteVideoStream) {
            console.log('attaching remoteVideoStream to #video' + localThis.applicationState.remoteVideoStream.getId());
            let elOtherCallerVideoStream = document.querySelector('#video' + localThis.applicationState.remoteVideoStream.getId());
            if (!elOtherCallerVideoStream) {
     localThis.applicationState.remoteVideoStream.play('remoteCallerVideo');
            }
        }

...ETC。这些元素被添加到一个 dom 元素中,该元素位于该组件的 React 渲染函数生成的元素之上和之外——因此当该渲染函数运行时它们不会受到影响。

我有一个函数,addWebRTCElements将这些元素添加到 dom。它由 调用ComponentDidMount(),并且每次发生 WebRTC 事件时也会调用它,例如远程流进来。

过时:2018 年 9 月更新

这是另一种方法,使用 React createRef()

  1. 获取视频元素的 React 引用。在 React 组件构造函数中:

    this.refToMyVideo = React.createRef();

  2. 将 html 元素附加到此 ref。在 React 渲染函数中:

<video ref={this.refToMyVideo}>
</video>
  1. 当视频流可用时使用 ref:
let vidElement = this.refToMyVideo.current;
attachMediaStream(vidElement, stream);
vidElement.onloadedmetadata = function(e) {
  vidElement.play();
};

关于 React createRef 的文档在这里

过时:从 2017 年 12 月开始:

@jordan,我认为您提出了一个很好的观点:“访问虚拟 dom 的方式不连续以及 attachMediaStream 的工作方式。”

这是我的处理方式。到目前为止,它似乎正在工作,尽管可能有一个更优雅的解决方案。

function attachMediaStreamToElement(idToWaitFor, stream){
        const elementExists = $(idToWaitFor).length > 0;
        if (elementExists) {
            const idToWaitForMinusPoundSign = idToWaitFor.replace("#", "");
            var vid = document.getElementById(idToWaitForMinusPoundSign);
            attachMediaStream(vid, stream);
        }
        else {
            setTimeout(function () {
                attachMediaStreamToElement(idToWaitFor, idToWaitFor, stream)
            }, 50);
        }
    }

一旦流可用,我就会调用它。该例程等待 Render 函数渲染目标元素,然后将流附加到它。

于 2017-12-25T00:51:54.360 回答
0

我也遇到了麻烦,似乎在访问虚拟 dom 的方式和attachMediaStream工作方式方面存在一些不连续性。

我将MediaStream对象置于状态并尝试调用attachMediaStream它......但无论出于何种原因,它都没有附加。

(我使用的是redux)但概念是一样的):

 componentDidMount = () => {
        setTimeout((function () {
            console.log('Attaching media stream')
            attachMediaStream(this.props.stream, this.video);
        }).bind(this), 0);
}

render() {
       return ( 
             <video  ref={(video) => { this.video = video; }} />
       )    
}

我使用ref( https://reactjs.org/docs/refs-and-the-dom.html ) 来获取虚拟媒体元素,并调用它,componentDidMount因为它可以访问 DOM 但不修改状态。

于 2017-12-24T07:09:56.580 回答