(feat): improved microphone gate
(fix): weird behaviour related to users that are screensharing
This commit is contained in:
parent
e76c579bb4
commit
c795f691bf
5 changed files with 34 additions and 9 deletions
|
|
@ -152,12 +152,12 @@ export default function Base({
|
|||
|
||||
const onClick = () => {
|
||||
if (view === "grid") {
|
||||
focusParticipant(user.user_id);
|
||||
focusParticipant(user.user_id, type);
|
||||
} else {
|
||||
if (user.user_id === focusedParticipantId) {
|
||||
setCallView("grid");
|
||||
} else {
|
||||
focusParticipant(user.user_id);
|
||||
focusParticipant(user.user_id, type);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -215,7 +215,7 @@ export default function Base({
|
|||
ref={currentCard}
|
||||
className={`transition-all duration-150 z-10 bg-card absolute top-0 left-0 w-full h-full flex gap-2 items-center justify-center ${
|
||||
flush ? "rounded-none" : "rounded-sm"
|
||||
} ${isSpeaking ? "border-4 border-(--primary-foreground-alt)/75" : "border-0"}`}
|
||||
} ${type === "user" && isSpeaking ? "border-4 border-(--primary-foreground-alt)/75" : "border-0"}`}
|
||||
style={{ containerType: "size" }}
|
||||
>
|
||||
{/* Detect video / user and place here */}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { log } from "@tensamin/shared/log";
|
||||
import { useCall } from "./store";
|
||||
|
||||
const SPEAKING_THRESHOLD = 0.01;
|
||||
const SPEAKING_HANGTIME_MS = 250;
|
||||
const SPEAKING_HANGTIME_MS = 500;
|
||||
const ANALYSIS_INTERVAL_MS = 30;
|
||||
const FFT_SIZE = 256;
|
||||
|
||||
|
|
@ -137,8 +138,10 @@ class SpeakingDetector {
|
|||
const db = 20 * Math.log10(Math.max(rms, 0.0001));
|
||||
|
||||
if (!this.localMicGateClosed && db < this.gateThresholdStart) {
|
||||
log(3, "noise gate", "purple", "closed");
|
||||
this.muteLocalTrack(true);
|
||||
} else if (this.localMicGateClosed && db > this.gateThresholdEnd) {
|
||||
log(3, "noise gate", "purple", "opened");
|
||||
this.muteLocalTrack(false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ type CallStore = {
|
|||
screenShareEnabled: boolean;
|
||||
screenShareSession: ScreenShareSession | null;
|
||||
focusedParticipantId: number | null;
|
||||
focusedParticipantType: "user" | "stream" | null;
|
||||
usersInFocusedViewHidden: boolean;
|
||||
watchedStreamParticipantIds: number[];
|
||||
pendingWatchedParticipantIds: number[];
|
||||
|
|
@ -464,6 +465,8 @@ function syncScreenShareParticipants() {
|
|||
watchedStreamParticipantIds,
|
||||
pendingWatchedParticipantIds,
|
||||
focusedParticipantId,
|
||||
focusedParticipantType:
|
||||
focusedParticipantId == null ? null : state.focusedParticipantType,
|
||||
view:
|
||||
state.view === "focused" && focusedParticipantId == null
|
||||
? "grid"
|
||||
|
|
@ -634,6 +637,7 @@ export function startWatchingStream(participantId: number) {
|
|||
? state.pendingWatchedParticipantIds
|
||||
: [...state.pendingWatchedParticipantIds, participantId],
|
||||
focusedParticipantId: participantId,
|
||||
focusedParticipantType: "stream",
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
@ -653,9 +657,13 @@ export function setParticipantTrackSubscribed(
|
|||
}
|
||||
|
||||
// Focus a participant in the main call view even when they are not sharing a screen.
|
||||
export function focusParticipant(participantId: number) {
|
||||
export function focusParticipant(
|
||||
participantId: number,
|
||||
type: "user" | "stream" = "user",
|
||||
) {
|
||||
useCall.setState({
|
||||
focusedParticipantId: participantId,
|
||||
focusedParticipantType: type,
|
||||
view: "focused",
|
||||
});
|
||||
}
|
||||
|
|
@ -675,6 +683,10 @@ export function stopWatchingStream(participantId: number) {
|
|||
state.focusedParticipantId === participantId
|
||||
? null
|
||||
: state.focusedParticipantId,
|
||||
focusedParticipantType:
|
||||
state.focusedParticipantId === participantId
|
||||
? null
|
||||
: state.focusedParticipantType,
|
||||
view:
|
||||
state.view === "focused" && state.focusedParticipantId === participantId
|
||||
? "grid"
|
||||
|
|
@ -790,6 +802,7 @@ export async function disconnect() {
|
|||
view: "preview",
|
||||
screenShareSession: null,
|
||||
focusedParticipantId: null,
|
||||
focusedParticipantType: null,
|
||||
usersInFocusedViewHidden: false,
|
||||
watchedStreamParticipantIds: [],
|
||||
pendingWatchedParticipantIds: [],
|
||||
|
|
@ -950,6 +963,7 @@ export function resetCallState() {
|
|||
deaf: false,
|
||||
screenShareSession: null,
|
||||
focusedParticipantId: null,
|
||||
focusedParticipantType: null,
|
||||
usersInFocusedViewHidden: false,
|
||||
watchedStreamParticipantIds: [],
|
||||
pendingWatchedParticipantIds: [],
|
||||
|
|
@ -1002,6 +1016,7 @@ export const useCall = create<CallStore>(() => ({
|
|||
screenShareEnabled: room.localParticipant.isScreenShareEnabled,
|
||||
screenShareSession: null,
|
||||
focusedParticipantId: null,
|
||||
focusedParticipantType: null,
|
||||
usersInFocusedViewHidden: false,
|
||||
watchedStreamParticipantIds: [],
|
||||
pendingWatchedParticipantIds: [],
|
||||
|
|
@ -1038,7 +1053,7 @@ export function useInitializeCall() {
|
|||
new DeepFilterNoiseFilterProcessor({
|
||||
enabled: true,
|
||||
enableNoiseReduction: true,
|
||||
noiseReductionLevel: 80,
|
||||
noiseReductionLevel: 60,
|
||||
sampleRate: 48000,
|
||||
assetConfig: {
|
||||
cdnUrl: "/assets",
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ export default function View() {
|
|||
const callIsFullscreen = useCall((state) => state.callIsFullscreen);
|
||||
|
||||
const focusedParticipantId = useCall((state) => state.focusedParticipantId);
|
||||
const focusedParticipantType = useCall(
|
||||
(state) => state.focusedParticipantType,
|
||||
);
|
||||
const activeScreenShareParticipantIds = useCall(
|
||||
(state) => state.activeScreenShareParticipantIds,
|
||||
);
|
||||
|
|
@ -157,6 +160,10 @@ export default function View() {
|
|||
const focusedParticipant = getParticipantById(focusedParticipantId);
|
||||
const focusedParticipantHasActiveScreenShare =
|
||||
activeScreenShareParticipantIdSet.has(focusedParticipantId);
|
||||
const focusedTileType: "user" | "stream" =
|
||||
focusedParticipantType === "stream" && focusedParticipantHasActiveScreenShare
|
||||
? "stream"
|
||||
: "user";
|
||||
const isImmersiveFocusedView = callIsFullscreen && usersInFocusedViewHidden;
|
||||
|
||||
return (
|
||||
|
|
@ -179,7 +186,7 @@ export default function View() {
|
|||
<Base
|
||||
fill={isImmersiveFocusedView}
|
||||
flush={isImmersiveFocusedView || isFocusedTileFlush}
|
||||
type={focusedParticipantHasActiveScreenShare ? "stream" : "user"}
|
||||
type={focusedTileType}
|
||||
participant={focusedParticipant}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue