daily-examples/custom/shared/hooks/useNetworkState.js

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;
};