Description
In the case of a layout with 2 video-player-containers (each stream user is rendered in one video-player-container), if the self video is rendered in a video-player-container that uses display: flex, this causes a black screen issue for the self video.
In version 2.1.0 this issue did not occur, but in version 2.2.5 it does. Could you clarify why this behavior changed and whether it is expected?
Browser Console Error
No error logs observed in the browser console.
Which Web Video SDK version?
Web Video SDK version**:** 2.2.5 (no issue in 2.1.0)
To Reproduce(If applicable)
Attach the self video and another user’s video to two different video-player-containers.
Detach both videos from their containers.
Re-attach them, but swap their positions between the two video-player-containers.
Troubleshooting Routes
Before attaching the stream, clone the video-player-container element and replace the original one to force the DOM to re-render.
With this workaround, the self video can render correctly, but this should not be required in normal behavior.
Device (please complete the following information):
Device: Mostly observed on mobile devices (both iOS and Android).
OS: Android 15, IOS 18.6 …
Browser: Chorme, Safari
Browser Version : Chorme 119, 118 …
Additional context
If we keep using the workaround (cloning and replacing the video-player-container to force DOM re-render), will it have any side effects on performance or stability
Is this approach recommended or could it cause unexpected issues when working with the Web Video SDK?
Also, is there a more optimal or recommended method to handle this case instead of cloning/replacing the element?
// start video
async function startVideo(){
await stream.startVideo();
const {userId} = client.getSessionInfo();
const element = await stream.attachVideo(userId, 3);
document.querySelector('.video1').appendChild(element);
}
// remote video
function videoUserBeforeJoin(){
client.getAllUser().forEach(async user => {
if (user.bVideoOn) {
const element = await stream.attachVideo(user.userId, 3);
document.querySelector('.video2').appendChild(element);
}
});
}
client.on('peer-video-state-change', async (payload) => {
const { action, userId } = payload;
if (action === 'Start') {
const element = await stream.attachVideo(userId, 3);
document.querySelector('.video2').appendChild(element);
} else if (action === 'Stop') {
const element = await stream.detachVideo(userId);
if (Array.isArray(element)) {
element.forEach(el => {
el.remove();
});
} else {
element.remove();
}
}
});
// switch video position
async function swapVideoPosition(){
const currentUserId = client.getSessionInfo().userId;
const firstVideoUser = client.getAllUser().filter(user => user.bVideoOn && user.userId !== currentUserId)[0];
// detach remote video
if(firstVideoUser){
const element = await stream.detachVideo(firstVideoUser.userId);
if (Array.isArray(element)) {
element.forEach(el => {
el.remove();
});
} else {
element.remove();
}
}
// detach current video
const element = await stream.detachVideo(currentUserId);
if (Array.isArray(element)) {
element.forEach(el => {
el.remove();
});
} else {
element.remove();
}
//attach remote video to video1 container
const newElement = await stream.attachVideo(firstVideoUser.userId, 3);
document.querySelector('.video1').appendChild(newElement);
//attach current video to video2 container
const newElement1 = await stream.attachVideo(currentUserId, 3);
document.querySelector('.video2').appendChild(newElement1);
}
I tested the swapVideoPosition method above and did not experience the self video
black screen issue. There is only one known issue: there’s a brief moment when the
video-player-container element appears black between detachVideo and attachVideo
calls, but as long as video rendering occurs, the element displays normally. We
will fix this in the upcoming release (2.2.10).
In the <video-player> component, setting position: static causes a display issue when following the To Reproduce steps. When I replace it with position: relative, the issue disappears, but if there are multiple <video-player> elements in the same video-player-container, their positions are incorrect for one frame. In VideoSDK version 2.1.0, I did not encounter this issue. Could you explain the difference between these two approaches and suggest a solution?
if there are multiple <video-player> elements in the same video-player-container , their positions are incorrect for one frame.
It depends on how you style the video-player element. Just treat it as a regular HTML element—you can use flex or grid layout to arrange them.
Could you explain the difference between these two approaches and suggest a solution?
I’m not sure which two approaches you want to compare. If it’s one video-player per video-player-container versus placing multiple video-players under the same video-player-container, we still recommend the latter because it offers better performance. However, it also depends on your actual use case.
When I set position: static on the element, after detaching and re-attaching the self video within the same video-player-container (and the container only contains the self video), the self video appears black until I manually resize the browser. Could you explain why this happens and what causes the video not to render correctly in this scenario?
Hi @vic.yang
I am experiencing an issue with video-player-container:
When attaching a remote video to a video-player-container, the SDK creates a shadow-root that contains a <canvas> element to render the video.
When attaching a local (start) video, the SDK also creates a shadow-root but without a <canvas>.
The problem occurs when I swap the remote video and the local video:
The <canvas> created from the previous remote video is not removed and still remains inside the shadow-root.
As a result, this <canvas> overlays the local video, causing the local video to appear black.
I confirmed this behavior in DevTools.
Could you please clarify if this is a bug in the SDK, and is there a way to ensure that the old <canvas> is properly cleaned up when swapping containers?
Thanks for your support!
The problem occurs when I swap the remote video and the local video:
The <canvas> created from the previous remote video is not removed and still remains inside the shadow-root.
As a result, this <canvas> overlays the local video, causing the local video to appear black.
I tested the same scenario and indeed found a canvas element inside the shadow-root of the swapped video-player-container. However, the actual rendering still uses the video tag, and since it comes after the canvas element, there is no overlay issue.
I have an additional finding with screenshots for reference:
After swapping containers, when the local video is blacked out, I noticed that if I manually change the width of the <canvas> inside the shadow-root, the local video becomes partially visible again. The visible area corresponds to the reduced pixel width of the <canvas>.
This suggests that the leftover <canvas> from the remote video render is not removed and continues to overlay on top of the local video, blocking it.
This issue occurs if the video-player element has position: static.
I applied your styles and also observed the black screen issue. Through debugging, I found that it was caused by the aspect-ratio property. After removing this property, it worked normally.
Hi @vic.yang
Currently, removing the aspect-ratio property does not solve the issue; when starting a video, the shadow DOM still overlays the content. I can only fix it by changing the position of the video-player element from static to relative, but this causes the subsequent video-player elements added to the video-player-container to briefly render in the wrong position for a few frames. Do you have any other suggestions for fixing the shadow DOM overlay problem?
Thanks for your support!
Sorry, I’m not sure how to fix this issue in your scenario, but if, as you mentioned, using relative positioning can resolve it, then that should work.