110 lines
3.2 KiB
JavaScript
110 lines
3.2 KiB
JavaScript
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
import { useCallState } from '../contexts/CallProvider';
|
|
|
|
const STANDARD_HIGH_BITRATE_CAP = 980;
|
|
const STANDARD_LOW_BITRATE_CAP = 300;
|
|
|
|
export const useNetworkState = (
|
|
co = null,
|
|
quality = 'high'
|
|
) => {
|
|
const [threshold, setThreshold] = useState('good');
|
|
const lastSetKBS = useRef(null);
|
|
|
|
const callState = useCallState();
|
|
|
|
const callObject = co ?? callState?.callObject;
|
|
|
|
const setQuality = useCallback(
|
|
async (q) => {
|
|
if (!callObject) return;
|
|
const peers = Object.keys(callObject.participants()).length - 1;
|
|
const isSFU = (await callObject.getNetworkTopology()).topology === 'sfu';
|
|
const lowKbs = isSFU
|
|
? STANDARD_LOW_BITRATE_CAP
|
|
: Math.floor(STANDARD_LOW_BITRATE_CAP / Math.max(1, peers));
|
|
const highKbs = isSFU
|
|
? STANDARD_HIGH_BITRATE_CAP
|
|
: Math.floor(STANDARD_HIGH_BITRATE_CAP / Math.max(1, peers));
|
|
|
|
switch (q) {
|
|
case 'auto':
|
|
case 'high':
|
|
if (lastSetKBS.current === highKbs) break;
|
|
callObject.setBandwidth({
|
|
kbs: highKbs,
|
|
});
|
|
lastSetKBS.current = highKbs;
|
|
break;
|
|
case 'low':
|
|
if (lastSetKBS.current === lowKbs) break;
|
|
callObject.setBandwidth({
|
|
kbs: lowKbs,
|
|
});
|
|
lastSetKBS.current = lowKbs;
|
|
break;
|
|
case 'bandwidth-saver':
|
|
callObject.setLocalVideo(false);
|
|
if (lastSetKBS.current === lowKbs) break;
|
|
callObject.setBandwidth({
|
|
kbs: lowKbs,
|
|
});
|
|
lastSetKBS.current = lowKbs;
|
|
break;
|
|
}
|
|
},
|
|
[callObject]
|
|
);
|
|
|
|
const handleNetworkQualityChange = useCallback(
|
|
(ev) => {
|
|
if (ev.threshold === threshold) return;
|
|
|
|
switch (ev.threshold) {
|
|
case 'very-low':
|
|
setQuality('bandwidth-saver');
|
|
setThreshold('very-low');
|
|
break;
|
|
case 'low':
|
|
setQuality(quality === 'bandwidth-saver' ? quality : 'low');
|
|
setThreshold('low');
|
|
break;
|
|
case 'good':
|
|
setQuality(
|
|
['bandwidth-saver', 'low'].includes(quality) ? quality : 'high'
|
|
);
|
|
setThreshold('good');
|
|
break;
|
|
}
|
|
},
|
|
[quality, setQuality, threshold]
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (!callObject) return;
|
|
callObject.on('network-quality-change', handleNetworkQualityChange);
|
|
return () => {
|
|
callObject.off('network-quality-change', handleNetworkQualityChange);
|
|
};
|
|
}, [callObject, handleNetworkQualityChange]);
|
|
|
|
useEffect(() => {
|
|
if (!callObject) return;
|
|
setQuality(quality);
|
|
let timeout;
|
|
const handleParticipantCountChange = () => {
|
|
if (timeout) clearTimeout(timeout);
|
|
timeout = setTimeout(() => {
|
|
setQuality(quality);
|
|
}, 500);
|
|
};
|
|
callObject.on('participant-joined', handleParticipantCountChange);
|
|
callObject.on('participant-left', handleParticipantCountChange);
|
|
return () => {
|
|
callObject.off('participant-joined', handleParticipantCountChange);
|
|
callObject.off('participant-left', handleParticipantCountChange);
|
|
};
|
|
}, [callObject, quality, setQuality]);
|
|
|
|
return threshold;
|
|
}; |