Hi @troto-maton
You’re running into a real limitation, not a formatting mistake.
Why your added settings appear to have no effect
The ZEDFusionLiveLinkConfig.json file is parsed by the LiveLink Fusion sender against a fixed schema. The sender reads only the blocks you already have — StreamingParameters, InitParameters, BodyTrackingParameters, InitFusionParameters, and BodyTrackingFusionParameters — and maps each known key onto the corresponding SDK struct. Any key the parser doesn’t explicitly look for is silently ignored. So if you’ve been adding things like brightness, exposure, gain, or whitebalance into the JSON, that’s exactly why nothing changes: there’s no code path reading them.
It’s also worth separating two different categories of settings:
InitParameters (resolution, fps, depth_mode, …) — these are applied at Camera::open() and the config file does drive them. These parameters can only be set before opening the camera and cannot be changed while the camera is in use. Reference: Using the Video API. Stereolabs
- Runtime ISP / video settings (brightness, contrast, hue, saturation, sharpness, gamma, gain, exposure, white balance, AEC/AGC) — these are not part of
InitParameters. Camera settings such as exposure, white balance and more can be manually set at runtime using setCameraSettings(); to change camera resolution and frame rate, use InitParameters. There is no JSON binding for these in the stock sender. Reference: Camera Controls. Stereolabs
So no amount of config editing will reach the ISP controls, because that path simply isn’t wired up.
The fix: patch the sender source
Since the 4.1 SDK, the LiveLink senders build like any other ZED SDK sample, so this is straightforward. After the camera opens (and before/while the grab loop runs) in the fusion sender, add your settings calls per camera. Something like:
cpp
// after zed.open(init_parameters) succeeds, per camera object
zed.setCameraSettings(VIDEO_SETTINGS::EXPOSURE, 50); // 0-100, or -1 for AUTO
zed.setCameraSettings(VIDEO_SETTINGS::GAIN, 60);
zed.setCameraSettings(VIDEO_SETTINGS::AEC_AGC, 0); // disable auto exposure/gain
zed.setCameraSettings(VIDEO_SETTINGS::WHITEBALANCE_AUTO, 0); // disable auto WB
zed.setCameraSettings(VIDEO_SETTINGS::WHITEBALANCE_TEMPERATURE, 4600);
zed.setCameraSettings(VIDEO_SETTINGS::BRIGHTNESS, 4);
zed.setCameraSettings(VIDEO_SETTINGS::CONTRAST, 4);
zed.setCameraSettings(VIDEO_SETTINGS::GAMMA, 5); // raise in low light
A couple of practical notes:
- For manual exposure, set
EXPOSURE and GAIN to explicit values and set AEC_AGC to 0. VIDEO_SETTINGS::AEC_AGC controls whether the Exposure/Gain are in automatic mode or not — this was previously mixed into the default value of Exposure or gain control and is now separated. Passing -1 puts a control back into AUTO. Stereolabs
- On white balance: setting a value to VIDEO_SETTINGS::WHITEBALANCE_TEMPERATURE will automatically disable VIDEO_SETTINGS::WHITEBALANCE_AUTO. Stereolabs
setCameraSettings() only works once the camera is opened, and it adjusts left/right sensors in sync — you can’t tune them individually.
- If you want to keep things config-driven rather than hardcoded, the clean approach is to add your own block (e.g.
"CameraSettings") to the JSON and extend the sender’s parser to read it and issue the matching setCameraSettings() calls. The stock parser won’t do this for you, but since you’re building from source anyway, it’s a small addition.
For the full enum of tunable values and their ranges, see the VIDEO_SETTINGS API reference. The LiveLink sender source and config layout are in the zed-livelink repo, and the build steps are documented under Building ZED Live Link.
If you’d rather avoid touching C++, the alternative is to set your desired ISP values once in ZED Explorer — on some setups the last-applied settings persist on the camera — but that’s far less reliable than driving them explicitly in the sender, especially across two ZED 2i units.
One thing to confirm: are you trying to set these once at startup (a known fixed look), or do you need to change them dynamically while Unreal is running? That changes whether a one-shot post-open block is enough or whether you need to expose a small control hook in the sender loop.
Let me know how it goes.