What is the Virtual Background preview view and is there any pre-made UI for selecting a virtual background image?

Description
Question 1: What are the virtual background preview interfaces for and how are they used?
I see the following interfaces in the MobileRTCMeetingService+VirtualBackground.h file:
UIView * _Nullable previewView;
- (BOOL)startPreviewWithFrame:(CGRect)frame;
yet there is no clear description of what they are used for nor how to use them.

My second question may be answered by the first but,
Question 2: is there any pre-made Zoom UI that can be used with custom meeting UI (independently of the native Zoom UI, similar to meeting chat) that will allow the user to choose an image to use as their virtual background?

Which Client iOS SDK version?
v5.4.54802.0124

Additional context
After verifying that isSupportVirtualBG returns YES, I tried setting the previewView to a custom UIView I made in one case without adding it to a view controller’s view and in another case adding it to a VC’s view, and there were no noticeable effects. When I added it to the VC’s view, the view I made showed but that’s it. In both cases previewView did hold a reference to the view I gave it. These were just guesses to see what the preview does.

MobileRTCMeetingService *ms = [[MobileRTC sharedRTC] getMeetingService];
UIView *previewView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
previewView.backgroundColor = [UIColor redColor];
[self.view addSubview:previewView]; // Tried both with and without this line.
[ms setPreviewView:previewView];

I also tried calling startPreviewWithFrame:CGRectMake(0, 0, 250, 250)]; but this had no noticeable effects either.

MobileRTCMeetingService *ms = [[MobileRTC sharedRTC] getMeetingService];
[ms startPreviewWithFrame:CGRectMake(0, 0, 250, 250)];

Hey @caleb.bolton,

Thanks for using the dev forum! Great questions.

When you use the standard Zoom Client iOS application and join a meeting, you will be shown a preview video before being admitted. The preview is your current camera view, so that you can check if your video stream looks good before entering. If you click on the button that is in the top left corner of this screen (it looks like an image button) a new view is presented that shows your preview again, but with Virtual Background options to chose from. When you click on one of these options, the preview will update with that virtual background. This does not reflect changes to the other users in the meeting until the virtual background is confirmed and the preview is dismissed. The view in this interface is that view.

Yep, that is the view in the first question.

Hmm, have you tried calling the other virtual background methods while this view is presented?
Like useBGImage? What does getBGImageList return for you?

Thanks!
Michael

Hi Michael, thanks for the quick reply.

I’ve tried the following code:

MobileRTCMeetingService *ms = [[MobileRTC sharedRTC] getMeetingService];
UIView *previewView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
previewView.backgroundColor = [UIColor redColor];
[self.view addSubview:previewView];
[ms setPreviewView:previewView];

NSArray *vbList = [ms getBGImageList];
[ms useBGImage:vbList[1]];

The second part successfully sets the video view’s background to the golden gate bridge image from the list, however, the red square view is shown but no noticeable preview behavior occurs.

I’m not sure how to use the previewView still. If the previewView is the same as the preview view in the native Zoom client, why do we need to set previewView with our own custom view? Shouldn’t we just be able to display a pre-made view or view controller?

In case it’s relevant, this is for non-login users.

Thanks!

Hi @caleb.bolton,

In order to modify the virtual background, the video preview must be active by the time you set the background. Can you please confirm whether or not the video preview is active?

Thanks!

Hi Jon,

By video preview do you mean previewView?
I am successfully modifying the virtual background without assigning to previewView or calling startPreviewWithFrame on MobileRTCMeetingService. previewView can be a custom view I’ve assigned to it or it can be null and I can still change the background image. What do you mean by active?

Modifying the virtual background is working though, and my primary question is how do I use startPreviewWithFrame and previewView? The documentation only says the following:

(BOOL) - startPreviewWithFrame:
Start preview for inspect the virtual background effect.

and

UIView *_Nullable previewView
The preview for inspect the virtual background effect.

The descriptions say generally what the interfaces are for but not how to use them. Like I said in my original question I’ve tried using both interfaces in various ways but neither produce any noticeable behavior.

