屏幕共享的实现与应用

语言: CN / TW / HK

随着音视频的迅速发展,无论是在商用还是娱乐方面都有很多场景的实际应用,玩法也是越来越多了,随之而来的就是对衍生功能要求的提高。

屏幕共享就是对于商用和娱乐场景最重要的功能之一。

简介

屏幕共享包括屏幕采集和视频流推送这两部分功能。与音视频互动不同,屏幕共享讲究的是高清实时,对带宽以及设备性能要求很高。本文的重点是 anyRTC 在屏幕共享上的调优以及实现步骤,开发者无需关注功能实现细节,只需要参透 API 调用顺序即可。下面以 Windows SDK 平台为例,介绍 anyRTC 屏幕共享功能。

目前 Windows SDK 屏幕分享功能支持屏幕分享窗口分享以及区域采集分享三种类型,其中屏幕分享和区域采集分享可以合二为一,区域采集分享为选定的屏幕中进行区域指定分享,如果想整个屏幕分享,需要指定整个屏幕区域位置即可。这三种采集方式,都有自己特定的使用场景,开发者只需要根据自己的实际应用场景,选择对应的分享类型即可。

anyRTC SDK 暂不提供方法获取显示器屏幕信息和 window ID,你需要通过 Windows 原生方法,例如 EnumDisplayMonitorsEnumWindows 获取相应信息。

屏幕分享 & 区域采集分享

在 Windows 系统中,每个显示器的屏幕都位于同一个虚拟屏幕上,通过 Windows 原生方法,获取对应的屏幕信息和 window ID。

具体实现步骤如下:

  1. 获取显示器屏幕信息列表。

