Listen for video events

The Video SDK for macOS fires several video-related callbacks through ZMVideoSDKDelegate. Conform to the delegate and implement the callbacks below to react to video state changes in your session. If you haven't already set up a delegate, see Integrate.

User video status

onUserVideoStatusChanged fires when any user starts or stops their video. Use this callback to update your UI, for example to swap a "video off" placeholder for the rendered video, or vice versa.

func onUserVideoStatusChanged(_ videoHelper: ZMVideoSDKVideoHelper!, userList userArray: [ZMVideoSDKUser]!) {
    // userArray contains the users that had a video status change.
    if let userArray = userArray {
        for user in userArray {
            if ((user.getVideoStatus()?.isOn) == true) {
                // User's video is on.
            }
        }
    }
}
- (void)onUserVideoStatusChanged:(ZMVideoSDKVideoHelper*)videoHelper userList:(NSArray*)userArray {
    // userArray contains the users that had a video status change.
    for (int i = 0; i < userArray.count; i++) {
        if (userArray[i]) {
            if ([userArray[i] videoStatus].isOn) {
                // User's video is on.
            }
        }
    }
}

Spotlight list changes

onSpotlightVideoChanged fires whenever the spotlighted user list changes, because a user was added to or removed from the spotlight. Use this to re-render your gallery layout (for example, to enlarge the spotlighted user's tile).

func onSpotlightVideoChanged(_ videoHelper: ZMVideoSDKVideoHelper!, userList: [ZMVideoSDKUser]!) {
    // userList contains the current spotlighted users.
    // Re-render your gallery to reflect the new spotlight state.
}
- (void)onSpotlightVideoChanged:(ZMVideoSDKVideoHelper*)videoHelper userList:(NSArray<ZMVideoSDKUser *> *)userList {
    // userList contains the current spotlighted users.
    // Re-render your gallery to reflect the new spotlight state.
}

For more on how to add and remove users from the spotlight, see Spotlight a user.

Multi-camera stream status

onMultiCameraStreamStatusChanged fires when a user enables, disables, mutes, or unmutes a multi-camera stream. The callback provides the parent user and the ZMVideoSDKRawDataPipe for the additional stream.

func onMultiCameraStreamStatusChanged(_ status: ZMVideoSDKMultiCameraStreamStatus, user: ZMVideoSDKUser!, rawDataPipe videoPipe: ZMVideoSDKRawDataPipe!) {
    // Subscribe to videoPipe to render the additional stream.
}
- (void)onMultiCameraStreamStatusChanged:(ZMVideoSDKMultiCameraStreamStatus)status user:(ZMVideoSDKUser *)user rawDataPipe:(ZMVideoSDKRawDataPipe *)videoPipe {
    // Subscribe to videoPipe to render the additional stream.
}

For more on how to enable, disable, mute, and unmute multi-camera streams, see Multiple camera support.

Alpha channel mode

onVideoAlphaChannelStatusChanged fires when alpha channel mode (transparent-background video) is toggled on or off. For the full feature, see Raw video with alpha channel.

func onVideoAlphaChannelStatusChanged(_ isAlphaModeOn: Bool) {
    // Adjust rendering to handle transparency.
}
- (void)onVideoAlphaChannelStatusChanged:(BOOL)isAlphaModeOn {
    // Adjust rendering to handle transparency.
}

Video canvas subscription failure

onVideoCanvasSubscribeFail fires when a call to subscribe an NSView to a user's video canvas fails. The reason is returned as a ZMVideoSDKSubscribeFailReason.

func onVideoCanvasSubscribeFail(_ failReason: ZMVideoSDKSubscribeFailReason, user: ZMVideoSDKUser!, view: NSView!) {
    // Surface an error in your UI, or retry after the underlying issue is resolved.
}
- (void)onVideoCanvasSubscribeFail:(ZMVideoSDKSubscribeFailReason)failReason user:(ZMVideoSDKUser *)user view:(NSView *)view {
    // Surface an error in your UI, or retry after the underlying issue is resolved.
}

Camera control requests

onCameraControlRequestResult fires on the requesting user's side when a remote camera control request is granted or denied. For the full flow, see Remote camera control.

func onCameraControlRequestResult(_ user: ZMVideoSDKUser!, approved isApproved: Bool) {
    // Update the UI based on whether the request was approved.
}
- (void)onCameraControlRequestResult:(ZMVideoSDKUser *)user approved:(BOOL)isApproved {
    // Update the UI based on whether the request was approved.
}

Canvas snapshots

onCanvasSnapshotTaken fires when a snapshot of a video canvas is successfully captured. onCanvasSnapshotIncompatible fires when a snapshot fails because the target user's stream is not compatible with snapshots.

func onCanvasSnapshotTaken(_ user: ZMVideoSDKUser!, isShare: Bool) {
    // The snapshot is ready — handle it in your UI.
}
func onCanvasSnapshotIncompatible(_ user: ZMVideoSDKUser!) {
    // Snapshot was not possible — fall back gracefully.
}
- (void)onCanvasSnapshotTaken:(ZMVideoSDKUser *)user isShare:(BOOL)isShare {
    // The snapshot is ready — handle it in your UI.
}
- (void)onCanvasSnapshotIncompatible:(ZMVideoSDKUser *)user {
    // Snapshot was not possible — fall back gracefully.
}

Network status

For per-user video network quality changes, implement onUserNetworkStatusChanged and check for the video-specific data type, or use onUserOverallNetworkStatusChanged for the user's overall quality across all data types.

func onUserNetworkStatusChanged(_ type: ZMVideoSDKDataType, level: ZMVideoSDKNetworkStatus, user: ZMVideoSDKUser!) {
    // React to network quality for a specific data type (such as video).
}
func onUserOverallNetworkStatusChanged(_ level: ZMVideoSDKNetworkStatus, user: ZMVideoSDKUser!) {
    // React to the user's overall network quality.
}
- (void)onUserNetworkStatusChanged:(ZMVideoSDKDataType)type level:(ZMVideoSDKNetworkStatus)level user:(ZMVideoSDKUser *)user {
    // React to network quality for a specific data type (such as video).
}
- (void)onUserOverallNetworkStatusChanged:(ZMVideoSDKNetworkStatus)level user:(ZMVideoSDKUser *)user {
    // React to the user's overall network quality.
}