mirror of
https://github.com/suitenumerique/meet.git
synced 2026-10-11 23:52:00 +00:00
1b6509982d
Add a Recording tab to the settings dialog with two selectors, a
content profile and a resolution, building on the per-recording
encoding API.
The goal is to let an instance default to a cheaper profile and
resolution to save egress CPU, while users who really need a smooth
HD recording can still opt in. Most users only need a recording of
acceptable quality, so the default stays cheap and configuring it is
optional.
Profiles are labelled by content ("Talking heads", "Presentations and
text", ...) rather than by fps or bitrate: users know what they are
about to record, not which encoder settings fit it. Each profile shows
a one-line description of its trade-off, so picking one requires no
technical knowledge.
The panel gets a third row, matching the meeting language row of the
transcript panel. It is a shortcut to the settings, without adding
mental load about how to configure a recording. It reads as a short
statement with a trailing "Change" link, like the informational rows
above it, and stays on a single line in every locale: the statement
truncates if a translation gets too long, the link never wraps.
The selected options are intentionally not shown in the panel.
Several users can access it, and each would see their own local
configuration while the running recording may use another user's
encoding, which would be misleading. The issue is milder in the
settings tab, which is frozen while a recording is starting or in
progress.
The selectors are disabled from the moment a start request is sent
until the recording is saved, for both screen recordings and
transcripts. Settings are sent once, when the recording starts, so
changing them afterwards would have no effect and suggest otherwise.
Choices are persisted in localStorage to keep things simple,
consistent with the meeting language, which is already stored
client-side.
The backend now exposes the available resolutions and profiles, and
their defaults, in the frontend configuration, so the UI follows
whatever the operator configures instead of hardcoding values. Stored
choices are checked against it before being sent: a profile removed by
the operator falls back to the instance default instead of being
rejected by the API. No encoding is sent when per-recording encoding
is disabled, as the backend would reject it. Operator-defined values
without a translation are shown by their raw key.
Alternatives considered:
- Storing the preference in room metadata: it would turn a pre-start,
personal choice into shared editable state, requiring a write
endpoint, permission checks and handling of concurrent edits.
- Notifying participants of the chosen encoding: notifications are
one-off, so users who join or reload after the recording started
would miss them, and the information is noise for most participants.
Next steps:
This is a deliberately small first iteration, meant to deliver most
of the value and evolve with feedback and usage. Possible next steps:
- persist the preferences in the backend instead of localStorage
- store the encoding chosen for a recording on the room (or on a
session, if such a model is introduced) and read it from there
rather than from user settings, so every user sees the same value
93 lines
2.3 KiB
TypeScript
93 lines
2.3 KiB
TypeScript
import { fetchApi } from './fetchApi'
|
|
import { keys } from './queryKeys'
|
|
import { useQuery } from '@tanstack/react-query'
|
|
import { RecordingMode } from '@/features/recording'
|
|
import type { ApiAccessLevel } from '@/features/rooms/api/ApiRoom'
|
|
import type { Track, VideoCodec } from 'livekit-client'
|
|
type Source = Track.Source
|
|
|
|
export interface ApiConfig {
|
|
analytics?: {
|
|
id: string
|
|
host: string
|
|
flags_api_host?: string
|
|
}
|
|
support?: {
|
|
id: string
|
|
help_article_transcript: string
|
|
help_article_recording: string
|
|
help_article_more_tools: string
|
|
}
|
|
feedback: {
|
|
url: string
|
|
}
|
|
documentation_url?: string
|
|
technical_documentation_url?: string
|
|
external_home_url?: string
|
|
silence_livekit_debug_logs?: boolean
|
|
is_silent_login_enabled?: boolean
|
|
custom_css_url?: string
|
|
use_french_gov_footer?: boolean
|
|
use_proconnect_button?: boolean
|
|
allow_unregistered_rooms?: boolean
|
|
idle_disconnect_warning_delay?: number
|
|
recording?: {
|
|
is_enabled?: boolean
|
|
available_modes?: RecordingMode[]
|
|
expiration_days?: number
|
|
max_duration?: number
|
|
encoding?: {
|
|
is_custom_enabled: boolean
|
|
available_resolutions: string[]
|
|
available_profiles: string[]
|
|
default_resolution?: string | null
|
|
default_profile?: string | null
|
|
}
|
|
}
|
|
background_image: {
|
|
upload_is_enabled: boolean
|
|
max_size: number
|
|
max_count_by_user: number
|
|
allowed_extensions: string[]
|
|
allowed_mimetypes: string[]
|
|
}
|
|
subtitle: {
|
|
enabled: boolean
|
|
}
|
|
diagnostics: {
|
|
connection_test_enabled?: boolean
|
|
}
|
|
telephony: {
|
|
enabled: boolean
|
|
international_phone_number?: string
|
|
default_country?: string
|
|
}
|
|
resource?: {
|
|
default_access_level?: ApiAccessLevel
|
|
}
|
|
manifest_link?: string
|
|
livekit: {
|
|
url: string
|
|
force_wss_protocol: boolean
|
|
enable_firefox_proxy_workaround: boolean
|
|
default_sources: Source[]
|
|
default_video_codec: VideoCodec
|
|
}
|
|
transcription_destination?: string
|
|
max_participants_for_sound: number
|
|
auto_mute_on_join_threshold: number
|
|
authenticated_users_can_edit_display_name: boolean
|
|
}
|
|
|
|
const fetchConfig = (): Promise<ApiConfig> => {
|
|
return fetchApi<ApiConfig>(`config/`)
|
|
}
|
|
|
|
export const useConfig = () => {
|
|
return useQuery({
|
|
queryKey: [keys.config],
|
|
queryFn: fetchConfig,
|
|
staleTime: Infinity,
|
|
})
|
|
}
|