屏幕共享

最近更新时间:2022-09-20 05:17:40

功能介绍

屏幕共享功能是指将采集到的屏幕内容以视频的方式分享给其他人。

屏幕共享支持对显示器屏幕、应用程序窗口、浏览器标签页等画面进行采集和本地预览,并作为视频源共享给其他终端用户。

主要应用于以下场景:

  • 视频会议场景中,主持人可将本地的文件、数据、网页、PPT 等画面通过屏幕分享的方式展示给其他与会人;
  • 在线课堂场景中,老师可通过屏幕捕捉将课件、资料通过屏幕分享的方式共享给学生,让教学更加高效。
  • 游戏直播场景中,游戏主播可以将游戏窗口或者指定屏幕(拓展屏)通过屏幕共享的方式分享给观众,让观众能够以主播同样的视角体验游戏。

Web 端屏幕共享支持 ChromeFirefox 浏览器以及 Electron 平台,但是他们之前存在一些差异:

ChromeFirefoxElectron
无插件
音频采集
自采集(指定采集卡)
自定义(选择采集内容)界面
自定义采集分辨率

在线体验

点击 在线体验 试用屏幕共享功能。

实现原理

实现 Web 端屏幕共享功能可以分为三个步骤:

  1. 采集(屏幕共享内容)以及本地预览
  2. 发布(屏幕共享音视频轨道)
  3. 订阅(屏幕共享音视频轨道)

采集屏幕共享内容可以通过以下 API 实现,开发者可以根据自己情况进行选择:

createScreenVideoTrackcreateCustomVideoTrackcreateCameraVideoTrack
1. 在浏览器中采集显示器屏幕、应用程序窗口以及浏览器标签页
2. 在 Electron 中采集指定 electronScreenSourceId 的媒体流内容或通过自定义界面选择采集内容
已采集到 MediaStreamTrack 作为屏幕共享内容采集指定摄像头或采集卡的媒体流作为屏幕共享内容(采集卡形式)

通过以上 API 返回的 Track 对象,我们可以调用 play 方法在本地进行实时预览。

Chrome 屏幕共享

本小节以 createScreenVideoTrack 为示例,来介绍如何在 Chrome 中进行屏幕共享。

该功能要求 Chrome 72 或以上版本。如果你使用的软件版本不满足此要求,请升级浏览器版本。

ArRTC.createScreenVideoTrack({
  // 可以在这里配置编码参数,详细参考 API 文档。
  encoderConfig: "1080p_1",
}).then(localScreenTrack => {
  /** ... **/
});

分享音频

同时采集屏幕共享的画面和本地播放的背景音,你需要在调用 createScreenVideoTrack 方法时将 withAudio 参数设为 enable

目前仅支持 Windows 平台的 Chrome 浏览器(74 及以上版本)。

采集成功之后,接口会返回一个数组,包含屏幕共享的视频轨道对象和本地播放背景音的音频轨道对象。

ArRTC.createScreenVideoTrack({
  encoderConfig: "1080p_1",
}, true).then([screenVideoTrack, screenAudioTrack] => {
  /** ... **/
});

注意:
分享音频开启后,还需要在选择屏幕共享内容窗口的弹出框上勾选分享音频才能真正生效。
单个应用窗口,不支持分享音频。

屏幕共享分享音频

Electron 屏幕共享

Electron 不提供「选择屏幕共享内容」的窗口,需要开发者自行绘制,为方便开发者快速集成,我们提供了一个默认的选择界面。

默认界面

在 Electron 中直接调用 createScreenVideoTrack 会弹出默认页面提供选择,操作简便和 Web 浏览器一样。

ArRTC.createScreenVideoTrack({
  encoderConfig: "1080p_1",
}).then(localScreenTrack => {
  /** ... **/
});

调用后 SDK 会提供自带的默认界面让终端用户选择要共享的屏幕或窗口,如下图所示:

Electron 屏幕共享内置界面

自定义界面

实现自定义画面流程需要开发者完成以下两个步骤:

1. 获取可共享的屏幕信息

调用 SDK 提供的 ArRTC.getElectronScreenSources 方法获取可共享的屏幕信息。

ArRTC.getElectronScreenSources().then(sources => {
  console.log(sources);
});

sources 是一个 source 对象的列表,source 里包含了视频源的 sourceId 和基本信息,source 的属性如下:

  • id: 即 sourceId
  • name: 视频源的名字。
  • thumbnail: 视频源的快照。

如下图:

Electron 屏幕共享源信息

2. 绘制选择界面

用 HTML 和 CSS 绘制选择自定义界面,再将返回的 sources 数据展示在自定义界面上,让用户选择需要共享的屏幕源。source 的属性与屏幕共享的选择界面对应关系如下:

Electron 屏幕自定义界面

3. 采集选中的屏幕共享源

  1. 获取用户选择的 sourceId
  2. 调用 createScreenVideoTrack 方法时指定 electronScreenSourceIdsourceId,就能创建相应的屏幕共享流了。
ArRTC.createScreenVideoTrack({
  // 填入用户选择的 sourceId。
  electronScreenSourceId: sourceId,
}).then(localScreenTrack => {
  /** ... **/
});
  • getElectronScreenSources 方法是对 Electron 提供的 desktopCapturer.getSources 进行的封装,详情可参考 desktopCapturer
  • 在非 Electron 下传入 sourceId 会被忽略。

Firefox 屏幕共享

screenSourceType 属性仅在 Firefox 浏览器下生效。

Firefox 屏幕共享需要通过设置 screenSourceType 指定分享屏幕的类型,screenSourceType 的选择如下:

  • screen: 分享整个显示器屏幕。
  • application: 分享某个应用的所有窗口。
  • window: 分享某个应用的某个窗口。
ArRTC.createScreenVideoTrack({
  screenSourceType: 'screen' // 'screen', 'application', 'window'
}).then(localScreenTrack => { /** ... **/ });

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

同时共享屏幕和发布本地摄像头

一个 ArRTCClient 客户端只能发送一路视频轨道,因此在一个页面中同时共享屏幕和发布本地摄像头,需要创建两个 ArRTCClient,一路发送屏幕共享轨道,一路发送摄像头轨道。

详情见下方示例:

async function startScreenCall() {
  const screenClient = ArRTC.createClient({ mode: "rtc", codec: "h264" });
  await screenClient.join("<APP_ID>", "<CHANNEL>", "<TOKEN>", "<UID>");

  const screenTrack = await ArRTC.createScreenVideoTrack();
  await screenClient.publish(screenTrack);

  return screenClient;
}

async function startVideoCall() {
  const videoClient = ArRTC.createClient({ mode: "rtc", codec: "h264" });
  await videoClient.join("<APP_ID>", "<CHANNEL>", "<TOKEN>", "<UID>");

  const videoTrack = await ArRTC.createCameraVideoTrack();
  await videoClient.publish(videoTrack);

  return videoClient;
}

Promise.all([startScreenCall(), startVideoCall()]).then(() => { /** ... **/ });

开发注意事项

  • 一个 ArRTCClient 对象只能发送一路视频轨道。
  • 负责发布屏幕共享的用户的 UID 不要固定在同一个值,否则某些场景下同 UID 的共享流可能会引起互踢。
  • 在屏幕共享的时候,本地流的 Client 不要订阅本地的屏幕共享流,否则会增加计费。
  • 在 Windows 平台上进行屏幕共享时,如果共享的是 QQ 聊天窗口会导致黑屏。
  • 共享的应用程序最小化,会导致黑屏。
  • 多次采集屏幕共享,可能会导致画面模糊,如需多次采集请先释放上一次采集的 track。