mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
fix(voice): stop direct input capturing microphones in stereo (#2929)
This commit is contained in:
1 parent
c2c0fdb445
commit
88038a1d5b
4 files changed
+42
-24
No files matched your search
@@ -98,7 +98,7 @@ import EntranceSoundLibrary from '@app/features/voice/state/EntranceSoundLibrary
|
||||
import LocalVoiceState from '@app/features/voice/state/LocalVoiceState';
|
||||
import ParticipantVolume from '@app/features/voice/state/ParticipantVolume';
|
||||
import VoiceSettings from '@app/features/voice/state/VoiceSettings';
|
||||
import {buildMicrophonePublishOptions} from '@app/features/voice/utils/AudioPublishOptions';
|
||||
import {buildMicrophonePublishOptions, sendsStereoMicrophone} from '@app/features/voice/utils/AudioPublishOptions';
|
||||
import {
|
||||
buildCameraPublishOptions,
|
||||
findVideoPublishCodecPolicyViolation,
|
||||
@@ -605,24 +605,31 @@ export class VoiceEngineV2AppMediaExecutionAdapter extends Store {
|
||||
return applyNoiseSuppressionOverride(profile, readEffectiveNoiseSuppression(MICROPHONE_CAPTURE_SAMPLE_RATE));
|
||||
}
|
||||
|
||||
private getMicrophoneCaptureOptions(options: VoiceEngineV2MicrophoneOptions = {}): AudioCaptureOptions {
|
||||
private resolveMicrophoneChannelBitrate(channelId: string | null): number {
|
||||
const channel = channelId ? Channels.getChannel(channelId) : null;
|
||||
const guild = channel?.guildId ? Guilds.getGuild(channel.guildId) : null;
|
||||
return resolveVoiceChannelBitrate(channel?.bitrate, guild?.features);
|
||||
}
|
||||
|
||||
private getMicrophoneCaptureOptions(
|
||||
options: VoiceEngineV2MicrophoneOptions = {},
|
||||
channelId: string | null = this.getActiveChannelId(),
|
||||
): AudioCaptureOptions {
|
||||
const profile = this.resolveActiveMicrophoneProfile();
|
||||
const stereo = sendsStereoMicrophone(this.resolveMicrophoneChannelBitrate(channelId), profile.stereoCapture);
|
||||
return {
|
||||
deviceId: options.deviceId ?? this.resolveInputDeviceId(),
|
||||
echoCancellation: options.echoCancellation ?? profile.echoCancellation,
|
||||
noiseSuppression: options.noiseSuppression ?? profile.browserNoiseSuppression,
|
||||
autoGainControl: options.autoGainControl ?? profile.autoGainControl,
|
||||
voiceIsolation: false,
|
||||
...(profile.stereoCapture ? {channelCount: {ideal: 2}} : {}),
|
||||
...(stereo ? {channelCount: {ideal: 2}} : {}),
|
||||
};
|
||||
}
|
||||
|
||||
private getMicrophonePublishOptions(channelId: string | null): TrackPublishOptions | undefined {
|
||||
const channel = channelId ? Channels.getChannel(channelId) : null;
|
||||
const guild = channel?.guildId ? Guilds.getGuild(channel.guildId) : null;
|
||||
const channelBitrate = resolveVoiceChannelBitrate(channel?.bitrate, guild?.features);
|
||||
const profile = this.resolveActiveMicrophoneProfile();
|
||||
return buildMicrophonePublishOptions(channelBitrate, profile.stereoCapture);
|
||||
return buildMicrophonePublishOptions(this.resolveMicrophoneChannelBitrate(channelId), profile.stereoCapture);
|
||||
}
|
||||
|
||||
async refreshMicrophonePublishSettings(room: Room | null, channelId: string | null): Promise<void> {
|
||||
@@ -902,7 +909,7 @@ export class VoiceEngineV2AppMediaExecutionAdapter extends Store {
|
||||
assertObjectLike<MicrophoneEnableState>(state, 'publishMicrophoneAudioTrack.state');
|
||||
await ctx.room.localParticipant.setMicrophoneEnabled(
|
||||
true,
|
||||
this.getMicrophoneCaptureOptions(ctx.options),
|
||||
this.getMicrophoneCaptureOptions(ctx.options, ctx.channelId),
|
||||
this.getMicrophonePublishOptions(ctx.channelId),
|
||||
);
|
||||
state.microphoneWasPublished = true;
|
||||
|
||||
@@ -16,6 +16,11 @@ export function normaliseAudioBitrateBps(value: number | null | undefined): numb
|
||||
return Math.min(Math.max(bitsPerSecond, VOICE_CHANNEL_MIN_AUDIO_BITRATE_BPS), OPUS_MAX_AUDIO_BITRATE_BPS);
|
||||
}
|
||||
|
||||
export function sendsStereoMicrophone(channelBitrate: number | null | undefined, stereoCapture: boolean): boolean {
|
||||
const maxBitrate = normaliseAudioBitrateBps(channelBitrate);
|
||||
return stereoCapture && maxBitrate !== undefined && maxBitrate >= STEREO_VOICE_MIN_AUDIO_BITRATE_BPS;
|
||||
}
|
||||
|
||||
export function buildMicrophonePublishOptions(
|
||||
channelBitrate: number | null | undefined,
|
||||
stereoCapture = false,
|
||||
@@ -29,7 +34,7 @@ export function buildMicrophonePublishOptions(
|
||||
},
|
||||
dtx: false,
|
||||
red: true,
|
||||
forceStereo: stereoCapture && maxBitrate >= STEREO_VOICE_MIN_AUDIO_BITRATE_BPS ? undefined : false,
|
||||
forceStereo: sendsStereoMicrophone(maxBitrate, stereoCapture) ? undefined : false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -84,9 +84,8 @@ export function supportsStereoCapture(profile: ResolvedVoiceProcessing): boolean
|
||||
|
||||
export function resolveStereoCapture(effective: EffectiveNoiseSuppression, profile: ResolvedVoiceProcessing): boolean {
|
||||
if (!supportsStereoCapture(profile)) return false;
|
||||
if (profile.mode === 'studio') return true;
|
||||
if (profile.mode === 'custom') return effective.stereoPreferred;
|
||||
return false;
|
||||
if (profile.mode === 'voice') return false;
|
||||
return effective.stereoPreferred;
|
||||
}
|
||||
|
||||
export function applyNoiseSuppressionOverride(
|
||||
|
||||
Reference in new issue
Block a user