# Render user video > The code on this page works with either the **default UI** or the **custom UI**. In custom UI mode, the SDK provides multiple options to render user video after a user subscribes to another user's video. After following the steps to render a user's video, each option contains a different type of video stream. - **Single attendee** - A single user's video. - **Active speaker** - A single user's video that automatically updates when the active speaker changes. - **Preview** - A preview of the local user's video. - **Share** - The content being shared by another user. Regardless of which render option you're using, the SDK utilizes two main components. - `MobileRTCVideoView`, `MobileRTCActiveShareView`, `MobileRTCActiveVideoView`, or `MobileRTCPreviewVideoView` - Interface for video element rendering in custom UI. - `MobileRTCMeetingServiceDelegate` - A delegate that indicates if a video's subscription fails and more. ## Subscribe to error data Before subscribing to the video, implement `MobileRTCMeetingServiceDelegate` to know when a video subscription fails. ```swift // Add delegate first. guard let meetingService = MobileRTC.shared().getMeetingService() else { return } meetingService.delegate = self // Also, conform your class to the MobileRTCMeetingServiceDelegate extension ViewController: MobileRTCMeetingServiceDelegate func onSubscribeUserFail(_ errorCode: MobileRTCSubscribeFailReason, size: Int, userId: UInt) { } } ``` ```objectivec // In your .h file, conform to the MobileRTCMeetingServiceDelegate protocol @interface ViewController : UIViewController { } // In your .m file, add delegate and add onSubscribeUserFail callback MobileRTCMeetingService *meetingService = [[MobileRTC sharedRTC] getMeetingService]; if (!meetingService) { return; } meetingService.delegate = self; - (void)onSubscribeUserFail:(MobileRTCSubscribeFailReason)errorCode size:(NSInteger)size userId:(NSUInteger)userId { } ``` When you've finished using the video view, remove the listener to avoid leaks. ```swift meetingService.delegate = nil ``` ```objectivec meetingService.delegate = nil; ``` ## Define a video view The primary user-facing video element is `MobileRTCVideoView` for rendering attendee video view. It is also inherited by these components. - `MobileRTCActiveVideoView` - for active speaker view - `MobileRTCActiveShareView` - for active share view - `MobileRTCPreviewVideoView` - for local user preview view Create a new `MobileRTCVideoView` instance based on which UIView you need, and give that new instance the `CGRect` frame that you'll be using to add the video view. ```swift let videoViewFrame = CGRect() // Your Video View // MobileRTCVideoView let videoView = MobileRTCVideoView(frame: videoViewFrame) // MobileRTCActiveShareView let activeShareView = MobileRTCActiveShareView(frame: videoViewFrame) // MobileRTCActiveVideoView let activeVideoView = MobileRTCActiveVideoView(frame: videoViewFrame) activeVideoView.setVideoAspect(MobileRTCVideoAspect_PanAndScan) // MobileRTCPreviewVideoView let previewVideoView = MobileRTCPreviewVideoView(frame: videoViewFrame) previewVideoView.setVideoAspect(MobileRTCVideoAspect_PanAndScan) ``` ```objectivec CGRect videoViewFrame = CGRectZero; // Your Video View // // MobileRTCVideoView MobileRTCVideoView *videoView = [[MobileRTCVideoView alloc] initWithFrame:videoViewFrame]; // MobileRTCActiveShareView MobileRTCActiveShareView *activeShareView = [[MobileRTCActiveShareView alloc] initWithFrame:videoViewFrame]; [activeShareView // MobileRTCActiveVideoView MobileRTCActiveVideoView *activeVideoView = [[MobileRTCActiveVideoView alloc] initWithFrame:videoViewFrame]; [activeVideoView setVideoAspect:MobileRTCVideoAspect_PanAndScan]; // MobileRTCPreviewVideoView MobileRTCPreviewVideoView *previewVideoView = [[MobileRTCPreviewVideoView alloc] initWithFrame:videoViewFrame]; [previewVideoView setVideoAspect:MobileRTCVideoAspect_PanAndScan]; ``` ## Subscribe to video streams To subscribe to a single attendee's video, you must provide the `userId` of the user whose video is being subscribed to. Access this in `MobileRTCMeetingUserInfo.userID`. ```swift let videoView = MobileRTCVideoView(frame: videoViewFrame) videoView.showAttendeeVideo(withUserID: 123456789) // userID videoView.stopAttendeeVideo() ``` ```objectivec MobileRTCVideoView *videoView = [[MobileRTCVideoView alloc] initWithFrame:videoViewFrame]; [videoView showAttendeeVideoWithUserID:123456789]; // userID [videoView stopAttendeeVideo]; ``` To subscribe to the active speaker stream, call these codes. ```swift let activeUserID = meetingService.activeUserID() let activeVideoView = MobileRTCActiveVideoView(frame: videoViewFrame) activeVideoView.setVideoAspect(MobileRTCVideoAspect_PanAndScan) activeVideoView.showAttendeeVideo(withUserID: activeUserID) // Show activeVideoView.stopAttendeeVideo() // Stop ``` ```objectivec NSUInteger activeUserID = meetingService.activeUserID; MobileRTCActiveVideoView *activeVideoView = [[MobileRTCActiveVideoView alloc] initWithFrame:videoViewFrame]; [activeVideoView setVideoAspect:MobileRTCVideoAspect_PanAndScan]; [activeVideoView showAttendeeVideoWithUserID:activeUserID]; // Show [activeVideoView stopAttendeeVideo]; // Stop ``` To subscribe to the local preview of the user associated with this SDK instance, call these codes. ```swift let localUserID = meetingService.myselfUserID() let previewVideoView = MobileRTCPreviewVideoView(frame: videoViewFrame) previewVideoView.setVideoAspect(MobileRTCVideoAspect_PanAndScan) previewVideoView.showAttendeeVideo(withUserID: localUserID) // Show previewVideoView.stopAttendeeVideo() // Stop ``` ```objectivec NSUInteger localUserID = meetingService.myselfUserID; MobileRTCPreviewVideoView *previewVideoView = [[MobileRTCPreviewVideoView alloc] initWithFrame:videoViewFrame]; [previewVideoView setVideoAspect:MobileRTCVideoAspect_PanAndScan]; [previewVideoView showAttendeeVideoWithUserID:activeUserID]; // Show [previewVideoView stopAttendeeVideo]; // Stop ``` To subscribe to the shared content shared by another user, call `showActiveSharealong` with the `shareSourceID`. To keep listening to the current sharing status and know when to subscribe to the shared view, use the `onSinkSharingStatus` callback from `MobileRTCMeetingServiceDelegate`. Alternatively, get the `shareSourceID` by calling the `getSharingSourceInfoList` from `MobileRTCMeetingService` using the sharer's userID and from the list and use `getShareSourceID`. ```swift var shareSourceID: UInt! // 1st way - Using the onSinkSharingStatus callback to get the latest share source ID func onSinkSharingStatus(_ shareInfo: MobileRTCSSharingSourceInfo) { // Check shareInfo's status to see if it's other share begin, only then we subscribe later on. if shareInfo.getStatus() == .other_Share_Begin { shareSourceID = shareInfo.getShareSourceID() } } // OR 2nd way - if you know the sharer's userID you want to subscribe to guard let sharingSourceInfoList = MobileRTC.shared().getMeetingService()?.getSharingSourceInfoList(12345) else { return } // If multi share is enabled, one user can share multiple times. Hence this might be a list of more than 1 share info. for shareInfo in sharingSourceInfoList { shareSourceID = shareInfo.getShareSourceID() // First identify the correct share info from the list and then get the Share Source ID. } // Once you have the desired Share Source ID, show or start active share. let activeShareView = MobileRTCActiveShareView(frame: videoViewFrame) activeShareView.showActiveShare(withShareSourceID: shareSourceID) // shareSourceID activeShareView.stopActiveShare() ``` ```objectivec NSUInteger shareSourceID; // 1st way - Using the onSinkSharingStatus callback to get the latest share source ID - (void)onSinkSharingStatus:(MobileRTCSSharingSourceInfo *)shareInfo { // Check shareInfo's status to see if it's other share begin, only then we subscribe later on. if (shareInfo.getStatus == MobileRTCSharingStatus_Other_Share_Begin) { shareSourceID = shareInfo.getShareSourceID; } } // OR 2nd way - if you know the sharer's userID you want to subscribe to guard let sharingSourceInfoList = MobileRTC.shared().getMeetingService()?.getSharingSourceInfoList(123456789) else { return } // If multi share is enabled, one user can share multiple times. Hence this might be a list of more than 1 share info. for (MobileRTCSSharingSourceInfo *shareInfo in sharingSourceInfoList) { shareSourceID = shareInfo.getShareSourceID; // First identify the correct share info from the list and then get the Share Source ID. } // Once you have the desired Share Source ID, show or start active share. MobileRTCActiveShareView *activeShareView = [[MobileRTCActiveShareView alloc] initWithFrame:videoViewFrame]; [activeShareView showActiveShareWithShareSourceID:shareSourceID]; [activeShareView stopActiveShare]; ``` ---