Skip to content

Commit 9d2abd9

Browse files
authored
feat(video): add video enhancement settings for saturation, brightness, and contrast (#557)
1 parent 52dd675 commit 9d2abd9

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed

ui/src/components/WebRTCVideo.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ export default function WebRTCVideo() {
4646
clientHeight: videoClientHeight,
4747
} = useVideoStore();
4848

49+
// Video enhancement settings
50+
const videoSaturation = useSettingsStore(state => state.videoSaturation);
51+
const videoBrightness = useSettingsStore(state => state.videoBrightness);
52+
const videoContrast = useSettingsStore(state => state.videoContrast);
53+
4954
// HID related states
5055
const keyboardLedStateSyncAvailable = useHidStore(state => state.keyboardLedStateSyncAvailable);
5156
const keyboardLedSync = useSettingsStore(state => state.keyboardLedSync);
@@ -674,6 +679,9 @@ export default function WebRTCVideo() {
674679
playsInline
675680
disablePictureInPicture
676681
controlsList="nofullscreen"
682+
style={{
683+
filter: `saturate(${videoSaturation}) brightness(${videoBrightness}) contrast(${videoContrast})`,
684+
}}
677685
className={cx(
678686
"max-h-full min-h-[384px] max-w-full min-w-[512px] bg-black/50 object-contain transition-all duration-1000",
679687
{

ui/src/hooks/stores.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,14 @@ interface SettingsState {
319319

320320
showPressedKeys: boolean;
321321
setShowPressedKeys: (show: boolean) => void;
322+
323+
// Video enhancement settings
324+
videoSaturation: number;
325+
setVideoSaturation: (value: number) => void;
326+
videoBrightness: number;
327+
setVideoBrightness: (value: number) => void;
328+
videoContrast: number;
329+
setVideoContrast: (value: number) => void;
322330
}
323331

324332
export const useSettingsStore = create(
@@ -362,6 +370,14 @@ export const useSettingsStore = create(
362370

363371
showPressedKeys: true,
364372
setShowPressedKeys: show => set({ showPressedKeys: show }),
373+
374+
// Video enhancement settings with default values (1.0 = normal)
375+
videoSaturation: 1.0,
376+
setVideoSaturation: value => set({ videoSaturation: value }),
377+
videoBrightness: 1.0,
378+
setVideoBrightness: value => set({ videoBrightness: value }),
379+
videoContrast: 1.0,
380+
setVideoContrast: value => set({ videoContrast: value }),
365381
}),
366382
{
367383
name: "settings",

ui/src/routes/devices.$id.settings.video.tsx

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Button } from "@/components/Button";
44
import { TextAreaWithLabel } from "@/components/TextArea";
55
import { useJsonRpc } from "@/hooks/useJsonRpc";
66
import { SettingsPageHeader } from "@components/SettingsPageheader";
7+
import { useSettingsStore } from "@/hooks/stores";
78

89
import notifications from "../notifications";
910
import { SelectMenuBasic } from "../components/SelectMenuBasic";
@@ -45,6 +46,14 @@ export default function SettingsVideoRoute() {
4546
const [customEdidValue, setCustomEdidValue] = useState<string | null>(null);
4647
const [edid, setEdid] = useState<string | null>(null);
4748

49+
// Video enhancement settings from store
50+
const videoSaturation = useSettingsStore(state => state.videoSaturation);
51+
const setVideoSaturation = useSettingsStore(state => state.setVideoSaturation);
52+
const videoBrightness = useSettingsStore(state => state.videoBrightness);
53+
const setVideoBrightness = useSettingsStore(state => state.setVideoBrightness);
54+
const videoContrast = useSettingsStore(state => state.videoContrast);
55+
const setVideoContrast = useSettingsStore(state => state.setVideoContrast);
56+
4857
useEffect(() => {
4958
send("getStreamQualityFactor", {}, resp => {
5059
if ("error" in resp) return;
@@ -126,6 +135,73 @@ export default function SettingsVideoRoute() {
126135
onChange={e => handleStreamQualityChange(e.target.value)}
127136
/>
128137
</SettingsItem>
138+
139+
{/* Video Enhancement Settings */}
140+
<SettingsItem
141+
title="Video Enhancement"
142+
description="Adjust color settings to make the video output more vibrant and colorful"
143+
/>
144+
145+
<div className="space-y-4 pl-4">
146+
<SettingsItem
147+
title="Saturation"
148+
description={`Color saturation (${videoSaturation.toFixed(1)}x)`}
149+
>
150+
<input
151+
type="range"
152+
min="0.5"
153+
max="2.0"
154+
step="0.1"
155+
value={videoSaturation}
156+
onChange={e => setVideoSaturation(parseFloat(e.target.value))}
157+
className="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
158+
/>
159+
</SettingsItem>
160+
161+
<SettingsItem
162+
title="Brightness"
163+
description={`Brightness level (${videoBrightness.toFixed(1)}x)`}
164+
>
165+
<input
166+
type="range"
167+
min="0.5"
168+
max="1.5"
169+
step="0.1"
170+
value={videoBrightness}
171+
onChange={e => setVideoBrightness(parseFloat(e.target.value))}
172+
className="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
173+
/>
174+
</SettingsItem>
175+
176+
<SettingsItem
177+
title="Contrast"
178+
description={`Contrast level (${videoContrast.toFixed(1)}x)`}
179+
>
180+
<input
181+
type="range"
182+
min="0.5"
183+
max="2.0"
184+
step="0.1"
185+
value={videoContrast}
186+
onChange={e => setVideoContrast(parseFloat(e.target.value))}
187+
className="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
188+
/>
189+
</SettingsItem>
190+
191+
<div className="flex gap-2">
192+
<Button
193+
size="SM"
194+
theme="light"
195+
text="Reset to Default"
196+
onClick={() => {
197+
setVideoSaturation(1.0);
198+
setVideoBrightness(1.0);
199+
setVideoContrast(1.0);
200+
}}
201+
/>
202+
</div>
203+
</div>
204+
129205
<SettingsItem
130206
title="EDID"
131207
description="Adjust the EDID settings for the display"

0 commit comments

Comments
 (0)