developer option to mute all audio (#3239)

This commit is contained in:
Timo
2025-05-13 21:11:12 +02:00
committed by GitHub
parent 34b3b9d733
commit 04bc6c77a3
8 changed files with 45 additions and 11 deletions

View File

@@ -70,6 +70,7 @@
"livekit_server_info": "LiveKit Server Info", "livekit_server_info": "LiveKit Server Info",
"livekit_sfu": "LiveKit SFU: {{url}}", "livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix ID: {{id}}", "matrix_id": "Matrix ID: {{id}}",
"mute_all_audio": "Mute all audio (participants, reactions, join sounds)",
"show_connection_stats": "Show connection statistics", "show_connection_stats": "Show connection statistics",
"show_non_member_tiles": "Show tiles for non-member media", "show_non_member_tiles": "Show tiles for non-member media",
"url_params": "URL parameters", "url_params": "URL parameters",

View File

@@ -47,12 +47,15 @@ export const callEventAudioSounds = prefetchSounds({
export function CallEventAudioRenderer({ export function CallEventAudioRenderer({
vm, vm,
muted,
}: { }: {
vm: CallViewModel; vm: CallViewModel;
muted?: boolean;
}): ReactNode { }): ReactNode {
const audioEngineCtx = useAudioContext({ const audioEngineCtx = useAudioContext({
sounds: callEventAudioSounds, sounds: callEventAudioSounds,
latencyHint: "interactive", latencyHint: "interactive",
muted,
}); });
const audioEngineRef = useLatest(audioEngineCtx); const audioEngineRef = useLatest(audioEngineCtx);

View File

@@ -62,8 +62,9 @@ import {
} from "../utils/errors.ts"; } from "../utils/errors.ts";
import { GroupCallErrorBoundary } from "./GroupCallErrorBoundary.tsx"; import { GroupCallErrorBoundary } from "./GroupCallErrorBoundary.tsx";
import { import {
useExperimentalToDeviceTransportSetting, useNewMembershipManager as useNewMembershipManagerSetting,
useNewMembershipManagerSetting as useNewMembershipManagerSetting, useExperimentalToDeviceTransport as useExperimentalToDeviceTransportSetting,
muteAllAudio as muteAllAudioSetting,
useSetting, useSetting,
} from "../settings/settings"; } from "../settings/settings";
import { useTypedEventEmitter } from "../useEvents"; import { useTypedEventEmitter } from "../useEvents";
@@ -104,11 +105,13 @@ export const GroupCallView: FC<Props> = ({
null, null,
); );
const [muteAllAudio] = useSetting(muteAllAudioSetting);
const memberships = useMatrixRTCSessionMemberships(rtcSession); const memberships = useMatrixRTCSessionMemberships(rtcSession);
const leaveSoundContext = useLatest( const leaveSoundContext = useLatest(
useAudioContext({ useAudioContext({
sounds: callEventAudioSounds, sounds: callEventAudioSounds,
latencyHint: "interactive", latencyHint: "interactive",
muted: muteAllAudio,
}), }),
); );
// This should use `useEffectEvent` (only available in experimental versions) // This should use `useEffectEvent` (only available in experimental versions)

View File

@@ -96,7 +96,8 @@ import { ReactionsOverlay } from "./ReactionsOverlay";
import { CallEventAudioRenderer } from "./CallEventAudioRenderer"; import { CallEventAudioRenderer } from "./CallEventAudioRenderer";
import { import {
debugTileLayout as debugTileLayoutSetting, debugTileLayout as debugTileLayoutSetting,
useExperimentalToDeviceTransportSetting, useExperimentalToDeviceTransport as useExperimentalToDeviceTransportSetting,
muteAllAudio as muteAllAudioSetting,
useSetting, useSetting,
} from "../settings/settings"; } from "../settings/settings";
import { ReactionsReader } from "../reactions/ReactionsReader"; import { ReactionsReader } from "../reactions/ReactionsReader";
@@ -220,6 +221,8 @@ export const InCallView: FC<InCallViewProps> = ({
room: livekitRoom, room: livekitRoom,
}); });
const [muteAllAudio] = useSetting(muteAllAudioSetting);
const [toDeviceEncryptionSetting] = useSetting( const [toDeviceEncryptionSetting] = useSetting(
useExperimentalToDeviceTransportSetting, useExperimentalToDeviceTransportSetting,
); );
@@ -693,10 +696,10 @@ export const InCallView: FC<InCallViewProps> = ({
</Text> </Text>
) )
} }
<RoomAudioRenderer /> <RoomAudioRenderer muted={muteAllAudio} />
{renderContent()} {renderContent()}
<CallEventAudioRenderer vm={vm} /> <CallEventAudioRenderer vm={vm} muted={muteAllAudio} />
<ReactionsAudioRenderer vm={vm} /> <ReactionsAudioRenderer vm={vm} muted={muteAllAudio} />
<ReactionsOverlay vm={vm} /> <ReactionsOverlay vm={vm} />
{footer} {footer}
{layout.type !== "pip" && ( {layout.type !== "pip" && (

View File

@@ -24,8 +24,10 @@ const soundMap = Object.fromEntries([
export function ReactionsAudioRenderer({ export function ReactionsAudioRenderer({
vm, vm,
muted,
}: { }: {
vm: CallViewModel; vm: CallViewModel;
muted?: boolean;
}): ReactNode { }): ReactNode {
const [shouldPlay] = useSetting(playReactionsSound); const [shouldPlay] = useSetting(playReactionsSound);
const [soundCache, setSoundCache] = useState<ReturnType< const [soundCache, setSoundCache] = useState<ReturnType<
@@ -34,6 +36,7 @@ export function ReactionsAudioRenderer({
const audioEngineCtx = useAudioContext({ const audioEngineCtx = useAudioContext({
sounds: soundCache, sounds: soundCache,
latencyHint: "interactive", latencyHint: "interactive",
muted,
}); });
const audioEngineRef = useLatest(audioEngineCtx); const audioEngineRef = useLatest(audioEngineCtx);

View File

@@ -15,8 +15,9 @@ import {
debugTileLayout as debugTileLayoutSetting, debugTileLayout as debugTileLayoutSetting,
showNonMemberTiles as showNonMemberTilesSetting, showNonMemberTiles as showNonMemberTilesSetting,
showConnectionStats as showConnectionStatsSetting, showConnectionStats as showConnectionStatsSetting,
useNewMembershipManagerSetting, useNewMembershipManager as useNewMembershipManagerSetting,
useExperimentalToDeviceTransportSetting, useExperimentalToDeviceTransport as useExperimentalToDeviceTransportSetting,
muteAllAudio as muteAllAudioSetting,
} from "./settings"; } from "./settings";
import type { MatrixClient } from "matrix-js-sdk"; import type { MatrixClient } from "matrix-js-sdk";
import type { Room as LivekitRoom } from "livekit-client"; import type { Room as LivekitRoom } from "livekit-client";
@@ -49,6 +50,9 @@ export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRoom }) => {
useExperimentalToDeviceTransport, useExperimentalToDeviceTransport,
setUseExperimentalToDeviceTransport, setUseExperimentalToDeviceTransport,
] = useSetting(useExperimentalToDeviceTransportSetting); ] = useSetting(useExperimentalToDeviceTransportSetting);
const [muteAllAudio, setMuteAllAudio] = useSetting(muteAllAudioSetting);
const urlParams = useUrlParams(); const urlParams = useUrlParams();
const sfuUrl = useMemo((): URL | null => { const sfuUrl = useMemo((): URL | null => {
@@ -175,6 +179,20 @@ export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRoom }) => {
)} )}
/> />
</FieldRow> </FieldRow>
<FieldRow>
<InputField
id="muteAllAudio"
type="checkbox"
label={t("developer_mode.mute_all_audio")}
checked={muteAllAudio}
onChange={useCallback(
(event: ChangeEvent<HTMLInputElement>): void => {
setMuteAllAudio(event.target.checked);
},
[setMuteAllAudio],
)}
/>
</FieldRow>
{livekitRoom ? ( {livekitRoom ? (
<> <>
<p> <p>

View File

@@ -115,14 +115,16 @@ export const soundEffectVolumeSetting = new Setting<number>(
0.5, 0.5,
); );
export const useNewMembershipManagerSetting = new Setting<boolean>( export const useNewMembershipManager = new Setting<boolean>(
"new-membership-manager", "new-membership-manager",
true, true,
); );
export const useExperimentalToDeviceTransportSetting = new Setting<boolean>( export const useExperimentalToDeviceTransport = new Setting<boolean>(
"experimental-to-device-transport", "experimental-to-device-transport",
true, true,
); );
export const muteAllAudio = new Setting<boolean>("mute-all-audio", false);
export const alwaysShowSelf = new Setting<boolean>("always-show-self", true); export const alwaysShowSelf = new Setting<boolean>("always-show-self", true);

View File

@@ -47,6 +47,7 @@ interface Props<S extends string> {
*/ */
sounds: PrefetchedSounds<S> | null; sounds: PrefetchedSounds<S> | null;
latencyHint: AudioContextLatencyCategory; latencyHint: AudioContextLatencyCategory;
muted?: boolean;
} }
interface UseAudioContext<S> { interface UseAudioContext<S> {
@@ -112,7 +113,7 @@ export function useAudioContext<S extends string>(
}, [audioContext, devices]); }, [audioContext, devices]);
// Don't return a function until we're ready. // Don't return a function until we're ready.
if (!audioContext || !audioBuffers) { if (!audioContext || !audioBuffers || props.muted) {
return null; return null;
} }
return { return {