功能简介

Agora RTC Web SDK 支持在视频通话或互动直播中进行屏幕共享,将说话人或主播的屏幕内容,以视频画面的方式分享给其他说话人或观众观看,以提高沟通效率。屏幕共享在如下场景中应用广泛:

  • 视频会议场景中,屏幕共享可以将讲话者本地的文件、数据、网页、PPT 等画面分享给其他与会人;
  • 在线课堂场景中,屏幕共享可以将老师的课件、笔记、讲课内容等画面展示给学生观看。
Web SDK 仅支持在以下桌面端浏览器中进行屏幕共享:
  • Chrome 58 或以上版本。
  • Firefox 56 或以上版本。
  • Windows 10+ 平台上的 Edge 80 及以上版本。
  • 点击在线体验试用屏幕共享功能。

    工作原理

    Web 端屏幕共享,实际上是通过创建一个屏幕共享的流来实现的。开始屏幕共享前,你需要在创建流的时候配置某些属性。不同浏览器在创建流的时候,相关的属性是不同的。建流的过程中浏览器会询问需要共享哪些屏幕,根据用户的选择去获取屏幕信息。

    • 如果只使用屏幕共享,则在新建流的时候,把 video 字段设为 falsescreen 字段设为 true 即可。
    • 如果在使用屏幕共享的同时,还开启本地视频采集,则需要创建两个 Client 对象,一路发送屏幕共享流,一路发送本地采集视频流。新建流的时候,屏幕共享流的 video 字段设为 falsescreen 字段设为 true;本地采集视频流的 video 字段设为 truescreen 字段设为 false。由于屏幕共享流也是一路流,因此也会占用一个 UID。

    自 3.2.0 版本起,Web SDK 支持在创建流时通过 optimizationMode 字段设置流的传输优化策略。对于屏幕共享流,该字段默认值为 "detail",SDK 会优先保障清晰度,适用于屏幕共享图片、文字等内容。如果你屏幕共享的内容为视频,你可以把 optimizationMode 字段设为 "motion",SDK 会优先保障流畅性。

    实现方法

    本节介绍如何在 Chrome、Edge、Firefox 浏览器和 Electron 框架中进行屏幕共享。

    开始屏幕共享前,请确保你已了解如何实现音视频通话实现互动直播

    Chrome 屏幕共享

    Web SDK 支持在 Chrome 58 及以上版本上进行屏幕共享。有两种方式:无插件屏幕共享和使用屏幕共享插件。

    无插件屏幕共享需同时满足以下两个要求:

    • Web SDK 2.6.0 或以上版本。
    • Chrome 72 或以上版本。

    如果无法满足上述要求,请使用屏幕共享插件实现在 Chrome 上共享屏幕。

    无插件屏幕共享

    直接调用 createStream 创建屏幕共享流,把 video 字段设为 falsescreen 字段设为 true即可。

    // Check if the browser supports screen sharing without an extension
    Number.tem = ua.match(/(Chrome(?=\/))\/?(\d+)/i);
    if(parseInt(tem[2]) >= 72  && navigator.mediaDevices.getDisplayMedia ) {
     // Create the stream for screensharing
        screenStream = AgoraRTC.createStream({
            streamID: uid,
            audio: false,
            video: false,
            screen: true,
        });
    }

    使用屏幕共享插件

    使用屏幕共享插件的步骤如下:

    1. 安装 Agora 提供的 Chrome 屏幕共享插件,并获取插件的 extensionId
    2. 调用 createStream 创建屏幕共享流时,把 video 字段设为 falsescreen 字段设为 true ,同时传入 extensionId
    screenStream = AgoraRTC.createStream({
      streamID: uid,
      audio: false,
      video: false,
      screen: true,
      //chrome extension ID
      extensionId: 'minllpmhdgpndnkomcoccfekfegnlikg'
    });

    Edge 屏幕共享

    Web SDK 支持在 Windows 10+ 平台上的 Edge 80 及以上版本上进行屏幕共享。

    直接调用 createStream 创建屏幕共享流,把 video 字段设为 falsescreen 字段设为 true 即可。

    screenStream = AgoraRTC.createStream({
      streamID: uid,
      audio: false,
      video: false,
      screen: true,
    });

    Firefox 屏幕共享

    Web SDK 支持在 Firefox 56 及以上版本上进行屏幕共享。

    你需要在调用 createStream 创建屏幕共享流时把 video 字段设为 falsescreen 字段设为 true,同时设置 mediaSource 指定分享屏幕的类型。mediaSource 的选择如下:

    • screen: 分享整个显示器屏幕。
    • application: 分享某个应用的所有窗口。
    • window: 分享某个应用的某个窗口。

    Firefox 在 Windows 平台不支持 application 模式。

    screenStream = AgoraRTC.createStream({
      streamID: uid,
      audio: false,
      video: false,
      screen: true,
      mediaSource: 'screen' // 'screen', 'application', 'window'
    });

    Electron 屏幕共享

    Electron 屏幕共享的选择界面需要你自行绘制。

    为方便快速集成,我们提供一个默认的选择界面。使用默认选择界面进行屏幕共享的步骤如下:

    1. 调用 AgoraRTC.createStream,将 video 设为 falsescreen 设为 true,创建屏幕共享流。

       localStream = AgoraRTC.createStream({
         streamID: UID,
         audio: false,
         video: false,
         screen: true
       });
       localStream.init(function(stream) {})
    2. 调用 localStream.init ,SDK 会提供自带的默认界面让用户选择要共享的屏幕或窗口,如下图所示:

    如果你需要自定义选择界面,参考以下步骤:

    1. 调用 AgoraRTC.getScreenSources 方法获取可共享的屏幕信息。

       AgoraRTC.getScreenSources(function(err, sources) {
           console.log(sources)
       })

      sources 是一个 source 对象的列表,source 里包含了分享源的信息和 sourceIdsource 的属性如下:

      • id: 即 sourceId
      • name: 屏幕源的名字。
      • thumbnail: 屏幕源的快照。
    2. 根据 source 的属性,(用 html 和 css)绘制选择界面,让终端用户选择要共享的屏幕源。

      source 的属性与屏幕共享的选择界面对应关系如下:

    3. 获取终端用户选择的 sourceId

    4. 调用 AgoraRTC.createStream, 将 video 设为 falsescreen 设为 true,并传入 sourceId,就能创建相应的屏幕共享流了。

       localStream = AgoraRTC.createStream({
           streamID: UID,
           audio: false,
           video: false,
           screen: true,
           sourceId: sourceId
       });
       localStream.init(function(stream) {})
      • getScreenSources 方法是对 Electron 提供的 desktopCapturer.getSources 进行的封装,详情可参考 desktopCapturer
      • 在非 Electron 下传入 sourceId 会被忽略。

    分享音频

    Web SDK 自 3.0.0 版本起支持在 Windows 平台的 Chrome 浏览器 74 及以上版本上同时共享屏幕和本地播放的背景音。如需实现分享音频,在调用 createStream 创建屏幕共享流时把 screen 字段和 screenAudio 字段都设为 true 即可。

    注意事项:
    • 在创建屏幕共享的流时要注意区分 audioscreenAudio 字段:
      • audio 字段用于控制创建的流中是否包含由本地音频输入设备采集的音频。
      • screenAudio 字段用于控制创建的流中是否包含本地播放的声音。
      我们建议在屏幕共享的流中将 audio 设为 false。如果 screenAudioaudio 都设置为 true,屏幕共享流中只会包含本地播放的背景音。
    • 设置了 screenAudiotrue 后,还需要在屏幕共享的弹出框上勾选分享音频才能真正生效。
    • 如果选择共享单个应用窗口无法使用分享音频功能。
    screenStream = AgoraRTC.createStream({
      streamID: uid,
      audio: false,
      video: false,
      screen: true,
      screenAudio: true
    });

    示例代码

    以下示例代码展示了屏幕共享的完整步骤。

    以下示例代码用了 isFirefoxisCompatibleChrome 来判断浏览器类型,你需要自己实现,也可以参考 common.js 中的代码。
    //TODO: 填入你的项目的 App ID
    var appID = "<yourAppID>";
    var channel = "screen_video";
    var channelKey = null;
    
    AgoraRTC.Logger.setLogLevel(AgoraRTC.Logger.INFO);
    
    var screenClient = AgoraRTC.createClient({
        mode: 'rtc',
        codec: 'vp8'
    });
    screenClient.init(appID, function() {
        screenClient.join(channelKey, channel, null, function(uid) {
            // 创建屏幕共享流
            const streamSpec = {
                streamID: uid,
                audio: false,
                video: false,
                screen: true
              }
              // 根据浏览器类型设置相关属性
              // 注意你需要自己实现判断浏览器的功能
              if (isFirefox()) {
                streamSpec.mediaSource = 'window';
              } else if (!isCompatibleChrome()) {
                streamSpec.extensionId = 'minllpmhdgpndnkomcoccfekfegnlikg';
              }
            screenStream = AgoraRTC.createStream(streamSpec);
            // 初始化流
            screenStream.init(function() {
                // 播放流
                screenStream.play('Screen');
                // 发布流
                screenClient.publish(screenStream);
    
            }, function(err) {
                console.log(err);
            });
    
        }, function(err) {
            console.log(err);
        })
    });

    此外,我们在 GitHub 提供一个开源的示例项目,你可以在线体验或者下载参考 rtc-client.jsindex.js 文件的源代码。

    同时共享屏幕和开启视频

    因为每个 Client 对象只能发送一路 Stream 流,所以如果一个发送端需要同时分享屏幕和开启本地视频采集,你需要创建两个 Client,一路发送屏幕共享流,一路发送本地采集视频流。

    // 创建用于发送屏幕共享流的 Client
    var screenClient = AgoraRTC.createClient({mode: 'rtc', codec: 'vp8'});
    screenClient.init(key, function() {
     screenClient.join(channelKey, channel, null, function(uid) {
      // 创建屏幕共享流 screenStream
      ...
      screenClient.publish(screenStream);
     }
      }
    
    // 创建用于发送本地采集视频流的 Client
    var videoClient = AgoraRTC.createClient({mode: 'rtc', codec: 'vp8'});
    videoClient.init(key, function() {
    videoClient.join(channelKey, channel, null, function(uid) {
      // 创建视频流 videoStream
      ...
      videoClient.publish(videoStream);
     }
    }

    本地 Client 对象互相订阅,会产生额外的费用,如图:

    ../_images/screensharing_streams.png

    Agora 建议,为避免重复计费,用于发送屏幕共享流的 Client 成功加入频道以后,把返回的 uid 存在列表里,然后按照以下方式处理订阅行为:

    • 用于发布本地采集视频流的 Client,监听到 'stream-added' 事件的时候,先判断加入的流是否是本地的屏幕共享流,如果是,则不订阅。
    • 用于发布屏幕共享流的 Client 不需要订阅任何流,因此无需监听 'stream-added' 事件。
    var localStreams = [];
    ...
    
    screenClient.join(channelKey, channel, null, function(uid) {
     // 保存本地屏幕共享流的 uid
     localStreams.push(uid);
    }
    ...
    
    videoClient.on('stream-added', function(evt) {
     var stream = evt.stream;
     var uid = stream.getId()
     // 收到流加入频道的事件后,先判定是不是本地的 uid
     if(!localStreams.includes(uid)) {
      console.log('subscribe stream: ' + uid);
      // 订阅流
      videoClient.subscribe(stream);
     }
    })

    设置共享屏幕的视频属性

    共享屏幕默认的视频属性为:分辨率(宽 × 高) 1920 × 1080,帧率 5 fps。如果你需要使用其他的视频属性,可以调用 Stream.setScreenProfile 设置共享屏幕的视频属性。

    // After creating a stream for screen sharing
    screenStream.setScreenProfile("720p_1");

    SDK 支持设置的视频属性如下表所示:

    屏幕视频属性 分辨率(宽 × 高) 帧率
    480p_1 640 × 480 5 fps
    480p_2 640 × 480 30 fps
    720p_1 1280 × 720 5 fps
    720p_2 1280 × 720 30 fps
    1080p_1 1920 × 1080 5 fps
    1080p_2 1920 × 1080 30 fps
    注意事项:
  • 屏幕视频属性必须在初始化流 (Stream.init) 之前设置。
  • 修改屏幕视频属性可能会影响计费。由于设备和浏览器的限制,部分浏览器对设置的屏幕视频属性不一定能全部适配。这种情况下浏览器会自动调整分辨率,计费也将按照实际分辨率计算。
  • 开发注意事项

    • 创建屏幕共享流的时候,video 必须设置为 false
    • 如果创建了多个 stream,我们建议只将其中一路流的 audio 属性设为 true
    • 屏幕共享流的 UID 尽量不要固定在同一个值,否则某些场景下同 UID 的共享流可能会引起互踢。
    • 在屏幕共享的时候,本地流的 Client 不要订阅本地的屏幕共享流,否则会增加计费。
    • 在 Windows 平台上进行屏幕共享时,如果共享的是 QQ 聊天窗口会导致黑屏。

    相关链接

    实现屏幕共享过程中,你还可以参考如下文档: