# Core features The Video SDK for macOS lets you control user video during a session: check video status, start video, stop video, and render a user's video. For per-device camera operations (switching, mirroring, rotating, pan/tilt/zoom), see [Camera controls](/docs/video-sdk/macos/video/camera-controls/). > Prior to using video controls, you must **request permission to use the camera**. For details, see [Requesting Authorization for Media Capture on macOS](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos?language=objc). ## Start video If the user's video is not already enabled, start video using `startVideo`, provided by the `ZMVideoSDKVideoHelper`. ```swift // Get the ZMVideoSDKVideoHelper to perform video actions. if let videoHelper = ZMVideoSDK.shared()?.getVideoHelper() { // Start local user's video. videoHelper.startVideo() } ``` ```objectivec // Get the ZMVideoSDKVideoHelper to perform video actions. ZMVideoSDKVideoHelper *videoHelper = [[ZMVideoSDK sharedVideoSDK] getVideoHelper]; if (videoHelper) { // Start local user's video. [videoHelper startVideo]; } ``` ## Stop video To stop displaying the video of the user, use `stopVideo`. ```swift // Get the ZMVideoSDKVideoHelper to perform video actions. if let videoHelper = ZMVideoSDK.shared()?.getVideoHelper() { // Stop local user's video. videoHelper.stopVideo() } ``` ```objectivec // Get the ZMVideoSDKVideoHelper to perform video actions. ZMVideoSDKVideoHelper *videoHelper = [[ZMVideoSDK sharedVideoSDK] getVideoHelper]; if (videoHelper) { // Stop local user's video. [videoHelper stopVideo]; } ``` ## Render a user's video To display a user's video, get their `ZMVideoSDKVideoCanvas` and subscribe an `NSView` to it. Retrieve each `ZMVideoSDKUser` as they join the session, then subscribe a view to render their stream. ### Retrieve user The `ZMVideoSDKUserHelper` helps with retrieval of user information. For more details on user management, see [Sessions](/docs/video-sdk/macos/sessions/). To be notified when users join a session, use `onUserJoin` within `ZMVideoSDKDelegate`. ```swift func onUserJoin(_ userHelper: ZMVideoSDKUserHelper!, userList userArray: [ZMVideoSDKUser]!) { // userArray contains the new users. // Use helper to perform actions on a user. if let userArray = userArray { for user in userArray { print(user) } } } ``` ```objectivec - (void)onUserJoin:(ZMVideoSDKUserHelper*)userHelper userList:(NSArray)userArray { // userArray contains the new users. // Use helper to perform actions on a user. for (int i = 0; i < userArray.count; i++) { NSLog(@"%@", userArray[i]); } } ``` ### Render a user's video into a view Get the user's `ZMVideoSDKVideoCanvas` and subscribe an `NSView` to it with `subscribeWithView`, passing an aspect mode and resolution. ```swift if let canvas = user.getVideoCanvas() { canvas.subscribe(with: yourView, aspectMode: .panAndScan, resolution: .auto) } ``` ```objectivec ZMVideoSDKVideoCanvas *canvas = [user getVideoCanvas]; [canvas subscribeWithView:yourView aspectMode:ZMVideoSDKVideoAspect_PanAndScan resolution:ZMVideoSDKResolution_Auto]; ``` The aspect mode controls how Zoom fits the video into the view. | Type | Description | | ----------------------------------- | ---------------------------------------------------------------------------------- | | `ZMVideoSDKVideoAspect_Original` | Display the video without any modifications. | | `ZMVideoSDKVideoAspect_Full_Filled` | Stretch the video to fill the view. | | `ZMVideoSDKVideoAspect_LetterBox` | Add bars (top/bottom or left/right) so the full frame is visible without cropping. | | `ZMVideoSDKVideoAspect_PanAndScan` | Crop the frame to fill the view without bars. | To render multiple users at once (gallery view), subscribe a view for each user in `onUserJoin` and unsubscribe in `onUserLeave`. ### Remove a user's video from a view When a user leaves the session, or when you recycle a view for a different user, unsubscribe with `unSubscribeWithView`. ```swift user.getVideoCanvas()?.unSubscribe(with: yourView) ``` ```objectivec [[user getVideoCanvas] unSubscribeWithView:yourView]; ``` For custom rendering from raw YUV frames instead of an `NSView`, see [Receive raw video data](/docs/video-sdk/macos/raw-data/receive-raw-data/#receive-raw-video-data) to subscribe to the user's video pipe. For sending or pre-processing video, see [Send raw data](/docs/video-sdk/macos/raw-data/send-raw-data/). ## Check the video status of a user You can control video on a per-user basis. First check the current video status of the user. ```swift // Get videoStatus for user. let videoStatus = user.videoStatus() // Check if user's video is on. let isVideoOn = user.getVideoPipe().getVideoStatus().isOn() ``` ```objectivec // Get videoStatus for user. ZMVideoSDKVideoStatus *videoStatus = [user videoStatus]; // Check if user's video is on. BOOL isVideoOn = [[[user getVideoPipe] getVideoStatus] isOn]; ``` To react to video status changes for all users, implement [`onUserVideoStatusChanged`](/docs/video-sdk/macos/video/video-events/#user-video-status).