概述
会议里的共享由ShareType 区分两类:
同一时刻一个会议只有一位成员在共享,共享者是谁可以读
RoomInfo.shareUid,当前共享类型读 RoomInfo.shareState。
屏幕共享在 iOS 上有两条采集路径,能采到的范围完全不同,接入前先确认要哪一条:
macOS 只有一条路径,
requestShare() 即整屏 / 指定窗口采集。
开始共享
默认采集
requestShare(shareType: .screen, preset: .h1080p),macOS 上采集主显示器。preset 取值来自 SRTC 的 ScreenPreset:.h720p、.h1080p(默认)。
macOS:让用户选择显示器或窗口
macOS 12.3 及以上支持指定采集源。业务层先枚举,展示选择 UI,再把用户选中的源传进来:source 接受 DisplaySource(显示器)或 WindowSource(应用窗口)。
SDK 负责「发现可共享的源」和「开始采集」,「怎么把源列表展示给用户」由你决定,这样 SDK 不绑定任何 UI 方案。
macOS:整屏共享时排除会中窗口
共享整个显示器时,画面默认包含本 App 自己的窗口(与 Zoom / 腾讯会议一致)。而会中主窗口通常正在渲染远端画面,如果它渲染的正是你这路共享流(同机双开自测,或界面上有共享预览),就会形成无限镜像。把这些窗口的 ID 传进去逐个挖掉:- 取值是
UInt32(NSWindow.windowNumber),只在共享整个显示器时有意义,采集单个窗口时忽略 - 列表在开始采集时快照一次,之后新开的窗口一律进画面
- 确实要回到「整个 App 都不共享」的旧行为,把
excludesCurrentApplication置true,此时excludedWindowIds被忽略
本地预览
如果你在 UIKit / AppKit 下需要本地预览共享画面,可以传入view;SwiftUI 下不传,改用 SRTCVideoView(track: meeting.screenTrack)。
iOS:全屏共享
requestShare() 在 iOS 上走的是应用内采集,只能采到本 App 的画面。要共享整个系统屏幕,必须走 ReplayKit 的 Broadcast Upload Extension —— 这是 iOS 的系统约束,任何 SDK 都绕不过去。
一、集成扩展 target
新建一个 Broadcast Upload Extension target,只链接SRTCBroadcastKit,principal class 继承 SRTCBroadcastSampleHandler:
SRTCBroadcastKit 是音视频层 srtc-swift-sdk 的产物,而 SwiftPM 不允许使用传递依赖的产品,所以要在工程里再加一条依赖,版本与 SMeeting 内部锁定的 SRTC 版本保持一致(见 集成方式):
二、配置 App Group
App 与扩展配同一个 App Group,并在扩展的Info.plist 写 SRTCAppGroupIdentifier。三处必须完全一致:App 的 entitlement、扩展的 entitlement、扩展的 Info.plist。
App Group 还要在开发者后台注册,两份描述文件都得带上该 capability,否则签名阶段就会报 Provisioning profile doesn't include the App Groups capability。
三、入会后挂监听,用户从系统 UI 发起
全屏采集只能由用户从系统 UI 发起,所以链路是「先挂监听 → 用户点系统胶囊 → 真的出帧了才对会议宣布共享」:publishBroadcastShare(byAdmin: true, adminUid:) 传上对应参数即可,与 requestShare 的语义一致。
因为共享按钮本体就是系统的 SRTCBroadcastPicker,界面上不需要「等待用户开启共享」这类中间态提示页。
四、状态与收尾
用户从系统胶囊停止广播时,SDK 会自动收尾(停止发布 + 通知会议后端)并重新挂上监听,业务侧不需要再调
stopShare()、也不用重新 prepare,只需刷新 UI。用户可以直接再共享一次。
不再需要共享能力时调 stopBroadcastListening();exitRoom() 会自动拆掉监听,不需要手动处理。
模拟器跑不通全屏采集,必须真机(依赖真实签名与 App Group)。扩展进程的日志不在 Xcode 控制台里,用 Console.app 按 subsystem
com.srtc.broadcast 过滤。iOS 全屏共享不采集系统音频 —— 扩展侧能拿到音频帧,但当前宿主侧的 iOS 音频链路接不通,协议里是预留位。共享内容只有画面。停止共享
stopShare() 会通知会议、停止发布并停止采集,不抛错。
主持人也可以强制结束当前正在进行的共享:
roomShareDidStop(byAdmin 为 true)。
白板共享
白板不产生媒体流,requestShare(shareType: .whiteBoard) 只是把共享状态广播出去:
WKWebView 加载即可。白板的具体交互由你在自己的容器里承载,SDK 只负责同步「现在谁在共享白板」这一状态。
中途入会的人收不到 roomShareDidStart,需要自己补一次判断:RoomInfo.shareState == 2 就说明会议里已经有人在共享白板。
白板页面的 URL 参数、宿主 JS 接口、生命周期与销毁时机见 SRTC · 电子白板。
共享事件
roomShareDidStart 以 RTC 媒体轨道为准:远端 screen 轨道到达即上报,因此收到这个事件时可以立即渲染共享画面,不需要额外做延时重试。共享广播消息与媒体轨道是两条独立通道、到达顺序不保证,SDK 已在三条路径上做了去重与兜底,同一次共享只会上报一次。
shareBroadcastDidStart / shareBroadcastDidFinish 只在 iOS 全屏共享、且只在共享方自己这一端触发,用于区分「监听已挂上」和「真的有画面了」。其他成员只关心 roomShareDidStart / roomShareDidStop 即可,不需要分辨对端用的是哪条采集路径。