【问题标题】:React - can't stream video from webcamReact - 无法从网络摄像头流式传输视频
【发布时间】:2018-11-09 12:55:10
【问题描述】:

我正在尝试将我的组件修复为从网络摄像头流式传输数据。它成功渲染并成功访问网络摄像头。但我不知道为什么视频标签不播放任何东西。如何解决这个问题?我错过了什么?

export class WebcamStream extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            src: null
        }
        this.videoRef = React.createRef()
    }

    componentDidMount() {
        // getting access to webcam
        navigator.mediaDevices
            .getUserMedia({video: true})
            .then(stream => this.setState({src: stream}))
            .catch(console.log);
    }

    render() {
        return <video id={this.props.id}
                      ref={() => this.videoRef.srcObject = this.state.src}
                      width={this.props.width}
                      height={this.props.height}
                      autoPlay="autoplay"
                      title={this.props.title}></video>
    }
}

【问题讨论】:

    标签: reactjs html5-video webcam


    【解决方案1】:

    嗯,我找到了问题所在。根据docs,我需要使用current 属性来使节点可访问。所以,我的网络摄像头组件的完整工作示例:

    export class WebcamStream extends React.Component {
        constructor(props) {
            super(props);
            this.videoTag = React.createRef()
        }
    
        componentDidMount() {
            // getting access to webcam
           navigator.mediaDevices
                .getUserMedia({video: true})
                .then(stream => this.videoTag.current.srcObject = stream)
                .catch(console.log);
        }
    
        render() {
            return <video id={this.props.id}
                          ref={this.videoTag}
                          width={this.props.width}
                          height={this.props.height}
                          autoPlay
                          title={this.props.title}></video>
        }
    }
    

    this.setState 在直接 srcObject 从承诺更改之前被删除,但我不确定这是否是 React 方式。也许,更正确的是将this.videoTag.current.srcObject = stream 代码移动为 setState 回调?

    【讨论】:

    • 它看起来很干净,可以说它是反应方式。如果你使用 set-state 来存储 src,你可以直接使用 video 标签的 src 属性而不需要 ref 回调。另一种解决方案是在 src 已经可用后按需渲染视频标签。如果 src 不可用则渲染 null,如果 src 可用则渲染视频。
    【解决方案2】:

    ref 在此行中未正确使用:

    ref={() => this.videoRef.srcObject = this.state.src}
    

    在您的代码中,只需将src 设置为未初始化的videoRef,因此它永远不会到达视频标签。

    你可以试试:

    ref={this.videoRef.srcObject}
    

    并且在componentDidMount中:

    .then(stream => {this.videoRef.srcObject = stream})
    

    或者简单地说:

    ref={(e) => e.srcObject = this.state.src}
    

    【讨论】:

    • 感谢您的回答。我已经尝试根据您的示例更新我的 render() 方法,但是当我将 ref 更改为 ref={(e) =&gt; e.srcObject = this.state.src} 时,我得到了下一个错误:TypeError: Cannot set property 'srcObject' of null
    • 顺便说一句,ref={(e) =&gt; e.srcObject = this.state.src} 会损害性能,因为每次重新渲染都会创建新函数
    • 公平地说,如果您正在加载一个已经使用大量资源的视频,并且您也不打算多次重新渲染该组件...函数的创建是最新的一个关心优化。
    【解决方案3】:

    对我有用的组件如下

    import React, { useState, useEffect } from 'react';
    
    export default function ModalVideo(props) { 
        const [video,]=useState(React.createRef());
    
        const videoError=(error)=>{
            console.log("error",error);
        }
    
        const handleVideo=(stream)=>{
            video.current.srcObject = stream;
        }
    
        useEffect(() => {
            navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
            if (navigator.getUserMedia) {
                navigator.getUserMedia({video: true}, handleVideo, videoError);
            }
        });
    
        return (
            <div>
                <video ref={video}  autoPlay={true} />
            </div>
        )
    }
    

    【讨论】:

      【解决方案4】:

      当使用上面相同的代码时,我也面临同样的错误,它显示“_this2.video 未定义;无法访问其“当前”属性”并且一切正常,获得视频许可,但它没有显示视频我的页面。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-22
        • 2013-05-14
        相关资源
        最近更新 更多