macOS SDK Guide
Install, join a channel, screen capture and platform notes.
The macOS platform shares the AgoraRtcEngineKit / AgoraRtcEngineDelegate shape with iOS; the difference is desktop capture: the capture source can be pinned by "display id" or "window id", and it requires the system screen-recording permission plus the matching entitlement.
Prerequisites
- Xcode 16+, a macOS 12+ deployment target.
- Add
NSCameraUsageDescriptionandNSMicrophoneUsageDescriptiontoInfo.plist; screen sharing must be authorised in "System Settings → Privacy & Security → Screen Recording". - If App Sandbox is enabled, you need
com.apple.security.device.camera,com.apple.security.device.audio-inputandcom.apple.security.device.screen-capture. - You already have an
appIdand a token service (see Enable services and get credentials).
Install
# Podfile (planned coordinate; not published yet)
pod 'NimeetRtc', :path => '../sdk/ios', :subspecs => ['macOS']Get a token
As on iOS: tokens are issued by the backend and injected by the client through CallbackTokenProvider; on macOS you can cache the token in memory, but do not write it into a plaintext Keychain item.
Join a channel
import NimeetRtc
final class MeetingController: NSObject, AgoraRtcEngineDelegate {
private var engine: AgoraRtcEngineKit?
func start(appId: String, token: String, localView: NSView) {
engine = AgoraRtcEngineKit.sharedEngine(withAppId: appId, delegate: self)
engine?.setChannelProfile(.liveBroadcasting)
engine?.enableVideo()
let canvas = AgoraRtcVideoCanvas()
canvas.view = localView
engine?.setupLocalVideo(canvas)
engine?.startPreview()
engine?.joinChannel(byToken: token, channelId: "weekly-sync", uid: 10001, mediaOptions: .init()) { channel, uid, elapsed in
print("joined \(channel) uid=\(uid)")
}
}
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { }
func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { }
}Publish and subscribe
The most common desktop scenario is "share one window":
// 1) Enumerate sources
engine?.getScreenCaptureSources(withThumbSize: CGSize(width: 160, height: 90),
iconSize: CGSize(width: 32, height: 32),
includeScreen: true) { sources in
// 2) Pick a window source and pin capture to its windowId
if let window = sources.first(where: { $0.sourceType == .window }) {
let params = AgoraScreenCaptureParameters()
params.frameRate = 15
let region = CGRect.zero
engine?.startScreenCapture(byWindowId: window.windowId, regionRect: region, captureParams: params)
}
}To capture a display, use startScreenCaptureByDisplayId:regionRect:captureParams:; stop with stopScreenCapture.
Events
The same delegate set as iOS: rtcEngine:didJoinedOfUid:elapsed:, rtcEngine:didOfflineOfUid:reason:, rtcEngine:didOccurError:; screen sharing adds source-list and capture-state callbacks.
Error handling
- Synchronous methods return
Int32;0means success and a negative value is an Agora error number; unimplemented capabilities return-4. - The most common screen-sharing failure is not a wrong version but a missing permission: when the source list is empty, check the system authorisation and the entitlement first.
Troubleshooting
| Symptom | Cause | Handling |
|---|---|---|
| The source list is empty | Screen-recording permission was not granted | Grant it in System Settings and restart the app |
| The shared window is black | A protected or minimised window was selected | Switch to the whole screen or to a visible window |
| The capture frame rate is very low | frameRate and resolution are too high | Drop to 15fps and 1080p or below |
| The app crashes under the sandbox | A missing entitlement | Add the com.apple.security.device.* entitlements |
| Local audio and video are fine but remotes hear nothing | Microphone permission was denied | Check NSMicrophoneUsageDescription and the system privacy settings |
Next steps
- Full interfaces and overloads: API reference for this platform
- Error codes and troubleshooting: Error code table, FAQ
- Issue tokens on your server: Token authentication
Platform information
| Item | value |
|---|---|
| Platform | macOS |
| Language | Swift / Objective-C |
| SDK package | NimeetRtc |
| Interface version | 4.7.0 |
| Compatible Agora API | Agora macos API |
The public interfaces are aligned with the Agora macos API; installation and runtime requirements are listed under Prerequisites above.
Availability
This platform's SDK: Generally available. The examples use the public API; runtime capability follows the published SDK package.
join-channel flow
The method names, parameter types and return values match the API reference for the same platform. Where a method has several overloads, the most common one is shown here; see the API reference for all overloads.
| Step | Interface | Method | Overload count |
|---|---|---|---|
| enable video and local preview | AgoraRtcEngineKit | enableVideo | 1 |
| Join a channel | AgoraRtcEngineKit | joinChannelByToken:channelId:info:uid:joinSuccess: | 1 |
| Leave a channel | AgoraRtcEngineKit | leaveChannel: | 1 |
| Create instance / initialize | AgoraRtcEngineKit | sharedEngineWithAppId:delegate: | 1 |
enableVideo(): int
joinChannelByToken:channelId:info:uid:joinSuccess:(token?: NSString*, channelId: NSString*, info?: NSString*, uid: NSUInteger, joinSuccessBlock?: void(^ )(NSString*channel,NSUInteger uid,NSInteger elapsed)): int
leaveChannel:(leaveChannelBlock?: void(^ )(AgoraChannelStats*stat)): int
sharedEngineWithAppId:delegate:(appId: NSString*, delegate?: id): instancetypeEvents and callbacks
This SDK has no event callbacks.
Error codes
| Constant | value |
|---|---|
AgoraErrorCodeAdmGeneralError | 1005 |
AgoraErrorCodeAdmInitLoopback | 1022 |
AgoraErrorCodeAdmInitPlayout | 1008 |
AgoraErrorCodeAdmInitRecording | 1011 |
AgoraErrorCodeAdmJavaResource | 1006 |
AgoraErrorCodeAdmNoPlayoutDevice | 1360 |
AgoraErrorCodeAdmNoRecordingDevice | 1359 |
AgoraErrorCodeAdmPlayAbnormalFrequency | 1020 |
AgoraErrorCodeAdmRecordAbnormalFrequency | 1021 |
AgoraErrorCodeAdmRecordAudioFailed | 1018 |
AgoraErrorCodeAdmRuntimePlayoutError | 1015 |
AgoraErrorCodeAdmRuntimeRecordingError | 1017 |
AgoraErrorCodeAdmSampleRate | 1007 |
AgoraErrorCodeAdmStartLoopback | 1023 |
AgoraErrorCodeAdmStartPlayout | 1009 |
AgoraErrorCodeAdmStartRecording | 1012 |
AgoraErrorCodeAdmStopPlayout | 1010 |
AgoraErrorCodeAdmStopRecording | 1013 |
AgoraErrorCodeAlreadyInUse | 19 |
AgoraErrorCodeBitrateLimit | 115 |
AgoraErrorCodeBufferTooSmall | 6 |
AgoraErrorCodeConnectionInterrupted | 111 |
AgoraErrorCodeConnectionLost | 112 |
AgoraErrorCodeDecryptionFailed | 120 |
AgoraErrorCodeEncryptedStreamNotAllowedPublish | 130 |
AgoraErrorCodeFailed | 1 |
AgoraErrorCodeInitNetEngine | 21 |
AgoraErrorCodeInvalidAppId | 101 |
AgoraErrorCodeInvalidArgument | 2 |
AgoraErrorCodeInvalidChannelId | 102 |
AgoraErrorCodeInvalidState | 8 |
AgoraErrorCodeInvalidToken | 110 |
AgoraErrorCodeInvalidUserAccount | 134 |
AgoraErrorCodeJoinChannelRejected | 17 |
AgoraErrorCodeLeaveChannelRejected | 18 |
AgoraErrorCodeLoadMediaEngine | 1001 |
AgoraErrorCodeNoError | 0 |
AgoraErrorCodeNoServerResources | 103 |
AgoraErrorCodeNotInChannel | 113 |
AgoraErrorCodeNotInitialized | 7 |
AgoraErrorCodeNotReady | 3 |
AgoraErrorCodeNotSupported | 4 |
AgoraErrorCodePcmSendBufferOverflow | 201 |
AgoraErrorCodePcmSendFormat | 200 |
AgoraErrorCodeResourceLimited | 22 |
AgoraErrorCodeSizeTooLarge | 114 |
AgoraErrorCodeStartCall | 1002 |
AgoraErrorCodeStartCamera | 1003 |
AgoraErrorCodeStartVideoRender | 1004 |
AgoraErrorCodeTimedOut | 10 |
AgoraErrorCodeTokenExpired | 109 |
AgoraErrorCodeTooManyDataStreams | 116 |
AgoraErrorCodeVcmEncoderEncodeError | 1602 |
AgoraErrorCodeVcmEncoderInitError | 1601 |
AgoraErrorCodeVcmEncoderSetError | 1603 |
AgoraErrorCodeVcmUnknownError | 1600 |
AgoraErrorCodeVdmCameraNotAuthorized | 1501 |
AgoraErrorCodeVideoEffectAssetInvalid | 1700 |
AgoraErrorCodeVideoEffectEngineInvalid | 1702 |
AgoraErrorCodeVideoEffectInvalidBundlePath | 1707 |
AgoraErrorCodeVideoEffectInvalidParam | 1705 |
AgoraErrorCodeVideoEffectNodeNotActive | 1704 |
AgoraErrorCodeVideoEffectNotSupported | 1706 |
AgoraErrorCodeVideoEffectSaveFailed | 1701 |
AgoraErrorCodeWatermarkAGRB | 128 |
AgoraErrorCodeWatermarkInfo | 127 |
AgoraErrorCodeWatermarkParam | 124 |
AgoraErrorCodeWatermarkPath | 125 |
AgoraErrorCodeWatermarkPng | 126 |
AgoraErrorCodeWatermarkRead | 129 |
the platform REST layer uses REST error codes;the SDK layer maps connection/authentication failures to Agora error numbers, for the mapping table see SDK error identifiers per platform。