The Zoom room loading/start times feel slow compared to Twilio

Compared to Twilio, Zoom is very slow in:

  1. camera turning on;
  2. users connecting to the room.

Is it possible to affect these items? Is there a way to speed these processes up?
Is the Zoom team going to improve these processes in the next releases?

Related:
After connecting to the room, the user sees the black screen for 1-3 seconds, and only after that, the stream starts opening.
How can we understand that on the user side, everything is loaded and ready to display the stream?
We tried using the following condition:

const isLoading = user?.audio !== 'computer';

But it still doesn’t work perfectly

Render:

        const zoomSession = zmClient.getMediaStream();
        zmClient.getAllUser().forEach(async (user) => {
            if (user.bVideoOn) {
                const userVideo = await zoomSession.attachVideo(user.userId, Video_720P);
                const targetElement = document.getElementById(`${PARTICIPANT_VIDEO_ID}_${user.userId}`)?.querySelector("video-player-container");
                targetElement?.appendChild(userVideo);
            }

            if (user.sharerOn) {
                const targetElement = document.getElementById(`${SHARE_CANVAS_ID}_${user.userId}`);
                if (targetElement) await zoomSession.startShareView(targetElement, user.userId);
            }
        });

SharedArrayBuffer is disabled
Zoom Video SDK 1.11.6
React 17.0.2

Hey @sergey77

Thanks for your feedback.

We are continuously optimizing the join speed and audio/video experience.

Currently, there are several optimization methods that can be adopted:

Thanks
Vic

Hi @vic.yang ,

  1. Am I getting right that the “preloadDependentAssets” should be called before initializing the client?

That is:

    const zmClient = ZoomVideo.createClient();

    await ZoomVideo.preloadDependentAssets(`${window.location.origin}/lib`);

    await zmClient.init("en-US", `${window.location.origin}/lib`, {
        webEndpoint: window?.webEndpoint ?? "zoom.us",
        stayAwake: true,
        patchJsMedia: true,
        leaveOnPageUnload: true,
        enforceVirtualBackground: true,
        enforceMultipleVideos: true,
    });

  • We recommend determining the loading state based on the connection-change event. If state='Connected', it indicates that the session has been successfully joined.

We do all this, but this still doesn’t work perfectly. After rendering, the user sees a black screen for several seconds, and only after this, the stream starts being displayed. We need a way to determine when everything is loaded on the user’s side and the stream can be displayed immediately, until that, we’ll display an animation with the loader to them

Any advice on how to do that?

Hey @sergey77

  1. Am I getting right that the “preloadDependentAssets” should be called before initializing the client?

Yes. That’s correct. Make sure the preloaded assets path is the same as the path used in client.init method.

Any advice on how to do that?

Microphone or camera capture may take some time, especially if it involves granting permissions, making the timing unpredictable.

Therefore, in our implementation, we typically show the user’s display name by default and replace it with their video once the media stream is captured.

Please feel free to reach out to me with any concerns about this.

Thanks
Vic

Hi @vic.yang ,
Thanks for the answer.

Your demo app uses the condition “bVideoOn && audio === ‘computer’” to determine that the user’s media stream is captured.

Is that correct?
I use exactly the same condition in my code and it doesn’t work perfectly

Hey @sergey77

“bVideoOn && audio === ‘computer’”
Is that correct?

Only need to check one of them.

  • bVideoOn===true represents video is captured
  • audio === 'computer' represents audio is captured

Thanks
Vic

1 Like

Hi @vic.yang ,
Could you please watch the video I recorded from Zoom Video SDK web sample?

It shows that after the Safari user gives permission to capture video from the camera, both users on stage see a black screen for a few seconds before the stream starts. We need ways to improve this. The goal is to not display a black screen. That is, after the user’s initials disappear, the stream should immediately start.
We should not show a black screen for a few seconds while the stream is loading

Hey @sergey77

Thank you for sharing the recording.

This could be a delay in enabling the camera on the Safari browser.

Could you try the official WebRTC demo and see if you experience the same issue?

Thanks
Vic

Hi @vic.yang ,
I tried testing Safari in the official WebRTC demo, and got a delay of 4-5 seconds there too.

We need a way to trace when the camera is completely ready and the stream is loaded and ready for being immediately displayed. That is, to show a loader animation to the user instead of a black screen

Hey @sergey77

Share some thoughts regarding this case:

// Display a loading animation before calling the `stream.startVideo` method
loadingElement.style.display = "block";
try {
  await stream.startVideo();
} finally {
  // Remove the animation when this method is resolved or rejected.
  loadingElement.style.display = "none";
}

Thanks
Vic

1 Like

Hi @vic.yang ,
This makes sense on the side of the user who uses Safari, but we also need to have a solution on the side of the user who receives the stream from the second user (who uses Safari)

Hey @sergey77

Currently, we do not have a built-in method to achieve this, but it can be done using the command channel. Here is a pseudocode implementation for this requirement:

// On the sender side
const commandChannel = client.getCommandClient();
// Display a loading animation before calling the `stream.startVideo` method
loadingElement.style.display = "block";
commandChannel.send(JSON.stringify({ action: "send video start" }));
try {
  await stream.startVideo();
} finally {
  // Remove the animation when this method is resolved or rejected.
  loadingElement.style.display = "none";
  commandChannel.send(JSON.stringify({ action: "send video successfully" }));
}
// On the receive side
client.on("command-channel-message", (payload) => {
  const { senderId, text } = payload;
  const command = JSON.parse(text ?? "{}");
  //Find the user video area corresponding to the senderID; this element has a loading child element.
  const loadingElement = document.querySelector(`[video_${senderId}]>.loading`);
  if (command.action === "send video start") {
    //  Display a loading animation
    loadingElement.style.display = "block";
  } else if (command.action === "send video successfully") {
    // Remove the animation
    loadingElement.style.display = "none";
  }
});

Thanks
Vic

1 Like

Hi @vic.yang, thanks for your support.
I’ll try it

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