Add image virtual background in client view

Ask
how to add image virtual background option in client view like on desktop app?

Stack
Nextjs

Screenshot
in down below (reply)

Code

"use client";

import config from "@/config/config";
import { buildQueryString } from "@/utils/string";
import { ZoomMtg } from "@zoom/meetingsdk";
import { useRouter, useSearchParams } from "next/navigation";
import { ChangeEvent, useEffect, useState } from "react";
import Button from "../Button";
import styles from "./style.module.css";

const { zoom } = config;

interface IMeetingData {
  name: string;
  mn: string;
  passcode: string;
}

interface ZoomSignatureResponse {
  signature: string;
}

const initializeZoomMeeting = (signature: string, data: IMeetingData) => {
  ZoomMtg.i18n.load(zoom.lang as any);
  ZoomMtg.init({
    leaveUrl: `${zoom.leaveUrl}?${buildQueryString(data)}`,
    disableRecord: true,
    isSupportChat: false,
    success: () => joinZoomMeeting(signature, data),
    error: (error: any) => console.error("Zoom initialization error:", error),
  });
};

const joinZoomMeeting = (signature: string, data: IMeetingData) => {
  ZoomMtg.join({
    sdkKey: zoom.clientId,
    signature,
    meetingNumber: data.mn,
    passWord: data.passcode,
    userName: data.name,
    success: (success: any) =>
      console.log("Successfully joined the meeting", success),
    error: (error: any) => console.error("Error joining the meeting:", error),
  });
};

const ZoomMeeting = () => {
  const [isLoading, setIsLoading] = useState(false);
  const [meetingData, setMeetingData] = useState<IMeetingData>({
    name: "",
    mn: "",
    passcode: "",
  });
  const [showForm, setShowForm] = useState(true);
  const searchParams = useSearchParams();
  const { replace } = useRouter();

  const getSignature = async (meetingNumber: string): Promise<string> => {
    try {
      const response = await fetch("/api/zoom", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ meetingNumber, role: 0 }),
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const data: ZoomSignatureResponse = await response.json();
      if (!data.signature) {
        throw new Error("Failed to get signature");
      }

      return data.signature;
    } catch (error) {
      console.error("Error getting signature:", error);
      throw error;
    }
  };

  const handleMeetingSetup = async (data: IMeetingData) => {
    setIsLoading(true);
    try {
      replace(`?${buildQueryString(data)}`);
      const signature = await getSignature(data.mn);
      initializeZoomMeeting(signature, data);
    } catch (error) {
      console.error("Error setting up the meeting:", error);
    } finally {
      setIsLoading(false);
    }
  };

  const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target;
    setMeetingData((prev) => ({ ...prev, [name]: value }));
  };

  useEffect(() => {
    const name = searchParams.get("name") || "";
    const mn = searchParams.get("mn") || "";
    const passcode = searchParams.get("passcode") || "";
    setMeetingData({ name, mn, passcode });

    if (name !== "" && mn !== "") {
      setShowForm(false);
      handleMeetingSetup({
        name,
        mn,
        passcode,
      });
    } else {
      setShowForm(true);
    }
  }, [searchParams]);

  if (!showForm) {
    return null;
  }

  return (
    <main className={styles.container}>
      <h1 className={styles.title}>Join Zoom Meeting</h1>
      <form
        onSubmit={(e) => {
          e.preventDefault();
          handleMeetingSetup(meetingData);
        }}
        className={styles.form}
      >
        {(["name", "mn", "passcode"] as const).map((field) => (
          <div key={field} className={styles.formGroup}>
            <label className={styles.label}>
              {field === "mn"
                ? "Meeting Number"
                : `${field.charAt(0).toUpperCase() + field.slice(1)}`}
            </label>
            <input
              className={styles.input}
              placeholder={`Enter ${field === "mn" ? "meeting number" : field}`}
              value={meetingData[field]}
              name={field}
              onChange={handleInputChange}
              required={field !== "passcode"}
            />
          </div>
        ))}
        <Button type="submit" disabled={isLoading}>
          {isLoading ? "Loading..." : "Join Meeting"}
        </Button>
      </form>
    </main>
  );
};

export default ZoomMeeting;

Screenshot
client view:


desktop app:

Hey @shafanaura48
Thanks for reaching out!
I am happy to help here!
there is a method available for the Zoom meeting SDK for web to setVirtualBackground

Hello @elisa.zoom
I am facing similar issue,

I am using Meeting SDK of latest version in my reactJS web to enable zoom meeting.
I am using Client view component

Also SharedArrayBuffer is there to enable the virtual background and other features.

Everything is working fine but, I am not getting (+) button of add custom virtual background.
Like i am not seeing option to upload a custom image for VB. Do i have to do any extra configuration in my code for this?

Can you please help me with that.
Thanks.

Attached Screenshot for the reference.