From 96d7f0c92cdbce7eea50af3d6c7e35594df44540 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 21 May 2026 20:38:30 +0100 Subject: [PATCH] Trace Kiyo Pro framerate controls --- docs/native-capture-cadence.md | 35 +++++++++++++++++++ .../ks_camera_cadence/ks_camera_cadence.cpp | 9 +++++ state/evidence.jsonl | 1 + state/map.yaml | 9 +++-- 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/docs/native-capture-cadence.md b/docs/native-capture-cadence.md index b011dc1..7546b4e 100644 --- a/docs/native-capture-cadence.md +++ b/docs/native-capture-cadence.md @@ -158,3 +158,38 @@ manual exposure is forced shorter. Kiyo Pro advertises 60 fps modes but the current KS path delivers about 25 fps regardless of manual exposure, so it needs a separate driver/control investigation before it should be trusted for high cadence capture. + +Online follow-up: + +- Razer's support page for the Kiyo Pro confirms `1080p @ 60/30/24FPS`, + `720p @ 60FPS`, USB 3.0 connectivity, and HDR support, but also says HDR must + be toggled off to keep output aligned with the selected frame rate. +- Razer's firmware updater page lists `v1.5.0.1_r1` as the current RZ19-0364 + updater lineage and includes a factory-default reset command in that firmware. +- Razer's flicker/banding guidance says capture frame rate and powerline + frequency can interact, and points users to the anti-flicker/powerline + setting. +- Microsoft documents `KSPROPERTY_CAMERACONTROL_AUTO_EXPOSURE_PRIORITY` as the + UVC low-light compensation control, and says it allows the device to vary + frame rate under lighting conditions. +- Razer community reports show other users seeing Kiyo Pro firmware or control + states stuck below 60 fps, including one report that Linux and Windows both + failed to reach 60 fps after a firmware update. + +Local follow-up after that research: + +| Device | Mode | Scenario | Result | +| --- | --- | --- | ---: | +| Kiyo Pro | 1280x720 MJPG | baseline, low-light priority value `1`, powerline `50Hz` | 127 frames / 5.009s = 25.35 fps | +| Kiyo Pro | 1280x720 MJPG | low-light compensation off | 125 frames / 5.039s = 24.81 fps | +| Kiyo Pro | 1280x720 MJPG | powerline `60Hz` | 145 frames / 5.008s = 28.95 fps | +| Kiyo Pro | 1920x1080 MJPG | baseline, low-light priority value `1`, powerline `50Hz` | 126 frames / 5.006s = 25.17 fps | +| Kiyo Pro | 1920x1080 MJPG | low-light compensation off | 126 frames / 5.006s = 25.17 fps | +| Kiyo Pro | 1920x1080 MJPG | powerline `60Hz` | 145 frames / 5.020s = 28.88 fps | + +Conclusion: the Kiyo Pro's 25 fps result matches the kind of low-light / +anti-flicker / firmware trouble reported elsewhere, but the standard KS +properties are not enough to recover 60 fps locally. Powerline `60Hz` moves the +needle only to about 29 fps. The next investigation should compare this direct +KS path with Synapse/OBS and inspect whether the firmware exposes a vendor or +extension control that selects the real 60 fps profile. diff --git a/native/probes/ks_camera_cadence/ks_camera_cadence.cpp b/native/probes/ks_camera_cadence/ks_camera_cadence.cpp index f2c47fc..48f7a6b 100644 --- a/native/probes/ks_camera_cadence/ks_camera_cadence.cpp +++ b/native/probes/ks_camera_cadence/ks_camera_cadence.cpp @@ -215,11 +215,13 @@ void printKnownControls(HANDLE filter) const ControlWrite controls[] = { {"camera.zoom/exposure", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_ZOOM, 0, KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL}, {"camera.exposure", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_EXPOSURE, 0, KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL}, + {"camera.auto-exposure-priority/low-light", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_AUTO_EXPOSURE_PRIORITY, 0, KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL}, {"procamp.contrast/hdr-led", ControlSet::VideoProcAmp, KSPROPERTY_VIDEOPROCAMP_CONTRAST, 0, KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL}, {"procamp.gamma", ControlSet::VideoProcAmp, KSPROPERTY_VIDEOPROCAMP_GAMMA, 0, KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL}, {"procamp.brightness/digital-gain", ControlSet::VideoProcAmp, KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS, 0, KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL}, {"procamp.gain", ControlSet::VideoProcAmp, KSPROPERTY_VIDEOPROCAMP_GAIN, 0, KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL}, {"procamp.whitebalance/dark-frame", ControlSet::VideoProcAmp, KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE, 0, KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL}, + {"procamp.powerline-frequency", ControlSet::VideoProcAmp, KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY, 0, KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL}, }; std::printf("known LeapUVC-ish controls:\n"); @@ -882,12 +884,19 @@ int main(int argc, char** argv) const ULONG procManual = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL; const std::vector webcamScenarios = { {"baseline", {}}, + {"low-light compensation off", {{"camera.auto-exposure-priority/low-light", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_AUTO_EXPOSURE_PRIORITY, 0, camManual}}}, + {"powerline disabled", {{"procamp.powerline-frequency", ControlSet::VideoProcAmp, KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY, 0, procManual}}}, + {"powerline 50hz", {{"procamp.powerline-frequency", ControlSet::VideoProcAmp, KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY, 1, procManual}}}, + {"powerline 60hz", {{"procamp.powerline-frequency", ControlSet::VideoProcAmp, KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY, 2, procManual}}}, {"manual exposure -5", {{"camera.exposure", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_EXPOSURE, -5, camManual}}}, {"manual exposure -6", {{"camera.exposure", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_EXPOSURE, -6, camManual}}}, {"manual exposure -7", {{"camera.exposure", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_EXPOSURE, -7, camManual}}}, {"manual exposure -8", {{"camera.exposure", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_EXPOSURE, -8, camManual}}}, {"manual exposure -9", {{"camera.exposure", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_EXPOSURE, -9, camManual}}}, {"manual exposure -10", {{"camera.exposure", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_EXPOSURE, -10, camManual}}}, + {"low-light off + exposure -8", { + {"camera.auto-exposure-priority/low-light", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_AUTO_EXPOSURE_PRIORITY, 0, camManual}, + {"camera.exposure", ControlSet::Camera, KSPROPERTY_CAMERACONTROL_EXPOSURE, -8, camManual}}}, {"gain minimum", {{"procamp.gain", ControlSet::VideoProcAmp, KSPROPERTY_VIDEOPROCAMP_GAIN, 0, procManual}}}, }; bool measuredAny = false; diff --git a/state/evidence.jsonl b/state/evidence.jsonl index c95080d..ecae9bd 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -7,3 +7,4 @@ {"ts":"2026-05-21T20:25:00+00:00","type":"verification","status":"ok","note":"LeapUVC KS probe now keeps eight asynchronous NtDeviceIoControlFile reads queued. The path reports async=yes but cadence stays effectively unchanged: 640x240 YUY2 delivered 415 frames in 5.004s (82.93 fps), and 640x120 delivered 777 frames in 5.000s (155.39 fps). The limiting factor is not simply an empty user-mode read queue."} {"ts":"2026-05-21T20:55:00+00:00","type":"verification","status":"ok","note":"LeapUVC KS control sweep showed the short-window 83 fps result was mostly startup drag. With two seconds of warm-up discarded and eight queued async KS reads, 640x240 YUY2 delivered about 110.7 fps against 115 fps advertised; 640x120 YUY2 delivered 1030 frames in 5.003s (205.87 fps) against 214 fps advertised. Exposure, gamma, HDR/LED, gain, and dark-frame controls are reachable through KS; digital gain=0 and the old FPS-ratio selector are rejected with ERROR_INVALID_PARAMETER."} {"ts":"2026-05-21T21:25:00+00:00","type":"verification","status":"ok","note":"Razer Kiyo direct KS probe measured VID_1532 PID_0E03 and PID_0E05 camera interfaces with eight queued async reads and two-second warm-up discard. Plain Kiyo is exposure-limited by default: 1920x1080 MJPG reaches 30.27 fps with manual exposure -9/-10, and 1280x720 MJPG reaches 51.51 fps after manual exposure/gain sweep against 60 fps advertised. Kiyo Pro advertises 60 fps at 1280x720 and 1920x1080 MJPG, but the current KS path delivers only about 25 fps regardless of manual exposure; it needs separate control/driver investigation before high-cadence use."} +{"ts":"2026-05-21T21:55:00+00:00","type":"verification","status":"ok","note":"Online Kiyo Pro research found matching trouble reports: Razer documents 1080p60/720p60, HDR can reduce frame rate, anti-flicker/powerline can interact with frame rate, and Microsoft maps low-light compensation to AUTO_EXPOSURE_PRIORITY, which can vary frame rate. Local KS follow-up found Kiyo Pro reports low-light priority=1 and powerline=50Hz. Setting low-light priority to 0 did not improve cadence; setting powerline to 60Hz moved 720p/1080p MJPG only from about 25 fps to about 29 fps. Standard KS controls are not enough; next step is compare Synapse/OBS and inspect vendor/extension controls or firmware state."} diff --git a/state/map.yaml b/state/map.yaml index e27156d..83a06be 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -89,9 +89,12 @@ current_status: usable through KS when manual exposure is forced shorter: 1080p MJPG reaches about 30 fps and 720p MJPG reaches about 51.5 fps. Kiyo Pro advertises 60 fps MJPG at 720p/1080p but currently delivers only about 25 fps through the - same KS path even with manual exposure tuning. + same KS path even with manual exposure tuning. Online reports and local + control tests point at Kiyo Pro firmware/Synapse/anti-flicker or extension + control state: standard KS low-light compensation off does not restore 60 + fps, and powerline 60Hz only raises Pro cadence to about 29 fps. next_action: > Turn the warmed, queued Leap KS path into an `IMimirVideoCaptureDriver`, preserve direct control hooks for timing-camera state, and decide whether - Kiyo Pro needs a separate UVC/control path before it joins the six-camera - capture set. + Kiyo Pro needs Synapse/OBS comparison, vendor extension control inspection, + or firmware reset before it joins the six-camera capture set.