mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
feat(voice): add audio bitrate guild features and 96 kbps cap (#2703)
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {describe, expect, it} from 'vitest';
|
||||
import {
|
||||
clampVoiceChannelBitrate,
|
||||
GuildFeatures,
|
||||
getMaxVoiceChannelBitrate,
|
||||
resolveVoiceChannelBitrate,
|
||||
} from './GuildConstants';
|
||||
|
||||
describe('getMaxVoiceChannelBitrate', () => {
|
||||
it('caps a guild holding no audio bitrate feature at 96 kbps', () => {
|
||||
expect(getMaxVoiceChannelBitrate([])).toBe(96000);
|
||||
expect(getMaxVoiceChannelBitrate([GuildFeatures.VIP_VOICE])).toBe(96000);
|
||||
});
|
||||
it('caps a call outside a guild at 96 kbps', () => {
|
||||
expect(getMaxVoiceChannelBitrate(null)).toBe(96000);
|
||||
expect(getMaxVoiceChannelBitrate(undefined)).toBe(96000);
|
||||
});
|
||||
it('raises the cap to the feature the guild holds', () => {
|
||||
expect(getMaxVoiceChannelBitrate([GuildFeatures.AUDIO_BITRATE_128_KBPS])).toBe(128000);
|
||||
expect(getMaxVoiceChannelBitrate([GuildFeatures.AUDIO_BITRATE_256_KBPS])).toBe(256000);
|
||||
expect(getMaxVoiceChannelBitrate([GuildFeatures.AUDIO_BITRATE_384_KBPS])).toBe(384000);
|
||||
});
|
||||
it('takes the highest feature when a guild holds several', () => {
|
||||
expect(
|
||||
getMaxVoiceChannelBitrate([GuildFeatures.AUDIO_BITRATE_384_KBPS, GuildFeatures.AUDIO_BITRATE_128_KBPS]),
|
||||
).toBe(384000);
|
||||
expect(
|
||||
getMaxVoiceChannelBitrate(new Set([GuildFeatures.AUDIO_BITRATE_128_KBPS, GuildFeatures.AUDIO_BITRATE_256_KBPS])),
|
||||
).toBe(256000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('clampVoiceChannelBitrate', () => {
|
||||
it('clamps above the cap the guild holds', () => {
|
||||
expect(clampVoiceChannelBitrate(384000, [])).toBe(96000);
|
||||
expect(clampVoiceChannelBitrate(384000, [GuildFeatures.AUDIO_BITRATE_128_KBPS])).toBe(128000);
|
||||
expect(clampVoiceChannelBitrate(384000, [GuildFeatures.AUDIO_BITRATE_384_KBPS])).toBe(384000);
|
||||
});
|
||||
it('leaves a value under the cap alone', () => {
|
||||
expect(clampVoiceChannelBitrate(64000, [])).toBe(64000);
|
||||
expect(clampVoiceChannelBitrate(8000, [])).toBe(8000);
|
||||
});
|
||||
it('raises a value under the minimum', () => {
|
||||
expect(clampVoiceChannelBitrate(1000, [])).toBe(8000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveVoiceChannelBitrate', () => {
|
||||
it('falls back to 64 kbps when the channel stores no bitrate', () => {
|
||||
expect(resolveVoiceChannelBitrate(null, null)).toBe(64000);
|
||||
expect(resolveVoiceChannelBitrate(undefined, [])).toBe(64000);
|
||||
expect(resolveVoiceChannelBitrate(0, [])).toBe(64000);
|
||||
expect(resolveVoiceChannelBitrate(Number.NaN, [])).toBe(64000);
|
||||
});
|
||||
it('clamps a stored bitrate to what the guild currently holds', () => {
|
||||
expect(resolveVoiceChannelBitrate(384000, [])).toBe(96000);
|
||||
expect(resolveVoiceChannelBitrate(384000, [GuildFeatures.AUDIO_BITRATE_256_KBPS])).toBe(256000);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,13 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {
|
||||
VOICE_CHANNEL_BITRATE_DEFAULT,
|
||||
VOICE_CHANNEL_BITRATE_MAX_128_KBPS,
|
||||
VOICE_CHANNEL_BITRATE_MAX_256_KBPS,
|
||||
VOICE_CHANNEL_BITRATE_MAX_384_KBPS,
|
||||
VOICE_CHANNEL_BITRATE_MAX_STANDARD,
|
||||
VOICE_CHANNEL_BITRATE_MIN,
|
||||
} from '@fluxer/constants/src/LimitConstants';
|
||||
import type {ValueOf} from '@fluxer/constants/src/ValueOf';
|
||||
|
||||
export const GuildVerificationLevel = {
|
||||
@@ -97,6 +105,9 @@ export const CONTENT_WARNING_TEXT_MAX_LENGTH = 200;
|
||||
export const GuildFeatures = {
|
||||
ANIMATED_ICON: 'ANIMATED_ICON',
|
||||
ANIMATED_BANNER: 'ANIMATED_BANNER',
|
||||
AUDIO_BITRATE_128_KBPS: 'AUDIO_BITRATE_128_KBPS',
|
||||
AUDIO_BITRATE_256_KBPS: 'AUDIO_BITRATE_256_KBPS',
|
||||
AUDIO_BITRATE_384_KBPS: 'AUDIO_BITRATE_384_KBPS',
|
||||
BANNER: 'BANNER',
|
||||
CLONE_EMOJI_DISABLED: 'CLONE_EMOJI_DISABLED',
|
||||
CLONE_STICKER_DISABLED: 'CLONE_STICKER_DISABLED',
|
||||
@@ -127,6 +138,37 @@ export const GuildFeatures = {
|
||||
|
||||
export type GuildFeature = ValueOf<typeof GuildFeatures>;
|
||||
|
||||
export function getMaxVoiceChannelBitrate(features: Iterable<string> | null | undefined): number {
|
||||
if (features == null) {
|
||||
return VOICE_CHANNEL_BITRATE_MAX_STANDARD;
|
||||
}
|
||||
let maximum = VOICE_CHANNEL_BITRATE_MAX_STANDARD;
|
||||
for (const feature of features) {
|
||||
if (feature === GuildFeatures.AUDIO_BITRATE_384_KBPS) {
|
||||
maximum = Math.max(maximum, VOICE_CHANNEL_BITRATE_MAX_384_KBPS);
|
||||
} else if (feature === GuildFeatures.AUDIO_BITRATE_256_KBPS) {
|
||||
maximum = Math.max(maximum, VOICE_CHANNEL_BITRATE_MAX_256_KBPS);
|
||||
} else if (feature === GuildFeatures.AUDIO_BITRATE_128_KBPS) {
|
||||
maximum = Math.max(maximum, VOICE_CHANNEL_BITRATE_MAX_128_KBPS);
|
||||
}
|
||||
}
|
||||
return maximum;
|
||||
}
|
||||
|
||||
export function clampVoiceChannelBitrate(bitrate: number, features: Iterable<string> | null | undefined): number {
|
||||
return Math.min(Math.max(bitrate, VOICE_CHANNEL_BITRATE_MIN), getMaxVoiceChannelBitrate(features));
|
||||
}
|
||||
|
||||
export function resolveVoiceChannelBitrate(
|
||||
bitrate: number | null | undefined,
|
||||
features: Iterable<string> | null | undefined,
|
||||
): number {
|
||||
if (typeof bitrate !== 'number' || !Number.isFinite(bitrate) || bitrate <= 0) {
|
||||
return VOICE_CHANNEL_BITRATE_DEFAULT;
|
||||
}
|
||||
return clampVoiceChannelBitrate(Math.round(bitrate), features);
|
||||
}
|
||||
|
||||
export const JoinSourceTypes = {
|
||||
CREATOR: 0,
|
||||
INSTANT_INVITE: 1,
|
||||
|
||||
@@ -4,7 +4,12 @@ export const MAX_GUILDS_PREMIUM = 200;
|
||||
export const MAX_GUILD_CHANNELS = 500;
|
||||
export const MAX_CHANNELS_PER_CATEGORY = 50;
|
||||
export const VOICE_CHANNEL_BITRATE_MIN = 8000;
|
||||
export const VOICE_CHANNEL_BITRATE_MAX = 320000;
|
||||
export const VOICE_CHANNEL_BITRATE_DEFAULT = 64000;
|
||||
export const VOICE_CHANNEL_BITRATE_MAX_STANDARD = 96000;
|
||||
export const VOICE_CHANNEL_BITRATE_MAX_128_KBPS = 128000;
|
||||
export const VOICE_CHANNEL_BITRATE_MAX_256_KBPS = 256000;
|
||||
export const VOICE_CHANNEL_BITRATE_MAX_384_KBPS = 384000;
|
||||
export const VOICE_CHANNEL_BITRATE_MAX = VOICE_CHANNEL_BITRATE_MAX_384_KBPS;
|
||||
export const VOICE_CHANNEL_USER_LIMIT_MIN = 0;
|
||||
export const VOICE_CHANNEL_USER_LIMIT_MAX = 99;
|
||||
export const VOICE_CHANNEL_CAMERA_USER_LIMIT = 25;
|
||||
|
||||
Reference in New Issue
Block a user