import { useEffect, useRef, useState } from 'react' import { useLocalParticipant } from '@livekit/components-react' import { LocalVideoTrack } from 'livekit-client' import { Text, P, ToggleButton, Div, H } from '@/primitives' import { useTranslation } from 'react-i18next' import { HStack, styled, VStack } from '@/styled-system/jsx' import { BackgroundBlur, BackgroundOptions, ProcessorWrapper, BackgroundTransformer, } from '@livekit/track-processors' const Information = styled('div', { base: { backgroundColor: 'orange.50', borderRadius: '4px', padding: '0.75rem 0.75rem', marginTop: '0.8rem', alignItems: 'start', }, }) enum BlurRadius { NONE = 0, LIGHT = 5, NORMAL = 10, } export const Effects = () => { const { t } = useTranslation('rooms', { keyPrefix: 'effects' }) const { isCameraEnabled, cameraTrack, localParticipant } = useLocalParticipant() const videoRef = useRef(null) const [processorPending, setProcessorPending] = useState(false) const localCameraTrack = cameraTrack?.track as LocalVideoTrack const getProcessor = () => { return localCameraTrack?.getProcessor() as ProcessorWrapper } const getBlurRadius = (): BlurRadius => { const processor = getProcessor() return ( (processor?.transformer as BackgroundTransformer)?.options?.blurRadius || BlurRadius.NONE ) } const toggleBlur = async (blurRadius: number) => { if (!isCameraEnabled) await localParticipant.setCameraEnabled(true) if (!localCameraTrack) return setProcessorPending(true) const processor = getProcessor() const currentBlurRadius = getBlurRadius() try { if (blurRadius == currentBlurRadius && processor) { await localCameraTrack.stopProcessor() } else if (!processor) { await localCameraTrack.setProcessor(BackgroundBlur(blurRadius)) } else { await processor?.updateTransformerOptions({ blurRadius }) } } catch (error) { console.error('Error applying blur:', error) } finally { setProcessorPending(false) } } useEffect(() => { const videoElement = videoRef.current if (!videoElement) return const attachVideoTrack = async () => localCameraTrack?.attach(videoElement) attachVideoTrack() return () => { if (!videoElement) return localCameraTrack.detach(videoElement) } }, [localCameraTrack, isCameraEnabled]) const isSelected = (blurRadius: BlurRadius) => { return isCameraEnabled && getBlurRadius() == blurRadius } const tooltipLabel = (blurRadius: BlurRadius) => { return t(`blur.${isSelected(blurRadius) ? 'clear' : 'apply'}`) } return ( {localCameraTrack && isCameraEnabled ? ( ) }