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

4.6 共享屏幕

在视频会议系统里共享屏幕是一项重要的功能,即把你的计算机桌面或者某一个应用窗口分享给其他人观看。这里主要阐述的是如何将应用窗口采集到屏幕画面,可以使用WebRTC的navigator.mediaDevices.getDisplayMedia()方法获取屏幕数据。

接下来通过一个例子来展示如何共享屏幕,具体步骤如下所示。

步骤1 打开h5-samples工程下的src目录,添加ScreenShare.jsx文件。编写捕获屏幕方法,添加约束条件,只需要设置{video:true}即可。代码如下所示。


const stream = await navigator.mediaDevices.getDisplayMedia({video: true});

约束条件只需要设置{video:true}的目的是将其转化成视频流,这里不需要设置宽高约束,这样可以使得共享出来的屏幕达到清晰的效果。

getDisplayMedia()是一个特殊方法,需要与getUserMedia()区分开来。旧的Chrome浏览器需要安装扩展插件才可以使用,新版的Chrome则不需要。

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


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

步骤3 在页面渲染部分添加video标签,由于现在已经将捕获到的屏幕数据转化成视频流了,所以可以在video对象里进行渲染。代码如下所示。


{/* 捕获屏幕数据渲染 */}
<video autoPlay playsInline></video>

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


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

/**
 * 共享屏幕示例
 */
class ScreenSharing extends React.Component {

    //开始捕获桌面
    startScreenShare = async (e) => {
        try {
            //调用getDisplayMedia()方法,约束设置成{video:true}即可
            const stream = await navigator.mediaDevices.getDisplayMedia({video: true});
            console.log('handleSuccess:');
            this.handleSuccess(stream);
        } catch (e) {
            this.handleError(e);
        }
    }

    //成功捕获,返回视频流
    handleSuccess = (stream) => {
        const video = this.refs['myVideo'];
        //获取视频轨道
        const videoTracks = stream.getVideoTracks();
        //读取视频资源名称
        console.log(`视频资源名称: ${videoTracks[0].label}`);
        window.stream = 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.startScreenShare}>开始共享</Button>
            </div>
        );
    }
}
//导出组件
export default ScreenSharing;

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


视频资源名称: screen:1127248311:0

运行程序后,打开共享屏幕示例,点击“开始共享”按钮,会弹出一个对话框让你选择要捕获的屏幕或应用窗口,如图4-4所示。

当选择了某个整个屏幕或应用窗口后,画面就会呈现在视频对象上,此时屏幕上有任何操作,都可以同步、实时地在视频里播放,如图4-5所示。

图4-4 共享屏幕选择窗口

图4-5 共享屏幕显示效果图

与此同时,Chrome浏览器会弹出一个小的对话框,可以点击“停止共享”按钮随时停止捕获屏幕,如图4-6所示。

图4-6 停止共享对话框