# Core features The Video SDK for iOS lets you programmatically control user video during a session: check video status, start video, stop video, and render one or many users. For switching, mirroring, rotating, and other per-device camera operations, see [Camera controls](/docs/video-sdk/ios/video/camera-controls/). > **Camera permission required.** > > Before using video, your app must request camera access. Add an `NSCameraUsageDescription` entry to your `Info.plist` and request permission at runtime. For details, see [Requesting authorization to capture and save media](https://developer.apple.com/documentation/avfoundation/capture_setup/requesting_authorization_to_capture_and_save_media). ## Check whether video is on To check whether a user has their video on, read `on` from the user's `videoStatus` to get a boolean indicating whether that user's video is on in the session. ```swift let isVideoOn = user.getVideoCanvas()?.videoStatus()?.on ``` ```objectivec BOOL isVideoOn = [[user videoCanvas] videoStatus].on; ``` ## Start video Start video by calling `startVideo` on the `ZoomVideoSDKVideoHelper`. Be sure your app has camera permission before calling, or the SDK can't capture from the camera. ```swift if let videoHelper = ZoomVideoSDK.shareInstance()?.getVideoHelper() { videoHelper.startVideo() } ``` ```objectivec ZoomVideoSDKVideoHelper *videoHelper = [[ZoomVideoSDK shareInstance] getVideoHelper]; if (videoHelper) { [videoHelper startVideo]; } ``` ## Stop video Stop video by calling `stopVideo` on the `ZoomVideoSDKVideoHelper`. ```swift ZoomVideoSDK.shareInstance()?.getVideoHelper()?.stopVideo() ``` ```objectivec [[[ZoomVideoSDK shareInstance] getVideoHelper] stopVideo]; ``` ## Render a user's video To render a user's video, get the user's `ZoomVideoSDKVideoCanvas` and subscribe a `UIView` to it. ```swift // Get the user's videoCanvas. if let usersVideoCanvas = user.getVideoCanvas() { // Set the video aspect. let videoAspect = ZoomVideoSDKVideoAspect.panAndScan // Subscribe the user's videoCanvas to render their video stream. usersVideoCanvas.subscribe(with: view, andAspectMode: videoAspect) } ``` ```objectivec // Get the user's videoCanvas. ZoomVideoSDKVideoCanvas *usersVideoCanvas = [user getVideoCanvas]; // Set the video aspect. ZoomVideoSDKVideoAspect videoAspect = ZoomVideoSDKVideoAspect_PanAndScan; // Subscribe the user's videoCanvas to render their video stream. [usersVideoCanvas subscribeWithView:view andAspectMode:videoAspect]; ``` The `aspect` parameter controls how Zoom fits the video into the view. | Type | Description | | ------------------------------------- | ---------------------------------------------------------------------------------------- | | `ZoomVideoSDKVideoAspect_Original` | Display video without any modifications. | | `ZoomVideoSDKVideoAspect_Full_Filled` | Stretch the video to fill the canvas. | | `ZoomVideoSDKVideoAspect_LetterBox` | Add black bars (top/bottom or left/right) so the full frame is visible without cropping. | | `ZoomVideoSDKVideoAspect_PanAndScan` | Crop the frame to fill the canvas without bars. | For more on choosing an aspect mode and on responsive layouts, see [Aspect ratio and orientation](/docs/video-sdk/ios/video/best-practices/#aspect-ratio-and-orientation). ### Remove a user's video from a canvas When a user leaves the session, or when you want to recycle a view for a different user, unsubscribe from the canvas. ```swift if let usersVideoCanvas = user.getVideoCanvas() { usersVideoCanvas.unSubscribe(with: view) } ``` ```objectivec ZoomVideoSDKVideoCanvas *usersVideoCanvas = [user getVideoCanvas]; [usersVideoCanvas unSubscribeWithView:view]; ``` ## Render multiple users To render multiple users at once (gallery view), iterate over the users in the session and subscribe a `UIView` for each. Respond to `onUserJoin` to add new users as they enter, and `onUserLeave` to unsubscribe. ```swift func onUserJoin(_ helper: ZoomVideoSDKUserHelper?, users userArray: [ZoomVideoSDKUser]?) { userArray?.forEach { user in // Create or dequeue a UIView for this user, add it to your gallery container, // then subscribe the user's canvas to it. user.getVideoCanvas()?.subscribe(with: view, andAspectMode: .original) } } func onUserLeave(_ helper: ZoomVideoSDKUserHelper?, users userArray: [ZoomVideoSDKUser]?) { userArray?.forEach { user in // Unsubscribe and remove the corresponding view from the container. user.getVideoCanvas()?.unSubscribe(with: view) } } ``` ```objectivec - (void)onUserJoin:(ZoomVideoSDKUserHelper *)helper users:(NSArray *)userArray { for (ZoomVideoSDKUser *user in userArray) { // Create or dequeue a UIView for this user, add it to your gallery container, // then subscribe the user's canvas to it. [[user getVideoCanvas] subscribeWithView:view andAspectMode:ZoomVideoSDKVideoAspect_Original]; } } - (void)onUserLeave:(ZoomVideoSDKUserHelper *)helper users:(NSArray *)userArray { for (ZoomVideoSDKUser *user in userArray) { // Unsubscribe and remove the corresponding view from the container. [[user getVideoCanvas] unSubscribeWithView:view]; } } ``` For grid layout and density recommendations, see [Layout and density](/docs/video-sdk/ios/video/best-practices/#layout-and-density).