feat(video): add video enhancement settings for saturation, brightness, and contrast

This commit is contained in:
Andy Riedel 2025-06-03 22:09:54 +00:00
parent 52dd675e52
commit 298c36398f
3 changed files with 100 additions and 0 deletions

View File

@ -46,6 +46,11 @@ export default function WebRTCVideo() {
clientHeight: videoClientHeight,
} = useVideoStore();
// Video enhancement settings
const videoSaturation = useSettingsStore(state => state.videoSaturation);
const videoBrightness = useSettingsStore(state => state.videoBrightness);
const videoContrast = useSettingsStore(state => state.videoContrast);
// HID related states
const keyboardLedStateSyncAvailable = useHidStore(state => state.keyboardLedStateSyncAvailable);
const keyboardLedSync = useSettingsStore(state => state.keyboardLedSync);
@ -674,6 +679,9 @@ export default function WebRTCVideo() {
playsInline
disablePictureInPicture
controlsList="nofullscreen"
style={{
filter: `saturate(${videoSaturation}) brightness(${videoBrightness}) contrast(${videoContrast})`,
}}
className={cx(
"max-h-full min-h-[384px] max-w-full min-w-[512px] bg-black/50 object-contain transition-all duration-1000",
{

View File

@ -319,6 +319,14 @@ interface SettingsState {
showPressedKeys: boolean;
setShowPressedKeys: (show: boolean) => void;
// Video enhancement settings
videoSaturation: number;
setVideoSaturation: (value: number) => void;
videoBrightness: number;
setVideoBrightness: (value: number) => void;
videoContrast: number;
setVideoContrast: (value: number) => void;
}
export const useSettingsStore = create(
@ -362,6 +370,14 @@ export const useSettingsStore = create(
showPressedKeys: true,
setShowPressedKeys: show => set({ showPressedKeys: show }),
// Video enhancement settings with default values (1.0 = normal)
videoSaturation: 1.0,
setVideoSaturation: value => set({ videoSaturation: value }),
videoBrightness: 1.0,
setVideoBrightness: value => set({ videoBrightness: value }),
videoContrast: 1.0,
setVideoContrast: value => set({ videoContrast: value }),
}),
{
name: "settings",

View File

@ -4,6 +4,7 @@ import { Button } from "@/components/Button";
import { TextAreaWithLabel } from "@/components/TextArea";
import { useJsonRpc } from "@/hooks/useJsonRpc";
import { SettingsPageHeader } from "@components/SettingsPageheader";
import { useSettingsStore } from "@/hooks/stores";
import notifications from "../notifications";
import { SelectMenuBasic } from "../components/SelectMenuBasic";
@ -45,6 +46,14 @@ export default function SettingsVideoRoute() {
const [customEdidValue, setCustomEdidValue] = useState<string | null>(null);
const [edid, setEdid] = useState<string | null>(null);
// Video enhancement settings from store
const videoSaturation = useSettingsStore(state => state.videoSaturation);
const setVideoSaturation = useSettingsStore(state => state.setVideoSaturation);
const videoBrightness = useSettingsStore(state => state.videoBrightness);
const setVideoBrightness = useSettingsStore(state => state.setVideoBrightness);
const videoContrast = useSettingsStore(state => state.videoContrast);
const setVideoContrast = useSettingsStore(state => state.setVideoContrast);
useEffect(() => {
send("getStreamQualityFactor", {}, resp => {
if ("error" in resp) return;
@ -126,6 +135,73 @@ export default function SettingsVideoRoute() {
onChange={e => handleStreamQualityChange(e.target.value)}
/>
</SettingsItem>
{/* Video Enhancement Settings */}
<SettingsItem
title="Video Enhancement"
description="Adjust color settings to make the video output more vibrant and colorful"
/>
<div className="space-y-4 pl-4">
<SettingsItem
title="Saturation"
description={`Color saturation (${videoSaturation.toFixed(1)}x)`}
>
<input
type="range"
min="0.5"
max="2.0"
step="0.1"
value={videoSaturation}
onChange={e => setVideoSaturation(parseFloat(e.target.value))}
className="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
/>
</SettingsItem>
<SettingsItem
title="Brightness"
description={`Brightness level (${videoBrightness.toFixed(1)}x)`}
>
<input
type="range"
min="0.5"
max="1.5"
step="0.1"
value={videoBrightness}
onChange={e => setVideoBrightness(parseFloat(e.target.value))}
className="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
/>
</SettingsItem>
<SettingsItem
title="Contrast"
description={`Contrast level (${videoContrast.toFixed(1)}x)`}
>
<input
type="range"
min="0.5"
max="2.0"
step="0.1"
value={videoContrast}
onChange={e => setVideoContrast(parseFloat(e.target.value))}
className="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
/>
</SettingsItem>
<div className="flex gap-2">
<Button
size="SM"
theme="light"
text="Reset to Default"
onClick={() => {
setVideoSaturation(1.0);
setVideoBrightness(1.0);
setVideoContrast(1.0);
}}
/>
</div>
</div>
<SettingsItem
title="EDID"
description="Adjust the EDID settings for the display"