WebRTC音视频开发:React+Flutter+Go实战
上QQ阅读APP看书,第一时间看更新

4.3 打开摄像头

这里我们通过一个打开摄像头的示例来熟悉一下如何获取摄像头数据,并且渲染至视频对象上。具体步骤如下所示。

步骤1 打开h5-samples工程下的src目录,添加Camera.jsx文件。定义约束条件,这里启用视频、禁用音频,代码如下所示。


//约束条件
const constraints = window.constraints = {
    //禁用音频
    audio: false,
    //启用视频
    video: true
};

步骤2 根据约束条件获取媒体,调用getUserMedia()方法,即可请求摄像头。代码如下所示。


//根据约束条件获取媒体
const stream = await navigator.mediaDevices.getUserMedia(constraints);

这里使用async/await关键字来处理异步操作。获取设备是一个I/O操作,需要消耗一定的时间,所以可以看到在方法前加了一个await,这样就不用写回调函数了。

步骤3 当成功获取视频流后,将其传递给video对象的srcObject即可,这样视频流就会源源不断地向video对象输出并渲染出来。大致处理如下所示。


//成功返回视频流
handleSuccess = (stream) => {
    //获取video对象
    ...
    //将video对象的视频源指定为stream
    video.srcObject = stream;
}

步骤4 在页面渲染部分添加video标签,video是HTML5标准的一个重要组成部分,可以用来播放视频。代码如下所示。


//autoPlay 视频自动播放
//playsInline不希望用户拖动
<video autoPlay playsInline></video>

这里我们添加了两个属性,作用如下所示。

·autoPlay:视频自动播放,用户不需要点击播放按钮。

·playsInline:防止用户拖动滚动条,由于不是点播视频,所以不要求快速。

步骤5 在src目录下的App.jsx及Samples.jsx里加上链接及路由绑定,这可以参考第3章。完整的代码如下所示。


import React from "react";
import { Button, message } from "antd";

//约束条件
const constraints = window.constraints = {
    //禁用音频
    audio: false,
    //启用视频
    video: true
};

/**
 * 摄像头使用示例
 */
class Camera extends React.Component {
    constructor() {
        super();
    }

    //打开摄像头
    openCamera = async (e) => {
        try {
            //根据约束条件获取媒体
            const stream = await navigator.mediaDevices.getUserMedia(constraints);
            console.log('handleSuccess:');
            this.handleSuccess(stream);
        } catch (e) {
            this.handleError(e);
        }
    }

    handleSuccess = (stream) => {
        const video = this.refs['myVideo'];
        const videoTracks = stream.getVideoTracks();
        console.log('通过设置限制条件获取到流:', constraints);
        console.log(`使用的视频设备: ${videoTracks[0].label}`);
        //使得浏览器能访问到stream
        window.stream = stream; 
        video.srcObject = stream;
    }

    handleError(error) {
        if (error.name === 'ConstraintNotSatisfiedError') {
            const v = constraints.video;
            //宽高尺寸错误
            message.error(`宽:${v.width.exact} 高:${v.height.exact} 设备不支持`);
        } else if (error.name === 'PermissionDeniedError') {
            message.error('没有摄像头和麦克风使用权限,请点击允许按钮');
        }
        message.error(`getUserMedia错误: ${error.name}`, error);
    }

    render() {
        return (
            <div className="container">
                <h1>
                    <span>摄像头示例</span>
                </h1>
                <video className="video" ref="myVideo" autoPlay playsInline></video>
                <Button onClick={this.openCamera}>打开摄像头</Button>
            </div>
        );
    }
}
//导出组件
export default Camera;

可以看到,当获取到媒体数据流后,可以通过stream.getVideoTracks()得到视频轨道,然后再通过videoTracks[0].label获取到摄像头的名称。输出内容如下所示。


使用的视频设备: FaceTime HD Camera

运行程序后,打开摄像头示例,点击“打开摄像头”按钮,运行效果如图4-1所示。

图4-1 摄像头示例