屏幕共享
更新时间: 2026/01/06 15:49:38
通过 NEMeeting SDK 可以在会议过程中实现屏幕共享,主讲人或参会者可以将自己的屏幕内容,以视频的方式分享给远端参会者观看,从而提升沟通效率。
-
视频会议场景中,参会者可以在会议中将本地的文件、数据、网页、PPT 等画面分享给其他与会者,让其他与会者更加直观的了解讨论的内容和主题。
-
在线课堂场景中,老师可以通过屏幕共享将课件、笔记、教学内容等画面展示给远端的其他学生观看,降低传统教学模式下的沟通成本,提升教育场景的用户体验。
网易云信以辅流的形式实现屏幕共享,即单独为屏幕共享开启一路上行的视频流,摄像头的视频流作为主流,屏幕共享的视频流作为辅流,两路视频流并行,主播同时上行摄像头画面和屏幕画面两路画面。
实现流程
基于 iOS 系统的屏幕共享功能,需要在 App Extension 中通过 iOS 原生的 ReplayKit 特性实现录屏进程,并配合主 App 进程进行推流。需要进行屏幕共享的时候,使用 Apple ReplayKit 框架进行屏幕录制,接收系统采集的屏幕图像,并将其发送给 SDK 以传输视频流数据。
屏幕共享的主要流程包括:
- 创建 App Group。 App Group 用于在主 App 进程和扩展程序之间之间进行视频数据和控制指令的传输。
- 通过 Xcode 在工程中创建一个 Target。Target 的类型为 Broadcast Upload Extension,用于开启屏幕共享的进程。
- 在 Extension 进程中采集录屏数据作为自定义视频源发送给 SDK,并使用 SDK 进行视频流的传输。
注意事项
主进程和系统录屏 Extension 进程需使用相同的 App Group 名以及签名。
配置步骤
第一步:创建 App Group
-
在 Certificates, Identifiers & Profiles 页面中注册 App Group。
操作步骤请参考 注册 App Group。
-
为您的 App ID 启用 App Group 功能。
操作步骤请参考 启用 App Group。
-
重新下载 Provisioning Profile 并配置到 XCode 中。
第二步:创建 Extension 录屏进程
创建一个类型为 Broadcast Upload Extension 的 Target,用于存放屏幕共享功能的实现代码。有关 iOS 主 App 与 Extension 的 Bundle ID 的规则和限制,请参考下文 常见问题。
-
在 Xcode 中打开项目的工程文件。
-
在菜单中选择 Editor > Add Target...。
-
在 iOS 页签中 选择 Broadcast Upload Extension,并单击 Next。
-
在 Product Name 中为 Extension 命名,单击 Finish。
至此,Xcode 会为此 Extension Target 创建对应的 Group,并自动生成了 SampleHandler.h 与 SampleHandler.m 两个文件。
第三步:在 Extension 进程中采集并发送数据
-
在项目的
Podfile文件中添加pod 'NEMeetingKit/ScreenShare', '~> 3.13.0',并执行pod install命令,引入NERtcReplayKitframework 依赖。该 framework 封装了数据的采集与发送,供 Extension 进程调用。Rubytarget 'BroadcasterExtension' do use_frameworks! pod 'NEMeetingKit/ScreenShare', '~> 3.13.0' endpod install -
请在
SampleHandle.h文件中添加 iOS 系统类RPBroadcastSampleHandler的依赖,以实现录屏功能。Objective-C#import <ReplayKit/ReplayKit.h> @interface SampleHandler : RPBroadcastSampleHandler @end -
在
SampleHandle.m文件中,使用步骤一中创建的 App Group 初始化NEScreenShareSampleHandler,并设置相关参数,同时需要处理停止直播。Objective-C#import "SampleHandler.h" #import <NERtcReplayKit/NERtcReplayKit.h> static NSString *kAppGroup =@"<Your_App_Group>";//具体实现时,只需修改此 kAppGroup 部分。 @interface SampleHandler () <NEScreenShareSampleHandlerDelegate> @end @implementation SampleHandler - (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo { // User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional. NEScreenShareBroadcasterOptions *options = [[NEScreenShareBroadcasterOptions alloc] init]; options.appGroup = kAppGroup; // 设置采集帧率 30 帧 options.frameRate = 30; // 设置需要采集系统音频数据 options.needAudioSampleBuffer = YES; [[NEScreenShareSampleHandler sharedInstance] broadcastStartedWithSetupInfo:options]; NEScreenShareSampleHandler.sharedInstance.delegate = self; } - (void)broadcastPaused { // User has requested to pause the broadcast. Samples will stop being delivered. [[NEScreenShareSampleHandler sharedInstance] broadcastPaused]; } - (void)broadcastResumed { // User has requested to resume the broadcast. Samples delivery will resume. [[NEScreenShareSampleHandler sharedInstance] broadcastResumed]; } - (void)broadcastFinished { // User has requested to finish the broadcast. [[NEScreenShareSampleHandler sharedInstance] broadcastFinished]; } - (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType { [[NEScreenShareSampleHandler sharedInstance] processSampleBuffer:sampleBuffer withType:sampleBufferType]; } - (void)onRequestToFinishBroadcastWithError:(NSError *)error { [self finishBroadcastWithError:error]; } @end
-
在项目的
Podfile文件中添加pod 'NEScreenShareBroadcaster', '~> 0.5.3',并执行pod install命令,引入NEScreenShareBroadcasterframework 依赖。该 framework 封装了数据的采集与发送,供 Extension 进程调用。Rubytarget 'BroadcasterExtension' do use_frameworks! pod 'NEScreenShareBroadcaster', '~> 0.5.3' endpod install -
在
SampleHandler.h文件中添加 ReplayKit 和NEScreenShareBroadcaster。请调整代码,使 SampleHandler 类继承于 NEScreenShareSampleHandler,否则会出现对端看到共享的屏幕是黑屏的情况。 Objective-C#import <ReplayKit/ReplayKit.h> #import <NEScreenShareBroadcaster/NEScreenShareBroadcaster.h> @interface SampleHandler : NEScreenShareSampleHandler @end -
在
SampleHandle.m文件中使用步骤一中创建的 App Group 初始化NEScreenShareBroadcaster,并设置相关参数,同时需要处理停止直播的请求。Objective-C#import "SampleHandler.h" static NSString *kAppGroup = @"<Your_App_Group>";//具体实现时,只需修改此 kAppGroup 部分。 @implementation SampleHandler - (void)setupWithOptions:(NEScreenShareBroadcasterOptions *)options { options.appGroup = kAppGroup; CGRect screenRect = [[UIScreen mainScreen] bounds]; CGFloat scale = [UIScreen mainScreen].scale; CGFloat screenWidth = screenRect.size.width * scale; CGFloat screenHeight = screenRect.size.height * scale; options.targetFrameSize = CGSizeMake(0, 0); } #pragma mark - NEScreenShareBroadcasterDelegate - (void)onHostRequestFinishBroadcast { NSError *error = [NSError errorWithDomain:NSStringFromClass(self.class) code:0 userInfo:@{ NSLocalizedFailureReasonErrorKey:NSLocalizedString(@"屏幕共享已结束。", nil) }]; [self finishBroadcastWithError:error]; } @end
第四步:初始化会议组件
使用与 Extension 进程相同的 App Group 初始化会议 SDK。
Objective-CNEMeetingKitConfig *config = [[NEMeetingKitConfig alloc] init];
config.appKey = kAppKey; // 会议 AppKey
config.appName = @"APPName";
config.broadcastAppGroup = @"<Your_App_Group>"; // 指定 App Group
// 其他初始化参数设置
// ...
[[NEMeetingKit getInstance] initialize:config
callback:^(NSInteger resultCode, NSString *resultMsg, id result) {
if (resultCode == ERROR_CODE_SUCCESS) {
//TODO when initialize success
} else {
//TODO when initalize fail
}
}];
常见问题
pod 集成出错
如果 pod 集成后,编译出错。如:'sharedApplication' is unavailable: not available on iOS (App Extension) - Use view controller based solutions where appropriate instead.`
请在 podfile 文件中添加如下代码:
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'No'
end
end
end
iOS 主 App 与 Extension 的 Bundle ID 有什么规则和限制?
Extension 的 Bundle ID 必须以主 App 的 Bundle ID 作为前缀。例如:
- 主 App:
com.example.myapp - Extension:
com.example.myapp.broadcast
两者必须使用同一 Apple 开发者账号证书签名,并且各自的 Provisioning Profile 中显式包含对应的 Bundle ID(不能使用通配符 *)。
会议中点击屏幕共享,没有“屏幕录制”弹窗?
- 请确保主进程和系统录屏 Extension 进程已经配置并使用了相同的 App Group 名以及签名。
- 请检查 Extension 的 Deploy Target Version,创建 Extension 时,Xcode 可能会将 Target 版本设置得比较高,导致该 Extension 无法在较低版本的 iOS 系统中安装。(主工程最低支持 iOS 10,Extensiong 工程最低支持 iOS 12.0)
共享成功后,对端看到黑屏画面?
-
3.13.0 及之后版本
- 请检查 Extension 代码,确保生成的代码中, SampleHandler 类继承于 RPBroadcastSampleHandler,并确认 SampleHandle 的实现是否与上面提供的代码一致。
- 请检查 Extension 工程中的 App Group 是否与创建的一致。
-
3.12.0 及之前版本
请检查 Extension 代码,确保生成的代码中,SampleHandler 类继承于 NEScreenShareSampleHandler,因为推流操作都是封装在 NEScreenShareSampleHandler 这个类中的。
共享屏幕失败
屏幕共享失败的排查思路如下:
-
请检查已生成的 App Group 是否可用,并确认以下设置是否正确:
-
在 NEMeetingKit 初始化设置中,
NEMeetingKitConfig.broadcastAppGroup参数是否设置为正确的 App Group。 -
在 SampleHandle.m 文件中,
kAppGroup参数是否设置为正确的 App Group。 -
在 Xcode 中确认主工程与 Extension 工程配置的 App Groups 是否一致。
-
-
检查 iOS 最低系统版本满足如下要求:
主工程最低支持 iOS 10,Extensiong 工程最低支持 iOS 12.0
如何处理主进程异常退出的问题?
当处于会议中并开启了屏幕共享时,如果主进程意外退出,则需要您手动停止直播扩展进程。您可通过注册监听进程退出的事件,并调用相应方法停止直播进程。
示例代码如下:
Objective-C@implementation AppDelegate
- (void)applicationWillTerminate:(UIApplication *)application {
[[[NEMeetingKit getInstance] getMeetingService] stopBroadcastExtension];
}
@end
正常结束或退出会议时不需要您手动停止直播进程。




