Tutorial: 屏幕分享

屏幕分享

WebRTC 屏幕分享支持桌面端 Chrome M72+ 及 Safari 13。

使用 WebRTC 进行屏幕分享的过程与创建并发布本地音视频流的过程大体一致,主要区别在于 TRTC.createStream 接口传参的不同。

WebRTC 提供 TRTC.isScreenShareSupported 接口判断当前浏览器是否支持屏幕分享。

一、创建和发布屏幕分享流

请严格按照以下顺序执行创建和发布屏幕分享流的代码。

第一步:创建屏幕分享客户端

const shareClient = TRTC.createClient({
  mode: 'rtc',
  sdkAppId,
  userId,
  userSig
});

第二步:创建屏幕分享流

// 仅采集屏幕分享视频流
const shareStream = TRTC.createStream({ audio: false, screen: true, userId });

// 采集麦克风及屏幕分享视频流
// const shareStream = TRTC.createStream({ audio: true, screen: true });

// 采集系统音频及屏幕分享视频流
// const shareStream = TRTC.createStream({ screenAudio: true, screen: true });

// audio 与 screenAudio 属性不能同时设为true, 关于screenAudio更多信息会在本文第五部分介绍。

第三步:初始化屏幕分享流

初始化屏幕分享流,浏览器向用户请求屏幕共享的内容和权限,如果用户拒绝/取消屏幕分享或者系统未授予浏览器屏幕共享的权限,代码会捕获到 NotReadableError 或者 NotAllowedError 错误。

try {
  await shareStream.initialize();
} catch (e) {
  // 当屏幕分享流初始化失败时, 提醒用户并停止后续进房发布流程
  switch (e.name) {
    case 'NotReadableError':
      // 提醒用户确保系统允许当前浏览器获取屏幕内容
      return;
    case 'NotAllowedError':
      if (e.message === 'Permission denied by system') {
        // 提醒用户确保系统允许当前浏览器获取屏幕内容
      } else {
        // 用户拒绝/取消屏幕分享
      }
      return;
    default:
      // 初始化屏幕分享流时遇到了未知错误,提醒用户重试
      return;
  }
}

第四步:屏幕分享客户端进房

try {
  await shareClient.join({ roomId });
  // ShareClient join room success
} catch (e) {
  // ShareClient join room failed
}

第五步:屏幕分享客户端发布屏幕分享流

try {
  await shareClient.publish(shareStream);
} catch (e) {
  // ShareClient failed to publish local stream
}

现在,您已经可以使用 WebRTC 进行屏幕分享了。


二、屏幕分享属性

屏幕分享属性包括分辨率、帧率和码率,可以通过 setScreenProfile() 接口指定一个属性 profile,每个 profile 对应着一组分辨率、帧率和码率。

const shareStream = TRTC.createStream({ userId, audio: false, screen: true });
shareStream.setScreenProfile('1080p');
await shareStream.initialize();

或者使用自定义分辨率、帧率和码率:

const shareStream = TRTC.createStream({ userId, audio: false, screen: true });
shareStream.setScreenProfile({ width: 1920, height: 1080, frameRate: 5, bitrate: 1600 /* kbps */});
await shareStream.initialize();

屏幕分享属性推荐列表:

profile 分辨率(宽 x 高) 帧率(fps) 码率 (kbps)
480p 640 x 480 5 900
480p_2 640 x 480 30 1000
720p 1280 x 720 5 1200
720p_2 1280 x 720 30 3000
1080p 1920 x 1080 5 1600
1080p_2 1920 x 1080 30 4000
  • 屏幕分享默认使用 '1080p'。

三、停止屏幕分享

// 屏幕分享客户端停止推流
await shareClient.unpublish(shareStream);
// 关闭屏幕分享流
shareStream.close();
// 屏幕分享客户端退房
await shareClient.leave();

// 以上三个步骤非必须,按照场景化需求执行需要的代码即可,通常需要添加是否已进房,是否已经发布流的判断,更详细的代码示例请参考官方demo。

在 Web 端,用户还有可能通过浏览器自带的按钮停止屏幕分享,因此屏幕分享流需要监听屏幕分享停止事件。

// 屏幕分享流监听屏幕分享停止事件
shareStream.on('screen-sharing-stopped', event => {
  // 屏幕分享客户端停止推流
  await shareClient.unpublish(shareStream);
  // 关闭屏幕分享流
  shareStream.close();
  // 屏幕分享客户端退房
  await shareClient.leave();
});

四、同时推送摄像头视频和屏幕分享

一个 Client 至多只能同时推送一路音频和一路视频,若需要同时推送摄像头视频和屏幕分享,建议创建两个独立的 Client , 分别负责本地音视频流的发布及屏幕分享流的发布。

userId: 音视频用户ID;
client: 音视频客户端;

TRTC.createClient({ mode: 'rtc', sdkAppId, userId, userSig });  

localStream: 本地音视频流;

TRTC.createStream({ audio: true, video: true }); 

shareUserId: 屏幕分享用户ID;

let shareUserId = `share-${userId}`;

shareClient: 屏幕分享客户端;

TRTC.createClient({ mode: 'rtc', sdkAppId, userId: shareUserId, userSig });  

shareStream: 屏幕分享流;

TRTC.createStream({ audio: false, screen: true });  

当同时推送本地音视频流和屏幕分享流时,需要注意一下两点:

  1. 设置 shareClient 不订阅远端流
// SDK 默认开启自动订阅,当收到 stream-added 时,会立刻解码音视频数据。
// 由于屏幕分享 client 只推流,不拉流。因此需要在收到流时取消订阅。
shareClient.on('stream-added', event => {
  const remoteStream = event.stream;
  shareClient.unsubscribe(remoteStream);
});

// v4.8.0+ 版本支持关闭自动订阅,关闭之后,则无需调用 unsubscribe 接口。
// 参考:https://web.sdk.qcloud.com/trtc/webrtc/doc/zh-cn/TRTC.html#.createClient
  1. 音视频 client 取消订阅 shareUserId 的远端流
  client.on('stream-added', event => {
    const remoteStream = event.stream;
    const remoteUserId = remoteStream.getUserId();
    if (remoteUserId === shareId) {
      // 取消订阅自己的屏幕分享流
      client.unsubscribe(remoteStream);
    } else {
      // 订阅其他一般远端流
      client.subscribe(remoteStream);
    }
  });

五、屏幕分享采集系统声音

采集系统声音只支持 Chrome M74+ ,在 Windows 和 Chrome OS 上,可以捕获整个系统的音频,在 Linux 和 Mac 上,只能捕获选项卡的音频。其它 Chrome 版本、其它系统、其它浏览器均不支持。

// 创建屏幕分享流 screenAudio 请设置为 true, 不支持同时采集系统和麦克风音量,请勿同时设置 audio 属性为 true
const shareStream = TRTC.createStream({ userId, screenAudio: true, screen: true });
...

在弹出的对话框中勾选分享音频,发布的 stream 将会带上系统声音。

六、注意事项

  • Web 端暂不支持推辅流,Web 端推屏幕分享是通过推主流实现的。因此若远端屏幕分享流来自于 Web 用户,RemoteStream.getType() 返回值为 'main'
  • Native 端支持推辅流,Native 推屏幕分享是通过推辅流实现的。因此若远端屏幕分享流来自于 Native 用户,RemoteStream.getType() 返回值为 'auxiliary'