Hello! I’m trying to implement the PiP feature in a React web app, but I’m running into some issues. I read the article that you guys have on this, but that is not working exactly as expected, meaning that you have to copy the fully initialized node and append it to the PiP document’s body. So if anything changes, for example someone turns his camera off, the video just freezes etc. I want to be able to use the methods that are available for the main document such as attachVideo or renderVideo, but I’m failing to do that.
attachVideo: I understand that there ‘video-player-container’ and ‘video-player’ are custom elements that are somehow initialized internally, so I don’t expect them to work. I don’t get any errors, just a blank element with blacked out background when i use this method. This is how the PiP DOM looks like:
<video-player-container>
<video-player class="custom-video-player" node-id="33555456"></video-player>
</video-player-container>
renderVideo: If i try to use this with an HTMLCanvasElement, i get this error:
{ reason: "Expected to accept HTMLCanvasElement or HTMLVideoElement, but actual it is HTMLCanvasElement",
type: "INVALID_PARAMETERS" }
Are there any solutions for this? Can i somehow initialize those custom elements in the PiP window? Or can I use renderVideo in any other way for this to work?
useEffect(() => {
const myUserId = zoomClient?.getSessionInfo().userId;
const participantsWithoutMe = participants;
// .filter(
// (participant) => participant.userId !== myUserId
// );
if (
!pipDocument ||
!participantsWithoutMe ||
!participantsWithoutMe.length ||
!zoomClient ||
!stream
)
return;
// Clear the PiP document body before re-rendering
pipDocument.body.innerHTML = '';
// Create a container to render into
const pipContainer = pipDocument.createElement('div');
pipContainer.id = 'pip-root';
pipDocument.body.appendChild(pipContainer);
ReactDOM.render(
<PiPVideoContent
participants={participantsWithoutMe}
speakingParticipants={speakingParticipants}
raisedHands={raisedHands}
thumbsUpList={thumbsUpList}
onSetVideoRef={onSetPipVideoRef}
/>,
pipContainer,
() => {
// After render completes, attach/detach videos
handlePipVideoUpdates(participantsWithoutMe);
}
);
}, [
pipDocument,
participants,
speakingParticipants,
raisedHands,
thumbsUpList,
zoomClient,
stream,
]);
const handlePipVideoUpdates = async (participants: Participant[]) => {
if (!stream || !zoomClient) return;
const myUserId = zoomClient.getSessionInfo().userId;
// for (const participant of participants) {
// await stream.detachVideo(participant.userId);
// }
for (const participant of participants) {
// if (participant.userId === myUserId) continue;
const ref = pipVideoListRef.current[participant.userId];
console.log({ ref });
if (participant.bVideoOn && ref) {
try {
await stream.renderVideo(
ref,
participant.userId,
undefined,
undefined,
undefined,
undefined,
VideoQuality.Video_720P
);
// await stream.attachVideo(
// participant.userId,
// VideoQuality.Video_720P,
// ref // The ref should be the DOM node for the video element
// );
console.log('here in for 2');
} catch (error) {
console.error('Error attaching PiP video:', error);
}
} else if (!participant.bVideoOn && ref) {
try {
stream.stopRenderVideo(ref, participant.userId);
} catch (error) {
console.error('Error detaching PiP video:', error);
}
}
}
};
Also, i tried uploading a screenshot here, but it’s telling me “An error occurred: Sorry, you can’t embed media items in a post.”
Version: 1.12.5
Device: Macbook Pro
OS: macOS 15.1
Browser: Chrome