All checks were successful
Build and Release / build-and-release (push) Successful in 10m6s
119 lines
4.3 KiB
JavaScript
119 lines
4.3 KiB
JavaScript
import { useState, useEffect, useRef } from 'react';
|
|
import { RoomEvent } from 'livekit-client';
|
|
|
|
export const VideoRenderer = ({ track, style }) => {
|
|
const videoRef = useRef(null);
|
|
|
|
useEffect(() => {
|
|
const el = videoRef.current;
|
|
if (el && track) {
|
|
track.attach(el);
|
|
return () => {
|
|
track.detach(el);
|
|
};
|
|
}
|
|
}, [track]);
|
|
|
|
return (
|
|
<video
|
|
ref={videoRef}
|
|
style={{ width: '100%', height: '100%', objectFit: 'contain', backgroundColor: 'black', ...style }}
|
|
/>
|
|
);
|
|
};
|
|
|
|
export function findTrackPubs(participant) {
|
|
let cameraPub = null;
|
|
let screenSharePub = null;
|
|
let screenShareAudioPub = null;
|
|
|
|
const trackMap = participant.tracks || participant.trackPublications;
|
|
if (trackMap) {
|
|
for (const pub of trackMap.values()) {
|
|
const source = pub.source ? pub.source.toString().toLowerCase() : '';
|
|
const name = pub.trackName ? pub.trackName.toLowerCase() : '';
|
|
|
|
if (source === 'screen_share_audio' || name === 'screen_share_audio') {
|
|
screenShareAudioPub = pub;
|
|
} else if (source === 'screenshare' || source === 'screen_share' || name.includes('screen')) {
|
|
screenSharePub = pub;
|
|
} else if (source === 'camera' || name.includes('camera')) {
|
|
cameraPub = pub;
|
|
} else if (pub.kind === 'video' && !screenSharePub) {
|
|
screenSharePub = pub;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fallback for older SDKs
|
|
if ((!screenSharePub && !cameraPub) && participant.getTracks) {
|
|
try {
|
|
for (const pub of participant.getTracks()) {
|
|
const source = pub.source ? pub.source.toString().toLowerCase() : '';
|
|
const name = pub.trackName ? pub.trackName.toLowerCase() : '';
|
|
if (source === 'screen_share_audio' || name === 'screen_share_audio') {
|
|
screenShareAudioPub = pub;
|
|
} else if (source === 'screenshare' || source === 'screen_share' || name.includes('screen')) {
|
|
screenSharePub = pub;
|
|
} else if (source === 'camera' || name.includes('camera')) {
|
|
cameraPub = pub;
|
|
} else if (pub.kind === 'video' && !screenSharePub) {
|
|
screenSharePub = pub;
|
|
}
|
|
}
|
|
} catch (e) { /* ignore */ }
|
|
}
|
|
|
|
return { cameraPub, screenSharePub, screenShareAudioPub };
|
|
}
|
|
|
|
export function useParticipantTrack(participant, source) {
|
|
const [track, setTrack] = useState(null);
|
|
|
|
useEffect(() => {
|
|
if (!participant) { setTrack(null); return; }
|
|
|
|
const resolve = () => {
|
|
const { cameraPub, screenSharePub } = findTrackPubs(participant);
|
|
const pub = source === 'camera' ? cameraPub : screenSharePub;
|
|
|
|
if (pub && !pub.isSubscribed && source === 'camera') {
|
|
pub.setSubscribed(true);
|
|
}
|
|
|
|
setTrack(pub?.track || null);
|
|
};
|
|
|
|
resolve();
|
|
const interval = setInterval(resolve, 1000);
|
|
const timeout = setTimeout(() => clearInterval(interval), 10000);
|
|
|
|
const onPub = () => resolve();
|
|
const onUnpub = () => resolve();
|
|
|
|
participant.on(RoomEvent.TrackPublished, onPub);
|
|
participant.on(RoomEvent.TrackUnpublished, onUnpub);
|
|
participant.on(RoomEvent.TrackSubscribed, onPub);
|
|
participant.on(RoomEvent.TrackUnsubscribed, onUnpub);
|
|
participant.on(RoomEvent.TrackMuted, onPub);
|
|
participant.on(RoomEvent.TrackUnmuted, onPub);
|
|
participant.on('localTrackPublished', onPub);
|
|
participant.on('localTrackUnpublished', onUnpub);
|
|
|
|
return () => {
|
|
clearInterval(interval);
|
|
clearTimeout(timeout);
|
|
participant.off(RoomEvent.TrackPublished, onPub);
|
|
participant.off(RoomEvent.TrackUnpublished, onUnpub);
|
|
participant.off(RoomEvent.TrackSubscribed, onPub);
|
|
participant.off(RoomEvent.TrackUnsubscribed, onUnpub);
|
|
participant.off(RoomEvent.TrackMuted, onPub);
|
|
participant.off(RoomEvent.TrackUnmuted, onPub);
|
|
participant.off('localTrackPublished', onPub);
|
|
participant.off('localTrackUnpublished', onUnpub);
|
|
};
|
|
}, [participant, source]);
|
|
|
|
return track;
|
|
}
|