I think example usage of these two interfaces might be very helpful if that’s possible.

Thank you

Hey @caleb.bolton,

Let me build out a sample ViewController in Objective-C that uses the preview view and I will post that here.

Thanks!
Michael

Hey @caleb.bolton,

Ok I see why this interface is so confusing now. The startPreviewWithFrame method will begin the VirtualBackground preview view, however it will not show it until the previewView from MobileRTCMeetingService is added to your view hierarchy.

So try this:

  1. Get into a meeting that has VB’s enabled
  2. Turn on your camera
  3. Call startPreviewWithFrame and pass in the frame of the view where you want the preview to be rendered
  4. Add the previewView to your view hierarchy
  5. The previewView should now show your standard camera stream, as if you were just viewing yourself in a meeting
  6. At this point you can call the other VB functions and watch the previewView update
  7. The previewView does not have any buttons or anything like that

Here is a pseudo viewController class that implements this:

@interface VBViewController ()
@property(nonatomic, strong) UIButton *addButton;
@property(nonatomic, strong) UIButton *removeButton;
@property(nonatomic, strong) UIButton *closeButton;
@property(nonatomic, strong) UIButton *useButton;
@end

@implementation VBViewController
@synthesize addButton, removeButton, closeButton, useButton;


- (void)viewDidLoad {
    [super viewDidLoad];
    MobileRTCMeetingService *ms = [[MobileRTC sharedRTC] getMeetingService];
    BOOL supportVB = [ms isSupportVirtualBG];
    NSLog(@"[VB Test] isSupportVirtualBG : %@.", @(supportVB));
    if (!supportVB) {
        return;
    }
    
    BOOL ret = [ms startPreviewWithFrame:self.view.frame];
    if (!ret) {
        NSLog(@"[VB Test] startPreviewWithFrame, please check camera status.");
        return;
    }
    
    NSLog(@"[VB Test] startPreviewWithFrame success.");
    
    NSLog(@"[VB Test] ms.previewView : %@.", ms.previewView);
    if (ms.previewView) {
        [self.view addSubview:ms.previewView];
    }
    
    [self initSubViews];
}

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    addButton.frame = CGRectMake(marginLeft, startY, buttonW, buttonH);
    removeButton.frame = CGRectMake(marginLeft + buttonW + intervalX, startY, buttonW, buttonH);
    closeButton.frame = CGRectMake(marginLeft + 2*buttonW + 2*intervalX, startY, buttonW, buttonH);
    useButton.frame = CGRectMake(marginLeft + 3*buttonW + 3*intervalX, startY, buttonW, buttonH);
}

