Random remote participant video Failure in Zoom Video SDK

Hi Team,

We are using the Zoom Video SDK for our video chat application, and we’ve encountered an issue during video calls. The problem occurs randomly: when I start a video call, the remote participant’s video does not appear on my end, although the other participant can see both videos. While I can see my own video, the remote participant’s video is missing on my screen.

This issue has occurred multiple times consecutively. Below are the session IDs of the affected calls for your reference:

  1. BqVmZIJZRUa5kHvSqHjBmw==
  2. ohCv6CfES7OhbAZ37Q8l4A==

Could you please investigate the cause of this video failure and suggest a solution at the earliest? This issue is significantly impacting our business operations, so a prompt resolution would be greatly appreciated.

Thank you in advance for your support.

Could you share some code snippets related to this issue?

By the way, from the session logs we found the Video SDK version is 1.11.10, could you upgrade the version and try it again?

Thanks
Vic

Hi @vic.yang ,
Thank you for suggesting upgrading the SDK version. I will go ahead and update to the latest version.
Regarding the code snippets, please find them below :

const connectVideoChat = async () => {
        await zmClient?.init('en-US', 'Global', { patchJsMedia: true, enforceMultipleVideos: true });
        try {
            await zmClient?.join(sessionName, zoomToken, userName).catch((e) => { 
        } catch (e: any) {
            console.log(e, 'e.reason while joining the zoom session ======================>');
        }
    }
const videoPlayerListRef = useRef<Record<string, VideoPlayer>>({});
const mediaStream = zmClient?.getMediaStream();
const attachment = videoPlayerListRef.current[`${userId}`];
mediaStream?.attachVideo(userId, VideoQuality.Video_720P, attachment);
<video-player-container class={`${(participants && participants.length) > 1 ? "video-container-wrap d-flex" : "video-container-wrap"} `}>
<div>
    {participants.length > 0 &&
        participants?.map((user: any) => {
            return (
                <>
                    {/* {user.bVideoOn ? "true" : "false"} */}
                    {user.bVideoOn ?
                        <div className='w-100'>
                            <video-player
                                key={user.userGuid}
                                style={user.bVideoOn ? { "aspectRatio": "16/9" } : { "background": "black", "aspectRatio": "1/1" }}
                                className='video-player'
                                ref={(element) => {
                                    setVideoPlayerRef(user.userId, element);
                                }}
                                node-id={user.userId}
                            />
                        </div>
                        : <div className='agent-video-wrapper'><i className="bi bi-camera-video-off" style={{ "color": "white" }}></i></div>
                    }
                </>
            );
        })
</div>                         
</video-player-container>

<video-player-container class="video-container-wrap">
                                        <div className="ml-auto Participant-video-frame">
                                            {zoomLocalParticipant?.map((user: any) => {
                                                return (
                                                    <div
                                                        className="video-cell localParticipantVideoClass video-thumbnail player-mute-icon"
                                                        key={user.userId}
                                                        style={user.bVideoOn ? { "aspectRatio": "16/9" } : { "background": "#6b6e76", "aspectRatio": "16/9" }}
                                                    >
                                                        {user.bVideoOn ?
                                                            <div key={user.userGuid} className='player-icons'>
                                                                <video-player
                                                                    class="video-player localParticipantVideoCard"
                                                                    ref={(element) => {
                                                                        setVideoPlayerRef(user.userId, element);
                                                                    }}
                                                                />
                                                                <span className='position-relative'>{audioDisable ? <i className="bi bi-mic-mute mute-icon"></i> : <></>} </span>
                                                            </div>

                                                            : <i className="bi bi-camera-video-off" style={{ "color": "white" }}></i>
                                                        }
                                                    </div>
                                                );
                                            })}
                                        </div>
                                    </video-player-container>

Thanks again for your prompt response and assistance.

Hi @vic.yang ,
I hope you’re doing well. I’m following up on the “Random Remote Participant Video Failure” issue. I trust you’ve had a chance to review the code snippets and details I shared a couple of days ago.

Could you please provide an update on the status of my request? Additionally, let me know if there’s any further information needed from my side.

On a related note, in cases where a participant’s video doesn’t appear, could you recommend any specific event or property from Zoom that we can use as a reliable indicator? This would allow us to implement a retry logic within our functionality based on that value.

Looking forward to your response.

Hey @anjithiruveedhi238

I noticed in the code that there are two user-related lists:

  • participants
  • zoomLocalParticipant.

What is the difference between these two? The users in these two lists should not overlap, as they are rendered in separate video-player-container containers.

Additionally, it is not recommended to manually set the node-id attribute on the video-player element; it needs to be updated through the attachVideo/detachVideo methods.

Thanks
Vic

Hi @vic.yang,

Thank you for your response.

Regarding the two user-related lists:

  • participants refers to remote participants.
  • zoomLocalParticipant refers to the local user (self).

The videos for these two lists do not overlap. We’ve implemented styling to display the local video as a smaller overlay, while the remote participant’s video is shown as the larger main view. For clarity, I’ve attached a screenshot below for your reference.


Regarding the node-id, we are updating it using the attachVideo and detachVideo methods as recommended and we will change the code as you suggested. Below is the relevant portion of the code for your reference:
Below I’m providing the code for your reference.

try {
            const addedUsers = subscribers.filter((user) => !(previousSubscribers || []).includes(user));
            const removedUsers = (previousSubscribers || []).filter((user: any) => !subscribers.includes(user));
            if (removedUsers.length > 0) {
                removedUsers.forEach((userId: any) => {
                    mediaStream?.detachVideo(userId);
                });
            }
            if (addedUsers.length > 0) {
                addedUsers.forEach((userId) => {
                    const attachment = videoPlayerListRef.current[`${userId}`];
                    if (attachment) {
                        mediaStream?.attachVideo(userId, VideoQuality.Video_720P, attachment);
                    }
                });
            }
        }

Could you let us know if you’ve identified any possible reasons for the video display failure during the two calls I mentioned earlier?
“On a related note, for cases where a participant’s video doesn’t appear, could you suggest any specific event or property from Zoom that we can use as a reliable indicator? This would allow us to implement a retry logic within our functionality.”

Looking forward to your insights and any updates on this.

1 Like

Hey @anjithiruveedhi238

On a related note, for cases where a participant’s video doesn’t appear, could you suggest any specific event or property from Zoom that we can use as a reliable indicator?

Yes.

We have multiple events to handle the issue.

  • For remote video black screen cases, you can call stream.subscribeVideoStatisticData({detailed: true}) and then listen to the video-detailed-data-change event. This will allow you to retrieve the resolution and FPS of each remote video. In black screen cases, both FPS and resolution will be 0.
  • For self-video issues, you can listen to the active-media-failed event, which notifies you of abnormalities in the current stream. In future versions, we will optimize this event to provide more detailed information in the event payload.

Thanks
Vic