# 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](/docs/video-sdk/macos/integrate/#implement-a-delegate). ## 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. ```swift 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. } } } } ``` ```objectivec - (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). ```swift func onSpotlightVideoChanged(_ videoHelper: ZMVideoSDKVideoHelper!, userList: [ZMVideoSDKUser]!) { // userList contains the current spotlighted users. // Re-render your gallery to reflect the new spotlight state. } ``` ```objectivec - (void)onSpotlightVideoChanged:(ZMVideoSDKVideoHelper*)videoHelper userList:(NSArray *)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](/docs/video-sdk/macos/video/spotlight/). ## 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. ```swift func onMultiCameraStreamStatusChanged(_ status: ZMVideoSDKMultiCameraStreamStatus, user: ZMVideoSDKUser!, rawDataPipe videoPipe: ZMVideoSDKRawDataPipe!) { // Subscribe to videoPipe to render the additional stream. } ``` ```objectivec - (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](/docs/video-sdk/macos/video/multiple-cameras/). ## 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](/docs/video-sdk/macos/raw-data/raw-video-alpha-channel/). ```swift func onVideoAlphaChannelStatusChanged(_ isAlphaModeOn: Bool) { // Adjust rendering to handle transparency. } ``` ```objectivec - (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`. ```swift func onVideoCanvasSubscribeFail(_ failReason: ZMVideoSDKSubscribeFailReason, user: ZMVideoSDKUser!, view: NSView!) { // Surface an error in your UI, or retry after the underlying issue is resolved. } ``` ```objectivec - (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](/docs/video-sdk/macos/video/remote-camera-control/). ```swift func onCameraControlRequestResult(_ user: ZMVideoSDKUser!, approved isApproved: Bool) { // Update the UI based on whether the request was approved. } ``` ```objectivec - (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. ```swift 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. } ``` ```objectivec - (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. ```swift 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. } ``` ```objectivec - (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. } ```