屏幕共享
更新时间: 2024/09/18 16:26:13
在大型会议或在线教育等场景中,为了满足提升沟通效率的需求,主讲人或老师需要将本端的屏幕内容分享给远端参会者或在线学生观看。NERTC 支持屏幕共享功能,帮助您实时分享本端设备的屏幕内容。
功能介绍
通过 NERTC SDK 可以在视频通话或互动直播过程中实现屏幕共享,主播或连麦者可以将自己的屏幕内容,以视频的方式分享给远端参会者或在线观众观看,从而提升沟通效率,一般适用于多人视频聊天、在线会议以及在线教育场景。
-
视频会议场景中,参会者可以在会议中将本地的文件、数据、网页、PPT 等画面分享给其他与会者,让其他与会者更加直观的了解讨论的内容和主题。
-
在线课堂场景中,老师可以通过屏幕共享将课件、笔记、教学内容等画面展示给远端的其他学生观看,降低传统教学模式下的沟通成本,提升教育场景的用户体验。
NERTC SDK 以辅流的形式实现屏幕共享,即单独为屏幕共享开启一路上行的视频流,摄像头的视频流作为主流,屏幕共享的视频流作为辅流,两路视频流并行,主播同时上行摄像头画面和屏幕画面两路画面。
此外 NERTC SDK 还支持在共享屏幕的同时,也共享本地播放的系统背景音。具体请参考音频共享。
注意事项
- NERTC Unity SDK 的屏幕共享功能仅支持 Windows、macOS 平台,移动端平台敬请期待后续版本。
- 在实现屏幕共享功能前,请确保开发环境满足如下要求:
- Visual Studio 2013 及以上版本。
- Windows7、Windows8、Windows10 或以上版本。
- NERTC Android、iOS、Windows 和 macOS SDK V3.9.0 及以上版本,Web SDK V4.1.0 及以上版本支持通过辅流实现屏幕共享。如果使用辅流的屏幕共享方案,请保证房间内所有成员均升级到支持版本以上,否则互相通信时会因同时发送主流和辅流造成通话异常等问题。
- 如果您的 App 无法针对所有端进行强制升级,屏幕共享场景中仅部分端使用 V3.9.0 及以上版本,为避免上述通话异常问题,必须保证通话过程中单人同时只有一路上行视频流。当需要将视频流切换为屏幕共享流时,请先通过
EnableLocalVideo
关闭视频流,再通过StartScreenCaptureByScreenRect
或其他屏幕共享相关接口启动屏幕共享流。反向切换同理。 - 对于 V5.4.0 及之后版本,如果当前正在使用本地视频辅流通道进行本地摄像头采集或者外部自定义视频输入,调用
StartScreenCaptureByScreenRect
或StartScreenCaptureByWindowId
开启屏幕共享时,需要先调用EnableLocalVideo
停止辅流。如果当前正在屏幕共享,调用EnableLocalVideo
开启辅流时,需要调用StopScreenCapture
先停止屏幕共享。
本端共享屏幕
API 调用时序
sequenceDiagram
participant 应用A
participant NERtcSDK1
participant WECAN
participant NERtcSDK2
participant 应用B
Note over 应用A, 应用B: 设置画布并开启屏幕共享
应用A ->> NERtcSDK1: SetupLocalVideoCanvas
应用A ->> NERtcSDK1: StartScreenCaptureByScreenRect 等
NERtcSDK1 -> WECAN: 视频数据传输
WECAN -> NERtcSDK2: 视频数据传输
NERtcSDK2 -->> 应用B: OnUserVideoStart
NERtcSDK2 -->> 应用B: OnScreenCaptureStatus
Note over 应用A, 应用B: 管理屏幕共享任务
应用A ->> NERtcSDK1: PauseScreenCapture 等
Note over 应用A, 应用B: 关闭屏幕共享
应用A ->> NERtcSDK1: StopScreenCapture
NERtcSDK1 -> WECAN: 视频数据传输
WECAN -> NERtcSDK2: 视频数据传输
NERtcSDK2 -->> 应用B: OnUserVideoStop
NERtcSDK2 -->> 应用B: OnScreenCaptureStatus
实现方法
-
获取指定的待共享区域在整个显示器屏幕中的 Rectangle 坐标。
-
设置屏幕共享辅流画布。
初始化后通过
SetupLocalVideoCanvas
设置本端的辅流视频回放画布。 -
开启屏幕共享。
加入房间后,根据需求开启屏幕共享并设置屏幕共享的方式,屏幕共享内容以辅流形式发送。
StartScreenCaptureByScreenRect
:开启屏幕共享,共享范围为指定屏幕的指定区域。StartScreenCaptureByWindowId
:开启屏幕共享,共享范围为指定窗口的指定区域。
对于 V5.4.0 及之后版本:
- 如果当前正在使用本地视频辅流通道进行本地摄像头采集或者外部自定义视频输入,调用
StartScreenCaptureByScreenRect
或StartScreenCaptureByWindowId
开启屏幕共享时,需要先调用EnableLocalVideo
停止辅流。 - 如果当前正在屏幕共享,调用
EnableLocalVideo
开启辅流时,需要调用StopScreenCapture
先停止屏幕共享。
您需要设置
captureParams
配置屏幕共享的编码参数,其RtcScreenCaptureParameters
结构体的参数说明如下表所示。参数 参数说明 prefer 屏幕共享编码策略倾向: kNERtcSubStreamContentPreferMotion
(默认):内容类型为动画。当用户共享的内容是视频、电影或游戏等动态画面时,推荐选择此枚举值;此时frameRate
参数完全按照您的设置处理。kNERtcSubStreamContentPreferDetails
:内容类型为细节。当用户共享的内容是图片、文字或 PPT 等静态画面时,推荐选择此枚举值;此时frameRate
参数最高可设置为 10 帧。
profile 视频编码的分辨率。
具体请参考NERtcScreenProfileType
。- 建议直接设置为
kNERtcScreenProfileCustom
,以确保所有设置符合您的真实业务场景。 - 若您需要使用自定义的尺寸(
dimensions
)和帧率(frameRate
),请务必设置此参数为kNERtcScreenProfileCustom
。 - 若设置
profile
为kNERtcScreenProfileCustom
之外的值,尺寸dimensions
会自动对应为profile
指定的大小,帧率frameRate
固定为 5 fps。
dimensions 视频编码的最大像素值,可以设置视频尺寸的宽、高。 此参数仅当 profile
参数设置为kNERtcScreenProfileCustom
有效。frameRate 视频编码的帧率。
单位为 fps,默认值为 5,建议此参数的值不要超过 15。bitrate 视频编码的码率,单位为 Kbps。
若设置的码率为 0 或超出合理范围,SDK 会自行计算出合理区间处理码率。excludedWindowList 待屏蔽窗口的列表。 captureMouseCursor 是否采集鼠标用于屏幕共享。 此外,网易云信提供一些常见场景下的参数推荐搭配值,供您参考,具体如下表所示。
参数名称 共享视频 共享 PPT prefer kNERtcSubStreamContentPreferMotion kNERtcSubStreamContentPreferDetails profile kNERtcScreenProfileCustom kNERtcScreenProfileCustom dimensions {1920, 1080} {1920, 1080} frameRate 15 5 regionRect
参数的坐标值请通过步骤一获取,具体如何设置请参考设置屏幕共享的窗口范围和枚举屏幕列表或窗口列表。- 开启屏幕共享之后,远端会触发
OnUserSubStreamVideoStart
和OnScreenCaptureStatusChanged
回调。
-
管理屏幕共享任务。
UpdateScreenCaptureParameters
:更新屏幕共享参数。PauseScreenCapture
:暂停屏幕共享。ResumeScreenCapture
:恢复屏幕共享。UpdateScreenCaptureRegion
:更新屏幕共享区域。SetExcludeWindowList
:设置共享指定屏幕区域时,需要屏蔽的窗口列表。SetScreenCaptureMouseCursor
:设置屏幕共享时是否显示鼠标。
-
关闭屏幕共享。
通过
StopScreenCapture
关闭辅流形式的屏幕共享。此时远端会触发onUserSubStreamVideoStop
回调,本端触发OnScreenCaptureStatusChanged
回调。
若您在屏幕共享过程中,SDK 触发 kScreenCaptureStatusAbort
回调,这是由于当前共享的窗口被关闭、进程崩溃等原因导致目标窗口无效。您需要在此事件的响应函数中调用 StopScreenCapture
结束屏幕共享进程。
示例代码
C#//纹理对象回调处理
public void OnTexture2DSubVideoFrame(ulong uid, Texture2D texture, RtcVideoRotation rotation)
{
//uid为0时代表是本人的视频数据回调
}
//设置本地辅流画布
private void SetupLocalSubstreamVideoCanvas()
{
var userCanvas = new RtcVideoCanvas();
userCanvas.callback = new VideoFrameCallback(OnTexture2DSubVideoFrame);
int result = rtcEngine.SetupLocalVideoCanvas(RtcVideoStreamType.kNERTCVideoStreamSub,userCanvas);
if (result != (int)RtcErrorCode.kNERtcNoError)
{
//失败
}
}
//开始屏幕共享
private void StartScreenCapture()
{
//开始屏幕共享前,需要先设置本地视频辅流的画布
//需要获取显示器的实际区域。
var screenRect = new RtcRectangle
{
x = screenTop,
y = screenLeft,
width = screenWidth,
height = screenHeight
};
//设置想要分享的屏幕区域,如果全部设置为0,则表示取全屏。
var regionRect = new RtcRectangle
{
x = 0,
y = 0,
width = 0,
height = 0
};
//设置参数,按需设置,看结构体说明填写
var screenParams = new RtcScreenCaptureParameters
{
profile = RtcScreenProfileType.kNERtcScreenProfileCustom,
dimensions = new RtcVideoDimensions{ width = 1920, height = 1080 },
frameRate = 10,// 细节模式最高支持10fps
bitrate = 0,
captureMouseCursor = true,
windowFocus = true,
prefer =RtcSubStreamContentPrefer.kNERtcSubStreamContentPreferDetails,
};
int result = rtcEngine.StartScreenCaptureByScreenRect(screenRect, regionRect, screenParams);
if (result != (int)RtcErrorCode.kNERtcNoError)
{
//失败
}
}
//停止分享屏幕
private void StopScreenCapture()
{
int result = rtcEngine.StopScreenCapture();
if (result != (int)RtcErrorCode.kNERtcNoError)
{
//失败
}
}
//删除辅流画布
private void RemoveRemoteVideoCanvas(ulong uid)
{
//删除本地画布
rtcEngine.SetupLocalVideoCanvas(RtcVideoStreamType.kNERTCVideoStreamSub,null);
//删除远端画布
rtcEngine.SetupRemoteVideoCanvas(uid, RtcVideoStreamType.kNERTCVideoStreamSub,null);
}
观看远端屏幕共享
API 调用时序
sequenceDiagram
participant 应用层
participant NERtcSDK
应用层 ->> NERtcSDK: SetupRemoteSubStreamVideoCanvas
Note left of NERtcSDK: 收到远端用户开启屏幕共享的回调
NERtcSDK -->> 应用层: OnUserSubStreamVideoStart
应用层 ->> NERtcSDK: SubscribeRemoteVideoSubStream
NERtcSDK -->> 应用层: OnUserSubStreamVideoStop
实现方法
-
设置远端辅流画布。
- 远端用户加入房间时,可以通过
onUserJoined
事件获取远端用户 ID,并通过SetupRemoteSubStreamVideoCanvas
设置指定远端用户的的辅流视频画布。 - (可选)通过
SetRemoteSubSteamRenderMode
设置远端的屏幕共享辅流视频渲染缩放模式。
- 远端用户加入房间时,可以通过
-
订阅远端用户的屏幕共享流。
- 收到
OnUserSubStreamVideoStart
远端用户开启屏幕共享辅流通道的回调。 - 通过
SubscribeRemoteVideoSubStream
订阅远端的屏幕共享辅流视频,订阅之后才能接收远端的辅流视频数据。
- 收到
-
结束屏幕共享。
收到
OnUserSubStreamVideoStop
其他用户关闭辅流的回调,结束屏幕共享。
示例代码
C#//设置远端辅流画布
private void SetupRemoteSubstreamVideoCanvas(long uid) {
var userCanvas = new RtcVideoCanvas();
userCanvas.callback = new VideoFrameCallback(OnTexture2DSubVideoFrame);
int result = rtcEngine.SetupRemoteVideoCanvas(uid, RtcVideoStreamType.kNERTCVideoStreamSub,userCanvas);
if(result != RtcErrorCode.kNERtcNoError) {
//失败
}
}
private void onUserVideoStart(RtcVideoStreamType type, ulong uid, RtcVideoProfileType maxProfile) {
// 订阅视频辅流
// type == RtcVideoStreamType.kNERTCVideoStreamSub时为辅流
SetupRemoteSubStreamVideoCanvas(uid,false);
int result = rtcEngine.SubscribeRemoteVideoStream(uid,
type,
RtcRemoteVideoStreamType.kNERtcRemoteVideoStreamTypeHigh,
true);
if(result != RtcErrorCode.kNERtcNoError) {
//失败
}
}
private void onUserVideoStop(RtcVideoStreamType type, ulong uid {
// 取消订阅视频辅流
//type == RtcVideoStreamType.kNERTCVideoStreamSub时为辅流
int result = rtcEngine.SubscribeRemoteVideoStream(uid,
type,
RtcRemoteVideoStreamType.kNERtcRemoteVideoStreamTypeHigh,
false);
if(result != RtcErrorCode.kNERtcNoError) {
//失败
}
}
设置屏幕共享的窗口范围
屏幕共享时,您可能需要限制共享屏幕的窗口范围,例如部分涉及敏感信息的窗口区域不进行屏幕共享。NERTC SDK 支持设置共享屏幕的区域范围,目前可通过以下方式实现:
-
开启屏幕共享时,仅共享指定窗口的部分区域。
通过
StartScreenCaptureByWindowId
开启窗口维度的屏幕共享,并通过参数regionRect
指定共享的窗口范围。 -
开启屏幕共享时,仅共享指定屏幕的部分区域,并排除部分窗口。
通过
StartScreenCaptureByScreenRect
开启屏幕维度的屏幕共享,并通过参数regionRect
指定共享的屏幕范围、通过RtcScreenCaptureParameters
设置需要过滤的窗口列表。 -
屏幕共享过程中,动态调整需要屏蔽的窗口列表。
共享整个屏幕时,您可以通过
SetExcludeWindowList
设置窗口过滤,将一个或多个需要过滤的窗口或应用排除出共享范围,其他观看端只能看到整个屏幕中指定窗口以外的其他内容。