- (void)initSubViews {
    MobileRTCMeetingService *ms = [[MobileRTC sharedRTC] getMeetingService];
    BOOL ret = [ms isUsingGreenVB];
    BOOL smartVB = [ms isSupportSmartVirtualBG];
    NSLog(@"[VB Test] isUsingGreenVB : %@, isSupportSmartVirtualBG : %@", @(ret), @(smartVB));
//    smartVB = 0;
    if (smartVB) {
        addButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [addButton setTitle:NSLocalizedString(@"Add", @"") forState:UIControlStateNormal];
        [addButton setBackgroundColor:RGBCOLOR(0x66, 0x66, 0x66)];
        [addButton setTitleColor:RGBCOLOR(45, 140, 255) forState:UIControlStateNormal];
        addButton.titleLabel.font = BUTTON_FONT;
        [addButton addTarget:self action:@selector(onAddButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
        
        removeButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [removeButton setTitle:NSLocalizedString(@"Remove", @"") forState:UIControlStateNormal];
        [removeButton setBackgroundColor:RGBCOLOR(0x66, 0x66, 0x66)];
        [removeButton setTitleColor:RGBCOLOR(45, 140, 255) forState:UIControlStateNormal];
        removeButton.titleLabel.font = BUTTON_FONT;
        [removeButton addTarget:self action:@selector(onRemoveButtonClicked:) forControlEvents:UIControlEventTouchUpInside];

        closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [closeButton setTitle:NSLocalizedString(@"Close", @"") forState:UIControlStateNormal];
        [closeButton setBackgroundColor:RGBCOLOR(0x66, 0x66, 0x66)];
        [closeButton setTitleColor:RGBCOLOR(45, 140, 255) forState:UIControlStateNormal];
        closeButton.titleLabel.font = BUTTON_FONT;
        [closeButton addTarget:self action:@selector(onCloseVBButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
        
        useButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [useButton setTitle:NSLocalizedString(@"Use", @"") forState:UIControlStateNormal];
        [useButton setBackgroundColor:RGBCOLOR(0x66, 0x66, 0x66)];
        [useButton setTitleColor:RGBCOLOR(45, 140, 255) forState:UIControlStateNormal];
        useButton.titleLabel.font = BUTTON_FONT;
        [useButton addTarget:self action:@selector(onUseVBButtonClicked:) forControlEvents:UIControlEventTouchUpInside];

        [self.view addSubview:addButton];
        [self.view addSubview:removeButton];
        [self.view addSubview:closeButton];
        [self.view addSubview:useButton];
    } else {
        MobileRTCMeetError error = [ms enableGreenVB:YES];
        NSLog(@"[VB Test] enableGreenVB : %@.", @(error));
        // please select one point and use the "- (MobileRTCMeetError)selectGreenVBPoint:(CGPoint)point;" pass to sdk.
    }
}

- (void)onAddButtonClicked:(id)sender
{
    MobileRTCMeetingService *ms = [[MobileRTC sharedRTC] getMeetingService];
    if ([ms isSupportSmartVirtualBG]) {
        MobileRTCMeetError ret = [ms addBGImage:[UIImage imageNamed:@"zoom_intro3"]];
        NSLog(@"[VB Test] addBGImage : %@.", @(ret));
    }
}

- (void)onRemoveButtonClicked:(id)sender
{
    MobileRTCMeetingService *ms = [[MobileRTC sharedRTC] getMeetingService];
    NSArray *imgList = [ms getBGImageList];
    if ([ms isSupportSmartVirtualBG]) {
        MobileRTCMeetError ret = [ms removeBGImage:[imgList lastObject]];
        NSLog(@"[VB Test] removeBGImage : %@.", @(ret));
    }
}

- (void)onCloseVBButtonClicked:(id)sender
{
    MobileRTCMeetingService *ms = [[MobileRTC sharedRTC] getMeetingService];
    if ([ms isSupportSmartVirtualBG]) {
        MobileRTCMeetError ret = [ms useNoneImage];
        NSLog(@"[VB Test] useNoneImage : %@.", @(ret));
    }
}

- (void)onUseVBButtonClicked:(id)sender
{
    MobileRTCMeetingService *ms = [[MobileRTC sharedRTC] getMeetingService];
    if ([ms isSupportSmartVirtualBG]) {
        NSArray *imgList = [ms getBGImageList];
        for (MobileRTCVirtualBGImageInfo *obj in imgList) {
            if (!obj.isNone && !obj.isSelect) {
                MobileRTCMeetError ret = [ms useBGImage:obj];
                NSLog(@"[VB Test] useBGImage : %@.", @(ret));
                return;
            }
        }
    }
    
    NSLog(@"[VB Test] onUseVBButtonClicked : not found any background image");
}
@end

You can also see how this looks/works in the MobileRTCSample application that is included with the SDK download.

  1. Set your domain and JWT in the AppDelegate.h file in the #define macros
  2. Set your own provisioning profile for both the main target and screenshare target
  3. Disable the appgroupID’s that are checked by default
  4. Remove the hardcoded provisioning profile in the Build Settings of the ScreenShare target
  5. Build and Run
  6. Click the settings button in the top right
  7. Click Meeting Settings → turn on custom meeting
  8. Navigate back to the home screen
  9. Join a meeting
  10. Once in the meeting, click the Virtual Background button from the meeting settings view
  11. The presented viewController will show your current camera stream with a virtual background (or without). This is the preview view. The buttons at the bottom call the virtual background functions. The code for this viewController is located in the file VBViewController.m

Thanks!
Michael

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.