cpp void CArScreenCapture::InitMonitorInfos() { // m_monitors 是 CMonitors 类的实例。CMonitors 类的具体实现参考示例项目。 // m_monitors 调用 EnumMonitor 获取显示器屏幕信息列表。EnumMonitor 方法的具体实现参考示例项目。 m_monitors.EnumMonitor(); // 定义 infos 向量,用于存储显示器屏幕信息列表。 std::vector<CMonitors::MonitorInformation> infos = m_monitors.GetMonitors(); CString str = _T(""); // 获取每个显示器屏幕在虚拟屏幕上的 Rectangle 坐标 for (size_t i = 0; i < infos.size(); i++) { RECT rcMonitor = infos[i].monitorInfo.rcMonitor; CString strInfo; strInfo.Format(_T("Screen%d: rect = {%d, %d, %d, %d} ") , i + 1, rcMonitor.left, rcMonitor.top, rcMonitor.right, rcMonitor.bottom); } str += strInfo; m_cmbScreenRegion.InsertString(i, utf82cs(infos[i].monitorName)); } m_cmbScreenRegion.InsertString(infos.size(), _T("Select Window Hwnd Rect Area")); m_staScreenInfo.SetWindowText(str); m_cmbScreenRegion.SetCurSel(0); }

  1. 通过待共享的显示器屏幕在虚拟屏幕上的 Rectangle 坐标以及待共享区域在显示器屏幕上的 Rectangle 坐标实现屏幕共享。

```cpp void CArScreenCapture::OnBnClickedButtonStartShareScreen() { m_screenShare = !m_screenShare; if (m_screenShare) { // 获取选择的显示器屏幕 int sel = m_cmbScreenRegion.GetCurSel(); agora::rtc::Rectangle regionRect = { 0,0,0,0 }, screenRegion = {0,0,0,0};

    // 获取指定的待共享区域在整个显示器屏幕中的 Rectangle 坐标。
    // GetMonitorRectangle 方法的具体实现详见示例项目。
    regionRect = m_monitors.GetMonitorRectangle(sel);
    // 获取显示器屏幕在虚拟屏幕中的 Rectangle 坐标。GetScreenRect 方法的实现详见示例项目。
    screenRegion = m_monitors.GetScreenRect();

    m_monitors.GetScreenRect();
    // 屏幕共享的编码参数配置
    ScreenCaptureParameters capParam;
    // 开始屏幕共享
    m_rtcEngine->startScreenCaptureByScreenRect(screenRegion, regionRect, capParam);
    m_btnShareScreen.SetWindowText(screenShareCtrlStopShare);

    m_btnStartCap.EnableWindow(FALSE);

}
else {
    // 停止屏幕共享
    m_rtcEngine->stopScreenCapture();
    m_btnShareScreen.SetWindowText(screenShareCtrlShareSCreen);
    m_btnStartCap.EnableWindow(TRUE);
}

} ```

窗口分享

Windows 系统为每个窗口分配一个 windowId,数据类型为 HWND。该 ID 对应唯一的 Windows 窗口。为了兼容 x86 和 x64 系统,使用 view_t 类型。

通过获取该 windowId,我们可以按如下步骤在 Windows 平台上实现窗口共享:

  1. 获取想要共享窗口的 Window ID

cpp BOOL CALLBACK EnumProc(HWND hWnd, LPARAM IParam) { // 仅获取可视窗口 ID,忽略弹出窗口及目录窗口 LONG IStyle = ::GetWindowLong(hWnd, GWL_STYLE); if ((IStyle&WS_VISIBLE) != 0 && (IStyle&(WAS_POPUP | WA_SYSMENU)) != 0) { HWND window_id = hWnd; } return TRUE; } EnumWindows(&EnumProc, NULL);

  1. 通过 Window ID 共享窗口

```cpp // 指定共享的屏幕或窗口 RECT rc; ar::rtc::Rectangle rcCap; ar::rtc::Rectangle screenRegion = { rc.left, rc.right, rc.right - rc.left, rc.bottom - rc.top }; capParam.dimensions.width = rc.right - rc.left; capParam.dimensions.height = rc.bottom - rc.top;

::GetWindowRect(hWnd, &rc); ScreenCaptureParameters capParam; capParam.dimensions.width = rc.right - rc.left; capParam.dimensions.height = rc.bottom - rc.top;

VideoContentHint contentHint; ar::rtc::Rect rt;

// 开始共享窗口 ret = m_lpAREngine->startScreenCaptureByWindowId(hWnd, rcCap, capParam);

// 更新屏幕共享编码参数 m_lpAREngine->updateScreenCaptureParameters(capParam);

// 更新屏幕共享区域 m_lpAREngine->updateScreenCaptureRegion(screenRegion);

// 设置屏幕共享内容类型 m_lpAREngine->setScreenCaptureContentHint(contentHint);

// 停止屏幕共享 m_lpAREngine->stopScreenCapture(); ```

以上是 Windows 平台屏幕共享介绍,想了解更多平台如 Android iOS 的小伙伴可以点击 anyRTC 文档中心进行查看。

应用场景

上文是对屏幕共享的功能介绍,下面为大家介绍一下屏幕共享的具体应用场景。

在线教育:

适用于大班课、小班课等多种教育场景,老师端可以通过屏幕共享将上课需要的课件,资料共享给学生,让教学变得更加高效,提高效率节省时间。

游戏直播:

游戏主播可以通过实时采集屏幕内容,以直播的方式共享给所有观众,让观众能够以主播同样的视角体验游戏。这样可以提高用户的观看体验,让用户可以有身临其境的感觉。使得用户观看的代入感更强,增加用户的粘性。

视频会议:

主持人可将电脑上的材料共享给远端的与会方,所有人观看屏幕的实时视频流,达到信息共享的目的。主持人不必再提起分发文档,因为参与者可以在演示者的屏幕上看到任何文档或文件,甚至可以要求会议者通过屏幕共享工具的传输功能发送这些文档和文件。

远程演示:

在进行远程协作或操作演示时,可以通过采集屏幕和窗口的内容,直观演示具体操作步骤,帮助他人快速理解。屏幕共享允许的在线演示是组织与客户和客户互动的完美方法。借助屏幕共享应用程序,不仅销售人员可以展示他们的产品,而且他们还可以通过提供PC键盘或鼠标的远程控制来邀请客户体验软件程序等项目。这是屏幕共享工具的最佳好处之一。

在线培训:

通过在线培训中使用屏幕共享工具,组织可以节省大量资金,因为他们不必设置整个投影仪设置并为外部讲座付费。相反,讲师的材料可以通过屏幕共享应用程序从他们的PC屏幕轻松共享,供所有与会者查看。

讲师甚至可以使用这样的屏幕共享功能作为白板或参与者指针来与学员互动,从而形成交互式和娱乐性的学习环境。

除了上述 Windows 的屏幕共享,anyRTC 已经实现了全平台的屏幕共享。Android 端支持屏幕共享采集H264格式的屏幕共享流,很大一定程度上优化了 Android 的性能;iOS 端无缝匹配 Replaykit ;Web 端除了区域采集分享,其他两种分析功能都有对应的 API 调用,更多产品细节,关注 anyRTC。