mirror of https://github.com/jetkvm/kvm.git
feat(video): add video enhancement settings for saturation, brightness, and contrast
This commit is contained in:
parent
52dd675e52
commit
298c36398f
|
@ -46,6 +46,11 @@ export default function WebRTCVideo() {
|
||||||
clientHeight: videoClientHeight,
|
clientHeight: videoClientHeight,
|
||||||
} = useVideoStore();
|
} = 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
|
// HID related states
|
||||||
const keyboardLedStateSyncAvailable = useHidStore(state => state.keyboardLedStateSyncAvailable);
|
const keyboardLedStateSyncAvailable = useHidStore(state => state.keyboardLedStateSyncAvailable);
|
||||||
const keyboardLedSync = useSettingsStore(state => state.keyboardLedSync);
|
const keyboardLedSync = useSettingsStore(state => state.keyboardLedSync);
|
||||||
|
@ -674,6 +679,9 @@ export default function WebRTCVideo() {
|
||||||
playsInline
|
playsInline
|
||||||
disablePictureInPicture
|
disablePictureInPicture
|
||||||
controlsList="nofullscreen"
|
controlsList="nofullscreen"
|
||||||
|
style={{
|
||||||
|
filter: `saturate(${videoSaturation}) brightness(${videoBrightness}) contrast(${videoContrast})`,
|
||||||
|
}}
|
||||||
className={cx(
|
className={cx(
|
||||||
"max-h-full min-h-[384px] max-w-full min-w-[512px] bg-black/50 object-contain transition-all duration-1000",
|
"max-h-full min-h-[384px] max-w-full min-w-[512px] bg-black/50 object-contain transition-all duration-1000",
|
||||||
{
|
{
|
||||||
|
|
|
@ -319,6 +319,14 @@ interface SettingsState {
|
||||||
|
|
||||||
showPressedKeys: boolean;
|
showPressedKeys: boolean;
|
||||||
setShowPressedKeys: (show: boolean) => void;
|
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(
|
export const useSettingsStore = create(
|
||||||
|
@ -362,6 +370,14 @@ export const useSettingsStore = create(
|
||||||
|
|
||||||
showPressedKeys: true,
|
showPressedKeys: true,
|
||||||
setShowPressedKeys: show => set({ showPressedKeys: show }),
|
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",
|
name: "settings",
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { Button } from "@/components/Button";
|
||||||
import { TextAreaWithLabel } from "@/components/TextArea";
|
import { TextAreaWithLabel } from "@/components/TextArea";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||||
|
import { useSettingsStore } from "@/hooks/stores";
|
||||||
|
|
||||||
import notifications from "../notifications";
|
import notifications from "../notifications";
|
||||||
import { SelectMenuBasic } from "../components/SelectMenuBasic";
|
import { SelectMenuBasic } from "../components/SelectMenuBasic";
|
||||||
|
@ -45,6 +46,14 @@ export default function SettingsVideoRoute() {
|
||||||
const [customEdidValue, setCustomEdidValue] = useState<string | null>(null);
|
const [customEdidValue, setCustomEdidValue] = useState<string | null>(null);
|
||||||
const [edid, setEdid] = 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(() => {
|
useEffect(() => {
|
||||||
send("getStreamQualityFactor", {}, resp => {
|
send("getStreamQualityFactor", {}, resp => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
|
@ -126,6 +135,73 @@ export default function SettingsVideoRoute() {
|
||||||
onChange={e => handleStreamQualityChange(e.target.value)}
|
onChange={e => handleStreamQualityChange(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</SettingsItem>
|
</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
|
<SettingsItem
|
||||||
title="EDID"
|
title="EDID"
|
||||||
description="Adjust the EDID settings for the display"
|
description="Adjust the EDID settings for the display"
|
||||||
|
|
Loading…
Reference in New Issue