mirror of
https://github.com/suitenumerique/meet.git
synced 2026-09-02 13:48:26 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d80d31897c | |||
| 63a7751072 | |||
| 1ac1778521 | |||
| fcc58065d2 |
@@ -8,6 +8,14 @@ and this project adheres to
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- ✨(frontend) add 1080p sending resolution option #1660
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- 🐛(frontend) keep the sending resolution picked while the camera is off #1667
|
||||||
|
|
||||||
## [1.30.0] - 2026-09-01
|
## [1.30.0] - 2026-09-01
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ RUN apk update && apk upgrade \
|
|||||||
musl \
|
musl \
|
||||||
musl-utils \
|
musl-utils \
|
||||||
zlib>=1.3.2-r0 \
|
zlib>=1.3.2-r0 \
|
||||||
|
libexpat>=2.8.4-r0 \
|
||||||
&& apk del curl
|
&& apk del curl
|
||||||
|
|
||||||
USER nginx
|
USER nginx
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ RUN apk update && apk upgrade \
|
|||||||
musl \
|
musl \
|
||||||
musl-utils \
|
musl-utils \
|
||||||
zlib>=1.3.2-r0 \
|
zlib>=1.3.2-r0 \
|
||||||
|
libexpat>=2.8.4-r0 \
|
||||||
&& apk del curl
|
&& apk del curl
|
||||||
|
|
||||||
USER nginx
|
USER nginx
|
||||||
|
|||||||
+6
-2
@@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import { useTrackToggle, UseTrackToggleProps } from '@livekit/components-react'
|
import { useTrackToggle, UseTrackToggleProps } from '@livekit/components-react'
|
||||||
import { Button, Popover } from '@/primitives'
|
import { Button, Popover } from '@/primitives'
|
||||||
import { RiArrowUpSLine, RiImageCircleAiFill } from '@remixicon/react'
|
import { RiArrowUpSLine, RiImageCircleAiFill } from '@remixicon/react'
|
||||||
import { Track, type VideoCaptureOptions } from 'livekit-client'
|
import { Track, type VideoCaptureOptions, VideoPresets } from 'livekit-client'
|
||||||
|
|
||||||
import { ToggleDevice } from './ToggleDevice'
|
import { ToggleDevice } from './ToggleDevice'
|
||||||
import { css } from '@/styled-system/css'
|
import { css } from '@/styled-system/css'
|
||||||
@@ -57,7 +57,8 @@ export const VideoDeviceControl = ({
|
|||||||
}: VideoDeviceControlProps) => {
|
}: VideoDeviceControlProps) => {
|
||||||
const { t } = useTranslation('rooms', { keyPrefix: 'selectDevice' })
|
const { t } = useTranslation('rooms', { keyPrefix: 'selectDevice' })
|
||||||
|
|
||||||
const { videoDeviceId, processorConfig } = useSnapshot(userChoicesStore)
|
const { videoDeviceId, processorConfig, videoPublishResolution } =
|
||||||
|
useSnapshot(userChoicesStore)
|
||||||
|
|
||||||
const onChange = React.useCallback(
|
const onChange = React.useCallback(
|
||||||
(enabled: boolean, isUserInitiated: boolean) =>
|
(enabled: boolean, isUserInitiated: boolean) =>
|
||||||
@@ -97,6 +98,9 @@ export const VideoDeviceControl = ({
|
|||||||
|
|
||||||
await toggle(!trackProps.enabled, {
|
await toggle(!trackProps.enabled, {
|
||||||
processor: processor,
|
processor: processor,
|
||||||
|
...(videoPublishResolution && {
|
||||||
|
resolution: VideoPresets[videoPublishResolution].resolution,
|
||||||
|
}),
|
||||||
} as VideoCaptureOptions)
|
} as VideoCaptureOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
saveVideoPublishResolution,
|
saveVideoPublishResolution,
|
||||||
saveVideoSubscribeQuality,
|
saveVideoSubscribeQuality,
|
||||||
userChoicesStore,
|
userChoicesStore,
|
||||||
|
VIDEO_RESOLUTIONS,
|
||||||
VideoResolution,
|
VideoResolution,
|
||||||
} from '@/stores/userChoices'
|
} from '@/stores/userChoices'
|
||||||
import { RowWrapper } from './layout/RowWrapper'
|
import { RowWrapper } from './layout/RowWrapper'
|
||||||
@@ -32,7 +33,8 @@ const EMPTY_PROPS = {}
|
|||||||
|
|
||||||
export const VideoTab = ({ id }: VideoTabProps) => {
|
export const VideoTab = ({ id }: VideoTabProps) => {
|
||||||
const { t } = useTranslation('settings', { keyPrefix: 'video' })
|
const { t } = useTranslation('settings', { keyPrefix: 'video' })
|
||||||
const { localParticipant, remoteParticipants } = useRoomContext()
|
const room = useRoomContext()
|
||||||
|
const { localParticipant, remoteParticipants } = room
|
||||||
|
|
||||||
const {
|
const {
|
||||||
videoDeviceId,
|
videoDeviceId,
|
||||||
@@ -69,20 +71,21 @@ export const VideoTab = ({ id }: VideoTabProps) => {
|
|||||||
isDisabled: true,
|
isDisabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleVideoResolutionChange = async (key: 'h720' | 'h360' | 'h180') => {
|
const handleVideoResolutionChange = async (key: VideoResolution) => {
|
||||||
const videoPublication = localParticipant.getTrackPublication(
|
saveVideoPublishResolution(key)
|
||||||
|
const videoTrack = localParticipant.getTrackPublication(
|
||||||
Track.Source.Camera
|
Track.Source.Camera
|
||||||
)
|
)?.track
|
||||||
const videoTrack = videoPublication?.track
|
if (!videoTrack) {
|
||||||
if (videoTrack) {
|
return
|
||||||
saveVideoPublishResolution(key)
|
|
||||||
await videoTrack.restartTrack({
|
|
||||||
resolution: VideoPresets[key].resolution,
|
|
||||||
deviceId: { exact: videoDeviceId },
|
|
||||||
processor:
|
|
||||||
BackgroundProcessorFactory.fromProcessorConfig(processorConfig),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await videoTrack.restartTrack({
|
||||||
|
resolution: VideoPresets[key].resolution,
|
||||||
|
deviceId: { exact: videoDeviceId },
|
||||||
|
processor:
|
||||||
|
BackgroundProcessorFactory.fromProcessorConfig(processorConfig),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,20 +125,13 @@ export const VideoTab = ({ id }: VideoTabProps) => {
|
|||||||
}, [videoDeviceId, videoElement])
|
}, [videoDeviceId, videoElement])
|
||||||
|
|
||||||
const resolutionItems = useMemo(() => {
|
const resolutionItems = useMemo(() => {
|
||||||
return [
|
const labels: Record<VideoResolution, string> = {
|
||||||
{
|
h1080: `${t('resolution.publish.items.veryHigh')} (1080p)`,
|
||||||
value: 'h720',
|
h720: `${t('resolution.publish.items.high')} (720p)`,
|
||||||
label: `${t('resolution.publish.items.high')} (720p)`,
|
h360: `${t('resolution.publish.items.medium')} (360p)`,
|
||||||
},
|
h180: `${t('resolution.publish.items.low')} (180p)`,
|
||||||
{
|
}
|
||||||
value: 'h360',
|
return VIDEO_RESOLUTIONS.map((value) => ({ value, label: labels[value] }))
|
||||||
label: `${t('resolution.publish.items.medium')} (360p)`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'h180',
|
|
||||||
label: `${t('resolution.publish.items.low')} (180p)`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}, [t])
|
}, [t])
|
||||||
|
|
||||||
const videoQualityItems = useMemo(() => {
|
const videoQualityItems = useMemo(() => {
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
"publish": {
|
"publish": {
|
||||||
"label": "Wähle die maximale Auflösung beim Senden",
|
"label": "Wähle die maximale Auflösung beim Senden",
|
||||||
"items": {
|
"items": {
|
||||||
|
"veryHigh": "Sehr hohe Auflösung",
|
||||||
"high": "Hohe Auflösung",
|
"high": "Hohe Auflösung",
|
||||||
"medium": "Mittlere Auflösung",
|
"medium": "Mittlere Auflösung",
|
||||||
"low": "Niedrige Auflösung"
|
"low": "Niedrige Auflösung"
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
"publish": {
|
"publish": {
|
||||||
"label": "Select your sending resolution (max.)",
|
"label": "Select your sending resolution (max.)",
|
||||||
"items": {
|
"items": {
|
||||||
|
"veryHigh": "Very high definition",
|
||||||
"high": "High definition",
|
"high": "High definition",
|
||||||
"medium": "Standard definition",
|
"medium": "Standard definition",
|
||||||
"low": "Low definition"
|
"low": "Low definition"
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
"publish": {
|
"publish": {
|
||||||
"label": "Selecciona tu resolución de envío (máx.)",
|
"label": "Selecciona tu resolución de envío (máx.)",
|
||||||
"items": {
|
"items": {
|
||||||
|
"veryHigh": "Muy alta definición",
|
||||||
"high": "Alta definición",
|
"high": "Alta definición",
|
||||||
"medium": "Definición estándar",
|
"medium": "Definición estándar",
|
||||||
"low": "Baja definición"
|
"low": "Baja definición"
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
"publish": {
|
"publish": {
|
||||||
"label": "Sélectionner votre résolution d'envoi (max.)",
|
"label": "Sélectionner votre résolution d'envoi (max.)",
|
||||||
"items": {
|
"items": {
|
||||||
|
"veryHigh": "Très haute définition",
|
||||||
"high": "Haute définition",
|
"high": "Haute définition",
|
||||||
"medium": "Définition standard",
|
"medium": "Définition standard",
|
||||||
"low": "Basse définition"
|
"low": "Basse définition"
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
"publish": {
|
"publish": {
|
||||||
"label": "Selecteer uw verzendresolutie (max.)",
|
"label": "Selecteer uw verzendresolutie (max.)",
|
||||||
"items": {
|
"items": {
|
||||||
|
"veryHigh": "Zeer hoge definitie",
|
||||||
"high": "Hoge definitie",
|
"high": "Hoge definitie",
|
||||||
"medium": "Standaarddefinitie",
|
"medium": "Standaarddefinitie",
|
||||||
"low": "Lage definitie"
|
"low": "Lage definitie"
|
||||||
|
|||||||
@@ -10,7 +10,12 @@ import {
|
|||||||
} from '@livekit/components-core'
|
} from '@livekit/components-core'
|
||||||
import { VideoQuality } from 'livekit-client'
|
import { VideoQuality } from 'livekit-client'
|
||||||
|
|
||||||
export type VideoResolution = 'h720' | 'h360' | 'h180'
|
export const VIDEO_RESOLUTIONS = ['h1080', 'h720', 'h360', 'h180'] as const
|
||||||
|
|
||||||
|
export type VideoResolution = (typeof VIDEO_RESOLUTIONS)[number]
|
||||||
|
|
||||||
|
const isVideoResolution = (value: unknown): value is VideoResolution =>
|
||||||
|
VIDEO_RESOLUTIONS.includes(value as VideoResolution)
|
||||||
|
|
||||||
export type LocalUserChoices = Omit<LocalUserChoicesLK, 'username'> & {
|
export type LocalUserChoices = Omit<LocalUserChoicesLK, 'username'> & {
|
||||||
processorConfig?: ProcessorConfig
|
processorConfig?: ProcessorConfig
|
||||||
@@ -21,13 +26,17 @@ export type LocalUserChoices = Omit<LocalUserChoicesLK, 'username'> & {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getUserChoicesState(): LocalUserChoices {
|
function getUserChoicesState(): LocalUserChoices {
|
||||||
return {
|
const stored: LocalUserChoices = {
|
||||||
noiseReductionEnabled: false,
|
noiseReductionEnabled: false,
|
||||||
audioOutputDeviceId: 'default', // Use 'default' to match LiveKit's standard device selection behavior
|
audioOutputDeviceId: 'default', // Use 'default' to match LiveKit's standard device selection behavior
|
||||||
videoPublishResolution: 'h720',
|
videoPublishResolution: 'h720',
|
||||||
videoSubscribeQuality: VideoQuality.HIGH,
|
videoSubscribeQuality: VideoQuality.HIGH,
|
||||||
...loadUserChoices(),
|
...loadUserChoices(),
|
||||||
}
|
}
|
||||||
|
if (!isVideoResolution(stored.videoPublishResolution)) {
|
||||||
|
stored.videoPublishResolution = 'h720'
|
||||||
|
}
|
||||||
|
return stored
|
||||||
}
|
}
|
||||||
|
|
||||||
export const userChoicesStore = proxy<LocalUserChoices>(getUserChoicesState())
|
export const userChoicesStore = proxy<LocalUserChoices>(getUserChoicesState())
|
||||||
|
|||||||
Reference in New Issue
Block a user