From 60f015b1997f3ff8eb1ed29739342b74fa430d7a Mon Sep 17 00:00:00 2001 From: Rodwin Spruel Date: Tue, 22 Apr 2025 11:22:20 +0000 Subject: [PATCH 1/7] Adding ability to override webp benchmark value --- common/rfb/EncodeManager.cxx | 2 +- common/rfb/ServerCore.cxx | 5 +++++ common/rfb/ServerCore.h | 1 + common/rfb/TightWEBPEncoder.cxx | 5 +++-- unix/vncserver | 9 +++++++++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx index 5e94cdc..30bfdce 100644 --- a/common/rfb/EncodeManager.cxx +++ b/common/rfb/EncodeManager.cxx @@ -395,7 +395,7 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_, screenArea = pb->getRect().width() * pb->getRect().height(); screenArea *= 1024; screenArea /= 256 * 256; - screenArea *= webpBenchResult; + screenArea *= screenArea *= Server::webpEncodingTime > 0 ? Server::webpEncodingTime : webpBenchResult; // Encoding the entire screen would take this many 1024*msecs, worst case // Calculate how many us we can send webp for, before switching to jpeg diff --git a/common/rfb/ServerCore.cxx b/common/rfb/ServerCore.cxx index 03a69d9..3c15be6 100644 --- a/common/rfb/ServerCore.cxx +++ b/common/rfb/ServerCore.cxx @@ -287,3 +287,8 @@ rfb::PresetParameter rfb::Server::preferBandwidth ("PreferBandwidth", "Set various options for lower bandwidth use. The default is off, aka to prefer quality.", false, bandwidthPreset); + +rfb::IntParameter rfb::Server::webpEncodingTime +("udpPort", + "Sets the benchmak WebP encoding time in KasmVNC. Default is calculated in TightWEBPEncoder benchmark function", + 0, 0, 10000); diff --git a/common/rfb/ServerCore.h b/common/rfb/ServerCore.h index 2035cf6..c3a53e5 100644 --- a/common/rfb/ServerCore.h +++ b/common/rfb/ServerCore.h @@ -91,6 +91,7 @@ namespace rfb { static BoolParameter ignoreClientSettingsKasm; static BoolParameter selfBench; static PresetParameter preferBandwidth; + static IntParameter webpEncodingTime; }; }; diff --git a/common/rfb/TightWEBPEncoder.cxx b/common/rfb/TightWEBPEncoder.cxx index 89d9b3a..2e79c6c 100644 --- a/common/rfb/TightWEBPEncoder.cxx +++ b/common/rfb/TightWEBPEncoder.cxx @@ -259,13 +259,14 @@ void TightWEBPEncoder::writeRect(const PixelBuffer* pb, const Palette& palette) WebPMemoryWriterClear(&wrt); } -// How many milliseconds would it take to encode a 256x256 block at quality 8 +// How many milliseconds would it take to encode a 256x256 block at quality 5 rdr::U32 TightWEBPEncoder::benchmark() const { rdr::U8* buffer; struct timeval start; int stride, i; - const uint8_t quality = 8, method = 2; + // the minimum WebP quality settings used in KasmVNC + const uint8_t quality = 5, method = 0; WebPConfig cfg; WebPPicture pic; WebPMemoryWriter wrt; diff --git a/unix/vncserver b/unix/vncserver index 41fc1be..eb2695f 100755 --- a/unix/vncserver +++ b/unix/vncserver @@ -2068,6 +2068,15 @@ sub DefineConfigToCLIConversion { $value; } }), + KasmVNC::CliOption->new({ + name => 'webpEncodingTime', + configKeys => [ + KasmVNC::ConfigKey->new({ + name => "encoding.video_encoding_mode.webp_encoding_time", + type => KasmVNC::ConfigKey::INT + }) + ] + }), KasmVNC::CliOption->new({ name => 'CompareFB', configKeys => [ From 2dbcd283545921d4c9a53196e0bd461d2d2fd25d Mon Sep 17 00:00:00 2001 From: Rodwin Spruel Date: Tue, 22 Apr 2025 11:22:20 +0000 Subject: [PATCH 2/7] Adding ability to override webp benchmark value --- common/rfb/EncodeManager.cxx | 2 +- common/rfb/ServerCore.cxx | 5 +++++ common/rfb/ServerCore.h | 1 + common/rfb/TightWEBPEncoder.cxx | 5 +++-- unix/vncserver | 9 +++++++++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx index 5e94cdc..30bfdce 100644 --- a/common/rfb/EncodeManager.cxx +++ b/common/rfb/EncodeManager.cxx @@ -395,7 +395,7 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_, screenArea = pb->getRect().width() * pb->getRect().height(); screenArea *= 1024; screenArea /= 256 * 256; - screenArea *= webpBenchResult; + screenArea *= screenArea *= Server::webpEncodingTime > 0 ? Server::webpEncodingTime : webpBenchResult; // Encoding the entire screen would take this many 1024*msecs, worst case // Calculate how many us we can send webp for, before switching to jpeg diff --git a/common/rfb/ServerCore.cxx b/common/rfb/ServerCore.cxx index 03a69d9..3c15be6 100644 --- a/common/rfb/ServerCore.cxx +++ b/common/rfb/ServerCore.cxx @@ -287,3 +287,8 @@ rfb::PresetParameter rfb::Server::preferBandwidth ("PreferBandwidth", "Set various options for lower bandwidth use. The default is off, aka to prefer quality.", false, bandwidthPreset); + +rfb::IntParameter rfb::Server::webpEncodingTime +("udpPort", + "Sets the benchmak WebP encoding time in KasmVNC. Default is calculated in TightWEBPEncoder benchmark function", + 0, 0, 10000); diff --git a/common/rfb/ServerCore.h b/common/rfb/ServerCore.h index 2035cf6..c3a53e5 100644 --- a/common/rfb/ServerCore.h +++ b/common/rfb/ServerCore.h @@ -91,6 +91,7 @@ namespace rfb { static BoolParameter ignoreClientSettingsKasm; static BoolParameter selfBench; static PresetParameter preferBandwidth; + static IntParameter webpEncodingTime; }; }; diff --git a/common/rfb/TightWEBPEncoder.cxx b/common/rfb/TightWEBPEncoder.cxx index 89d9b3a..2e79c6c 100644 --- a/common/rfb/TightWEBPEncoder.cxx +++ b/common/rfb/TightWEBPEncoder.cxx @@ -259,13 +259,14 @@ void TightWEBPEncoder::writeRect(const PixelBuffer* pb, const Palette& palette) WebPMemoryWriterClear(&wrt); } -// How many milliseconds would it take to encode a 256x256 block at quality 8 +// How many milliseconds would it take to encode a 256x256 block at quality 5 rdr::U32 TightWEBPEncoder::benchmark() const { rdr::U8* buffer; struct timeval start; int stride, i; - const uint8_t quality = 8, method = 2; + // the minimum WebP quality settings used in KasmVNC + const uint8_t quality = 5, method = 0; WebPConfig cfg; WebPPicture pic; WebPMemoryWriter wrt; diff --git a/unix/vncserver b/unix/vncserver index 41fc1be..eb2695f 100755 --- a/unix/vncserver +++ b/unix/vncserver @@ -2068,6 +2068,15 @@ sub DefineConfigToCLIConversion { $value; } }), + KasmVNC::CliOption->new({ + name => 'webpEncodingTime', + configKeys => [ + KasmVNC::ConfigKey->new({ + name => "encoding.video_encoding_mode.webp_encoding_time", + type => KasmVNC::ConfigKey::INT + }) + ] + }), KasmVNC::CliOption->new({ name => 'CompareFB', configKeys => [ From 7353f386524c4ee6baf7ecb558322a65375e04e1 Mon Sep 17 00:00:00 2001 From: "Rodwin.Spruel" Date: Tue, 22 Apr 2025 10:39:53 -0400 Subject: [PATCH 3/7] Adding defaults and fixing typo --- common/rfb/ServerCore.cxx | 4 ++-- unix/kasmvnc_defaults.yaml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/common/rfb/ServerCore.cxx b/common/rfb/ServerCore.cxx index 3c15be6..f242b54 100644 --- a/common/rfb/ServerCore.cxx +++ b/common/rfb/ServerCore.cxx @@ -289,6 +289,6 @@ rfb::PresetParameter rfb::Server::preferBandwidth false, bandwidthPreset); rfb::IntParameter rfb::Server::webpEncodingTime -("udpPort", - "Sets the benchmak WebP encoding time in KasmVNC. Default is calculated in TightWEBPEncoder benchmark function", +("webpEncodingTime", + "Sets a weighted value that determines how much webp is used to balance bandwidth and CPU usage.", 0, 0, 10000); diff --git a/unix/kasmvnc_defaults.yaml b/unix/kasmvnc_defaults.yaml index 3d0551c..e75591e 100644 --- a/unix/kasmvnc_defaults.yaml +++ b/unix/kasmvnc_defaults.yaml @@ -129,6 +129,7 @@ encoding: logging: level: off scaling_algorithm: progressive_bilinear + webp_encoding_time: 0 compare_framebuffer: auto zrle_zlib_level: auto From 3bc040387767544dc3932aba1e50a7e07a1477a6 Mon Sep 17 00:00:00 2001 From: "Rodwin.Spruel" Date: Tue, 22 Apr 2025 17:17:58 -0400 Subject: [PATCH 4/7] Updating weighting function and limits Signed-off-by: Rodwin.Spruel --- common/rfb/EncodeManager.cxx | 3 ++- common/rfb/ServerCore.cxx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx index 30bfdce..69142c0 100644 --- a/common/rfb/EncodeManager.cxx +++ b/common/rfb/EncodeManager.cxx @@ -395,7 +395,8 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_, screenArea = pb->getRect().width() * pb->getRect().height(); screenArea *= 1024; screenArea /= 256 * 256; - screenArea *= screenArea *= Server::webpEncodingTime > 0 ? Server::webpEncodingTime : webpBenchResult; + screenArea *= screenArea; + screenArea /= Server::webpEncodingTime > 1 ? Server::webpEncodingTime : 1; // Encoding the entire screen would take this many 1024*msecs, worst case // Calculate how many us we can send webp for, before switching to jpeg diff --git a/common/rfb/ServerCore.cxx b/common/rfb/ServerCore.cxx index f242b54..91174d6 100644 --- a/common/rfb/ServerCore.cxx +++ b/common/rfb/ServerCore.cxx @@ -291,4 +291,4 @@ rfb::PresetParameter rfb::Server::preferBandwidth rfb::IntParameter rfb::Server::webpEncodingTime ("webpEncodingTime", "Sets a weighted value that determines how much webp is used to balance bandwidth and CPU usage.", - 0, 0, 10000); + 1, 1, 1000); From f674e2c58df88038dab84f01baa4b7498e681b19 Mon Sep 17 00:00:00 2001 From: Rodwin Spruel Date: Tue, 22 Apr 2025 21:45:16 +0000 Subject: [PATCH 5/7] Fixing default value --- unix/kasmvnc_defaults.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unix/kasmvnc_defaults.yaml b/unix/kasmvnc_defaults.yaml index e75591e..c4e2a03 100644 --- a/unix/kasmvnc_defaults.yaml +++ b/unix/kasmvnc_defaults.yaml @@ -129,7 +129,7 @@ encoding: logging: level: off scaling_algorithm: progressive_bilinear - webp_encoding_time: 0 + webp_encoding_time: 1 compare_framebuffer: auto zrle_zlib_level: auto From 02852185a86475737bb047a3abbd099a9274af08 Mon Sep 17 00:00:00 2001 From: "Rodwin.Spruel" Date: Thu, 24 Apr 2025 05:57:25 -0400 Subject: [PATCH 6/7] Fixing webp usage calculation and updating default value --- common/rfb/EncodeManager.cxx | 4 ++-- unix/kasmvnc_defaults.yaml | 24 ++++++++++++------------ unix/vncserver | 18 +++++++++++++++--- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx index 69142c0..cd855e9 100644 --- a/common/rfb/EncodeManager.cxx +++ b/common/rfb/EncodeManager.cxx @@ -395,8 +395,8 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_, screenArea = pb->getRect().width() * pb->getRect().height(); screenArea *= 1024; screenArea /= 256 * 256; - screenArea *= screenArea; - screenArea /= Server::webpEncodingTime > 1 ? Server::webpEncodingTime : 1; + screenArea *= webpBenchResult; + screenArea /= Server::webpEncodingTime; // Encoding the entire screen would take this many 1024*msecs, worst case // Calculate how many us we can send webp for, before switching to jpeg diff --git a/unix/kasmvnc_defaults.yaml b/unix/kasmvnc_defaults.yaml index c4e2a03..1f042ee 100644 --- a/unix/kasmvnc_defaults.yaml +++ b/unix/kasmvnc_defaults.yaml @@ -37,7 +37,7 @@ user_session: keyboard: remap_keys: - # - 0x22->0x40 + # - 0x22->0x40 ignore_numlock: false raw_keyboard: false @@ -92,16 +92,16 @@ data_loss_prevention: enabled: true rate_limit: unlimited watermark: - # image: /etc/kasmvnc/picture.png - # location: 10,10 - # tint: 255,20,20,128 - # repeat_spacing: 10 - #text: - # template: "${USER} %H:%M" - # font: auto - # font_size: 48 - # timezone_name: Australia/Adelaide - # angle: 0 + # image: /etc/kasmvnc/picture.png + # location: 10,10 + # tint: 255,20,20,128 + # repeat_spacing: 10 + #text: + # template: "${USER} %H:%M" + # font: auto + # font_size: 48 + # timezone_name: Australia/Adelaide + # angle: 0 logging: # "verbose" SETTING LOGS YOUR PRIVATE INFORMATION. Keypresses and clipboard content level: off @@ -129,7 +129,7 @@ encoding: logging: level: off scaling_algorithm: progressive_bilinear - webp_encoding_time: 1 + webp_encoding_time: auto compare_framebuffer: auto zrle_zlib_level: auto diff --git a/unix/vncserver b/unix/vncserver index eb2695f..975d4a9 100755 --- a/unix/vncserver +++ b/unix/vncserver @@ -2069,13 +2069,25 @@ sub DefineConfigToCLIConversion { } }), KasmVNC::CliOption->new({ - name => 'webpEncodingTime', + name => 'WebpEncodingTime', configKeys => [ KasmVNC::ConfigKey->new({ name => "encoding.video_encoding_mode.webp_encoding_time", - type => KasmVNC::ConfigKey::INT + validator => KasmVNC::PatternValidator->new({ + pattern => qr/^(auto|[1-9][0-9]{0,2}|1000)$/, + errorMessage => "must be 'auto' or a number in 1..1000" + }), }) - ] + ], + deriveValueSub => sub { + my $self = shift; + my $value = $self->configValue(); + + if ($value eq "auto") { + $value = 1; + } + $value; + } }), KasmVNC::CliOption->new({ name => 'CompareFB', From 00b8d025db7ab77471e29652c2f0d7bb22a144f7 Mon Sep 17 00:00:00 2001 From: matt Date: Thu, 24 Apr 2025 16:50:44 +0000 Subject: [PATCH 7/7] KASM-7125 fixed issue with rebuilding Xvnc, switched to simplier webp mix math. --- builder/build.sh | 79 +++++++++++++++++++----------------- common/rfb/EncodeManager.cxx | 15 +------ common/rfb/ServerCore.cxx | 4 +- unix/kasmvnc_defaults.yaml | 22 +++++----- unix/vncserver | 30 ++++---------- 5 files changed, 65 insertions(+), 85 deletions(-) diff --git a/builder/build.sh b/builder/build.sh index ed481df..332fd27 100755 --- a/builder/build.sh +++ b/builder/build.sh @@ -76,46 +76,49 @@ if [ ! -d unix/xserver/include ]; then patch -s -p0 < ../CVE-2022-2320-v1.19.patch ;; esac - - autoreconf -i - # Configuring Xorg is long and has many distro-specific paths. - # The distro paths start after prefix and end with the font path, - # everything after that is based on BUILDING.txt to remove unneeded - # components. - # remove gl check for opensuse - if [ "${KASMVNC_BUILD_OS}" == "opensuse" ] || ([ "${KASMVNC_BUILD_OS}" == "oracle" ] && [ "${KASMVNC_BUILD_OS_CODENAME}" == 9 ]); then - sed -i 's/LIBGL="gl >= 7.1.0"/LIBGL="gl >= 1.1"/g' configure - fi - - # build X11 - ./configure \ - --disable-config-hal \ - --disable-config-udev \ - --disable-dmx \ - --disable-dri \ - --disable-dri2 \ - --disable-kdrive \ - --disable-static \ - --disable-xephyr \ - --disable-xinerama \ - --disable-xnest \ - --disable-xorg \ - --disable-xvfb \ - --disable-xwayland \ - --disable-xwin \ - --enable-glx \ - --prefix=/opt/kasmweb \ - --with-default-font-path="/usr/share/fonts/X11/misc,/usr/share/fonts/X11/cyrillic,/usr/share/fonts/X11/100dpi/:unscaled,/usr/share/fonts/X11/75dpi/:unscaled,/usr/share/fonts/X11/Type1,/usr/share/fonts/X11/100dpi,/usr/share/fonts/X11/75dpi,built-ins" \ - --without-dtrace \ - --with-sha1=libcrypto \ - --with-xkb-bin-directory=/usr/bin \ - --with-xkb-output=/var/lib/xkb \ - --with-xkb-path=/usr/share/X11/xkb "${CONFIG_OPTIONS}" - - # remove array bounds errors for new versions of GCC - find . -name "Makefile" -exec sed -i 's/-Werror=array-bounds//g' {} \; +else + cd unix/xserver fi +autoreconf -i +# Configuring Xorg is long and has many distro-specific paths. +# The distro paths start after prefix and end with the font path, +# everything after that is based on BUILDING.txt to remove unneeded +# components. +# remove gl check for opensuse +if [ "${KASMVNC_BUILD_OS}" == "opensuse" ] || ([ "${KASMVNC_BUILD_OS}" == "oracle" ] && [ "${KASMVNC_BUILD_OS_CODENAME}" == 9 ]); then + sed -i 's/LIBGL="gl >= 7.1.0"/LIBGL="gl >= 1.1"/g' configure +fi + +# build X11 +./configure \ + --disable-config-hal \ + --disable-config-udev \ + --disable-dmx \ + --disable-dri \ + --disable-dri2 \ + --disable-kdrive \ + --disable-static \ + --disable-xephyr \ + --disable-xinerama \ + --disable-xnest \ + --disable-xorg \ + --disable-xvfb \ + --disable-xwayland \ + --disable-xwin \ + --enable-glx \ + --prefix=/opt/kasmweb \ + --with-default-font-path="/usr/share/fonts/X11/misc,/usr/share/fonts/X11/cyrillic,/usr/share/fonts/X11/100dpi/:unscaled,/usr/share/fonts/X11/75dpi/:unscaled,/usr/share/fonts/X11/Type1,/usr/share/fonts/X11/100dpi,/usr/share/fonts/X11/75dpi,built-ins" \ + --without-dtrace \ + --with-sha1=libcrypto \ + --with-xkb-bin-directory=/usr/bin \ + --with-xkb-output=/var/lib/xkb \ + --with-xkb-path=/usr/share/X11/xkb "${CONFIG_OPTIONS}" + +# remove array bounds errors for new versions of GCC +find . -name "Makefile" -exec sed -i 's/-Werror=array-bounds//g' {} \; + + make -j"$(nproc)" # modifications for the servertarball diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx index cd855e9..5dbf1dc 100644 --- a/common/rfb/EncodeManager.cxx +++ b/common/rfb/EncodeManager.cxx @@ -360,7 +360,6 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_, int nRects; Region changed, cursorRegion; struct timeval start; - unsigned screenArea; updates++; if (conn->cp.supportsUdp) @@ -390,17 +389,7 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_, memset(&webpstats, 0, sizeof(codecstats_t)); if (allowLossy && activeEncoders[encoderFullColour] == encoderTightWEBP) { - const unsigned rate = 1024 * 1000 / rfb::Server::frameRate; - - screenArea = pb->getRect().width() * pb->getRect().height(); - screenArea *= 1024; - screenArea /= 256 * 256; - screenArea *= webpBenchResult; - screenArea /= Server::webpEncodingTime; - // Encoding the entire screen would take this many 1024*msecs, worst case - - // Calculate how many us we can send webp for, before switching to jpeg - webpFallbackUs = rate * rate / screenArea; + webpFallbackUs = (1000 * 1000 / rfb::Server::frameRate) * (static_cast(Server::webpEncodingTime) / 100.0); } /* @@ -884,7 +873,7 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed, void EncodeManager::checkWebpFallback(const timeval *start) { // Have we taken too long for the frame? If so, drop from WEBP to JPEG if (start && activeEncoders[encoderFullColour] == encoderTightWEBP && !webpTookTooLong.load(std::memory_order_relaxed)) { - const auto us = msSince(start) * 1024; + const auto us = msSince(start) * 1000; if (us > webpFallbackUs) webpTookTooLong.store(true, std::memory_order_relaxed); } diff --git a/common/rfb/ServerCore.cxx b/common/rfb/ServerCore.cxx index 91174d6..3881693 100644 --- a/common/rfb/ServerCore.cxx +++ b/common/rfb/ServerCore.cxx @@ -290,5 +290,5 @@ rfb::PresetParameter rfb::Server::preferBandwidth rfb::IntParameter rfb::Server::webpEncodingTime ("webpEncodingTime", - "Sets a weighted value that determines how much webp is used to balance bandwidth and CPU usage.", - 1, 1, 1000); + "Percentage of time allotted for encoding a frame, that can be used for encoding rects in webp.", + 30, 0, 100); diff --git a/unix/kasmvnc_defaults.yaml b/unix/kasmvnc_defaults.yaml index 1f042ee..afad666 100644 --- a/unix/kasmvnc_defaults.yaml +++ b/unix/kasmvnc_defaults.yaml @@ -92,16 +92,16 @@ data_loss_prevention: enabled: true rate_limit: unlimited watermark: - # image: /etc/kasmvnc/picture.png - # location: 10,10 - # tint: 255,20,20,128 - # repeat_spacing: 10 - #text: - # template: "${USER} %H:%M" - # font: auto - # font_size: 48 - # timezone_name: Australia/Adelaide - # angle: 0 + # image: /etc/kasmvnc/picture.png + # location: 10,10 + # tint: 255,20,20,128 + # repeat_spacing: 10 + #text: + # template: "${USER} %H:%M" + # font: auto + # font_size: 48 + # timezone_name: Australia/Adelaide + # angle: 0 logging: # "verbose" SETTING LOGS YOUR PRIVATE INFORMATION. Keypresses and clipboard content level: off @@ -129,7 +129,7 @@ encoding: logging: level: off scaling_algorithm: progressive_bilinear - webp_encoding_time: auto + webp_encoding_time: 30 compare_framebuffer: auto zrle_zlib_level: auto diff --git a/unix/vncserver b/unix/vncserver index 975d4a9..1ac99c8 100755 --- a/unix/vncserver +++ b/unix/vncserver @@ -2068,27 +2068,15 @@ sub DefineConfigToCLIConversion { $value; } }), - KasmVNC::CliOption->new({ - name => 'WebpEncodingTime', - configKeys => [ - KasmVNC::ConfigKey->new({ - name => "encoding.video_encoding_mode.webp_encoding_time", - validator => KasmVNC::PatternValidator->new({ - pattern => qr/^(auto|[1-9][0-9]{0,2}|1000)$/, - errorMessage => "must be 'auto' or a number in 1..1000" - }), - }) - ], - deriveValueSub => sub { - my $self = shift; - my $value = $self->configValue(); - - if ($value eq "auto") { - $value = 1; - } - $value; - } - }), + KasmVNC::CliOption->new({ + name => 'WebpEncodingTime', + configKeys => [ + KasmVNC::ConfigKey->new({ + name => "encoding.video_encoding_mode.webp_encoding_time", + type => KasmVNC::ConfigKey::INT + }) + ] + }), KasmVNC::CliOption->new({ name => 'CompareFB', configKeys => [