Change deadband zone message from DEBUG to LOG level to prevent spam while still showing gain/exposure adjustment messages. This allows using --gst-debug to see important ramping information without flooding the output with 'Within deadband zone' messages every frame.
GStreamer Intervalometer Filter
Automatic Exposure Control for IDS uEye Cameras
Inspired by YASS (Yet Another Sunset Script) for CHDK cameras.
Overview
The intervalometer element is a GStreamer filter that automatically adjusts camera exposure and gain settings during changing light conditions. It analyzes video brightness in real-time and smoothly ramps camera parameters to maintain optimal exposure - perfect for time-lapse photography during sunset, sunrise, or other variable lighting scenarios.
Features
- Automatic Exposure Ramping: Smoothly adjusts exposure time based on scene brightness
- Automatic Gain Control: Increases/decreases sensor gain when exposure limits are reached
- Configurable Ranges: Set custom min/max values for exposure (0.85-1.24ms) and gain (0-52)
- Multiple Ramp Rates: Choose from VSlow/Slow/Medium/Fast/VFast adjustment speeds
- Exposure Compensation: Fine-tune brightness with ±4 stops of compensation
- CSV Logging: Optional detailed logging of all exposure parameters
- Multiple Format Support: Works with GRAY8, GRAY16, RGB, BGR, and BGRA video
Requirements
- GStreamer 1.0+
- IDS uEye camera with
idsueyesrcelement - Camera must support runtime exposure and gain property changes
Installation
The filter is built as part of the gst-plugins-vision project. Build and install normally:
mkdir build
cd build
cmake ..
make
make install
Properties
Control Properties
| Property | Type | Range | Default | Description |
|---|---|---|---|---|
enabled |
boolean | - | TRUE | Enable/disable auto-exposure |
target-brightness |
double | 0-255 | 128.0 | Target average brightness level |
compensation |
double | -4.0 to 4.0 | 0.0 | Exposure compensation in stops |
camera-element |
string | - | "" | Name of upstream idsueyesrc element |
Exposure Range
| Property | Type | Range | Default | Description |
|---|---|---|---|---|
exposure-min |
double | 0.01-1000.0 | 0.85 | Minimum exposure time (ms) |
exposure-max |
double | 0.01-1000.0 | 1.24 | Maximum exposure time (ms) |
Gain Range
| Property | Type | Range | Default | Description |
|---|---|---|---|---|
gain-min |
int | 0-100 | 0 | Minimum gain value |
gain-max |
int | 0-100 | 52 | Maximum gain value |
Ramping
| Property | Type | Values | Default | Description |
|---|---|---|---|---|
ramp-rate |
enum | VSlow, Slow, Medium, Fast, VFast | Medium | Speed of parameter changes |
update-interval |
int | 10-10000 | 100 | Time between exposure updates (ms) |
Brightness Filtering
| Property | Type | Range | Default | Description |
|---|---|---|---|---|
brightness-smoothing |
double | 0.0-1.0 | 0.1 | Temporal smoothing factor (EMA alpha) |
brightness-deadband |
double | 0.0-50.0 | 10.0 | Deadband zone to prevent oscillation (0=disabled) |
Logging
| Property | Type | Range | Default | Description |
|---|---|---|---|---|
log-file |
string | - | "" | Path to CSV log file (empty = disabled) |
Usage Examples
Basic Auto-Exposure
gst-launch-1.0 idsueyesrc name=cam ! \
intervalometer enabled=true camera-element=cam ! \
videoconvert ! autovideosink
Custom Range for Day/Night Transition
Configure for the typical day (0.85ms exposure, gain 52) to night (1.24ms exposure, gain 0) range:
gst-launch-1.0 idsueyesrc name=cam ! \
intervalometer enabled=true camera-element=cam \
exposure-min=0.85 exposure-max=1.24 \
gain-min=0 gain-max=52 \
ramp-rate=medium ! \
videoconvert ! autovideosink
With Exposure Compensation
Adjust overall brightness with compensation:
gst-launch-1.0 idsueyesrc name=cam ! \
intervalometer enabled=true camera-element=cam \
compensation=1.0 \
target-brightness=140 ! \
videoconvert ! autovideosink
With CSV Logging
Log all exposure data to a CSV file:
gst-launch-1.0 idsueyesrc name=cam ! \
intervalometer enabled=true camera-element=cam \
log-file=exposure_log.csv ! \
videoconvert ! autovideosink
Dawn/Dusk Time-Lapse (Recommended)
Optimized settings for smooth sunrise/sunset time-lapse:
gst-launch-1.0 \
idsueyesrc config-file=ini/whole-presacler64_autoexp-binningx2.ini \
exposure=0.85 framerate=50 gain=0 name=cam device-id=2 ! \
intervalometer enabled=true camera-element=cam \
ramp-rate=vslow \
update-interval=1000 \
brightness-smoothing=0.1 \
brightness-deadband=10.0 \
log-file=timelapse.csv ! \
videocrop bottom=3 ! queue ! videoconvert ! autovideosink
Key settings:
ramp-rate=vslow: 5% exposure steps per update (smooth transitions)update-interval=1000: Updates every 1 second (not too aggressive)brightness-smoothing=0.1: Filters out moving objects (cars, people, birds)brightness-deadband=10.0: Prevents oscillation by creating a stable zone
Complete Time-Lapse Recording
Record a time-lapse with auto-exposure:
gst-launch-1.0 idsueyesrc name=cam framerate=1 ! \
intervalometer enabled=true camera-element=cam \
exposure-min=0.85 exposure-max=1.24 \
gain-min=0 gain-max=52 \
ramp-rate=slow \
log-file=timelapse_exposure.csv ! \
videoconvert ! x264enc ! mp4mux ! \
filesink location=timelapse.mp4
How It Works
Exposure Control Algorithm
The filter uses a YASS-inspired algorithm with deadband control:
- Brightness Analysis: Calculates average brightness of each frame
- Deadband Check: If brightness is within deadband zone, skip adjustments (prevents oscillation)
- Error Calculation: Compares to target brightness (with compensation)
- Ramping Priority:
- When too bright: Decreases exposure first, then gain
- When too dark: Increases exposure first (up to max), then gain
- Smooth Ramping: Changes are gradual based on ramp-rate setting
Typical Behavior
- Daytime: Fast shutter (low exposure), high gain for noise reduction
- Sunset/Dusk: Gradually increases exposure time as light fades
- Night: Maximum exposure time, minimum gain
CSV Log Format
When logging is enabled, the filter creates a CSV file with:
Frame,Time_s,Brightness,Exposure_ms,Gain,Target_Brightness
0,0.000,145.32,0.850,52,128.00
1,0.033,143.21,0.851,52,128.00
2,0.067,142.15,0.853,52,128.00
...
Camera Property Control
The filter finds and controls the upstream idsueyesrc element using the camera-element property. It sets:
- exposure: Exposure time in milliseconds
- gain: Master gain (0-100 range)
Ensure your camera source is named and the name matches the camera-element property.
Configuration Reference
Ramp Rates
| Rate | Multiplier | Step Size | Best For |
|---|---|---|---|
| VSlow | 0.5x | 5% per update | Dawn/dusk time-lapse (recommended) |
| Slow | 1.0x | 10% per update | Gradual sunset/sunrise over hours |
| Medium | 2.0x | 20% per update | Normal time-lapse scenarios |
| Fast | 4.0x | 40% per update | Faster light changes, clouds passing |
| VFast | 8.0x | 80% per update | Quick adaptation, testing |
Note: The base ramping rate is 10% of the delta between current and target values, multiplied by the ramp rate setting.
Update Intervals
| Interval | Updates/sec | Best For |
|---|---|---|
| 100ms | 10 Hz | Fast-changing scenes (clouds, indoor) |
| 500ms | 2 Hz | Moderate changes |
| 1000ms | 1 Hz | Dawn/dusk time-lapse (recommended) |
| 2000ms | 0.5 Hz | Very slow lighting changes |
| 5000ms | 0.2 Hz | Extremely slow changes |
Important: At high frame rates (50fps), avoid very short update intervals (< 500ms) to prevent oscillation and flickering.
Brightness Smoothing
The brightness-smoothing property uses Exponential Moving Average (EMA) to filter out transient brightness changes from moving objects:
smoothed_brightness = (alpha × current_brightness) + ((1 - alpha) × previous_smoothed)
| Value | Behavior | Best For |
|---|---|---|
| 0.05 | Very heavy smoothing | High traffic scenes |
| 0.1 | Heavy smoothing (default) | Time-lapse with moving objects |
| 0.3 | Moderate smoothing | Some filtering needed |
| 0.5 | Light smoothing | Quick response |
| 1.0 | No smoothing | Instant response to changes |
Effect: With brightness-smoothing=0.1, the algorithm effectively averages brightness over ~10 frames, filtering out cars, people, and birds while still tracking slow lighting trends.
Brightness Deadband
The brightness-deadband property creates a tolerance zone around the target brightness where no adjustments are made. This prevents oscillation caused by continuous micro-adjustments.
How it works:
- When brightness is within ±deadband of target, no changes are made
- When brightness exceeds the deadband, normal adjustments resume
- Allows fast corrections when needed, prevents hunting when stable
| Value | Behavior | Best For |
|---|---|---|
| 0.0 | No deadband (disabled) | Maximum responsiveness (may oscillate) |
| 5.0 | Narrow deadband | Slow update rates (>500ms) |
| 10.0 | Standard deadband (default) | Fast update rates (10-100ms), prevents oscillation |
| 20.0 | Wide deadband | Very stable, less responsive |
Example:
- With
target-brightness=128andbrightness-deadband=10.0 - No adjustments when brightness is between 118-138
- Adjustments resume when brightness < 118 or > 138
Important: Higher deadband = more stability but less precision. Lower deadband = more precision but potential oscillation at fast update rates.
Tips for Best Results
Dawn/Dusk Time-Lapse (Recommended Configuration)
ramp-rate: vslow (5% steps - very gradual)
update-interval: 1000 (1 second between updates)
brightness-smoothing: 0.1 (filter moving objects)
brightness-deadband: 10.0 (prevent oscillation)
exposure-min: 0.85 (or camera minimum)
exposure-max: 1.24 (or 1/framerate)
gain-min: 0 (cleanest image)
gain-max: 52 (or camera limit)
target-brightness: 128
Why these settings:
vslowramp rate prevents visible exposure jumps- 1000ms update interval allows camera hardware to settle
- Brightness smoothing filters transient changes (cars, people)
- Results in smooth, flicker-free time-lapse
Fast Changing Conditions (with Fast Update Rates)
ramp-rate: fast or vfast
update-interval: 10-100 (very fast updates)
brightness-smoothing: 0.3-1.0 (more responsive)
brightness-deadband: 10.0-15.0 (ESSENTIAL to prevent oscillation)
compensation: Adjust to preference (-1.0 for darker, +1.0 for brighter)
Critical: When using fast update rates (10-100ms), brightness-deadband is ESSENTIAL to prevent oscillation. Without it, the algorithm will continuously overshoot and create flickering.
Maximum Image Quality
gain-max: 20-30 (lower max gain = less noise)
ramp-rate: slow or vslow (smoother transitions)
update-interval: 1000-2000
Avoiding Flickering and Oscillation
If you experience flickering or oscillation:
- Enable deadband (MOST IMPORTANT): Set
brightness-deadband=10.0or higher - Increase update-interval: Start with 1000ms for slow changes, or keep at 10-100ms with deadband for fast response
- Decrease ramp-rate: Use
vsloworslow - Enable brightness-smoothing: Set to 0.1 or lower
The New Solution: With the brightness-deadband parameter, you can now use fast update rates (10ms) with fast ramp rates without oscillation! The deadband creates a stable zone that prevents continuous micro-adjustments.
Troubleshooting
Filter not adjusting exposure:
- Verify
camera-elementproperty matches your camera source name - Check that camera allows runtime exposure/gain changes
- Ensure
enabled=trueis set
Flickering or oscillating exposure:
- Primary cause: No deadband zone at fast update rates
- Solution: Set
brightness-deadband=10.0(or higher) - Alternative: Increase
update-intervalto 1000ms - Also try: Set
ramp-rate=vslowandbrightness-smoothing=0.1 - New capability: With deadband enabled, you CAN use fast update intervals (10-100ms) for rapid response without oscillation!
Changes too fast/slow:
- Adjust
ramp-rateproperty - Modify
update-interval(higher = slower convergence) - Check
exposure-min/exposure-maxrange is appropriate
Brightness oscillates with moving objects:
- Enable
brightness-smoothing=0.1to filter transients - Lower values (0.05) provide even more smoothing
- This filters cars, people, birds while tracking lighting trends
Brightness not reaching target:
- Increase
gain-maxto allow more gain - Increase
exposure-maxif not motion-limited - Adjust
target-brightnessor usecompensation
Log file not created:
- Check file path is writable
- Verify
log-fileproperty is set before starting pipeline
Comparison to YASS
| Feature | YASS (CHDK) | Intervalometer (GStreamer) |
|---|---|---|
| Platform | Canon cameras with CHDK | IDS uEye cameras |
| Control | Shutter speed + ISO | Exposure time + Gain |
| Integration | Standalone Lua script | GStreamer pipeline element |
| Real-time | Script-based intervals | Frame-by-frame analysis |
| Logging | CSV to SD card | CSV to filesystem |
Technical Notes
Flickering Fix (2025)
The original implementation had a critical bug where exposure ramping was not actually implemented - the code would instantly jump to target values instead of gradually ramping. This caused visible flickering, especially with short update intervals.
Fixed in gstintervalometer.c:688-716:
- Implemented proper gradual ramping using the
ramp_stepvariable - Each update now applies a percentage of the delta (not instant jumps)
- Formula:
current_exposure += (target_exposure - current_exposure) × ramp_step
Exposure Range Query Fix
The original implementation used GObject property specs to query exposure limits, which returned incorrect values (0.0 min, DBL_MAX max). This has been fixed to use the IDS uEye SDK directly:
Changes made:
- Added IDS SDK header include and camera handle support
- Added
hcamproperty toidsueyesrcto expose camera handle - Use
is_Exposure(IS_EXPOSURE_CMD_GET_EXPOSURE_RANGE)for proper hardware limits - Result: Proper min/max values (e.g., [0.019 - 19.943] ms) from camera
Brightness Smoothing
Added Exponential Moving Average (EMA) filtering to handle transient brightness changes from moving objects (cars, people, birds). This prevents exposure oscillation while maintaining responsiveness to actual lighting changes.
Brightness Deadband (Anti-Oscillation)
Added deadband control to prevent continuous micro-adjustments that cause oscillation. When brightness is within the deadband zone (default ±10 units), no adjustments are made. This allows:
- Fast update rates (10-100ms) without oscillation
- Rapid response when changes exceed deadband
- Stable operation at any ramp rate
Implementation in gstintervalometer.c:698-707:
- Checks absolute error against deadband before making adjustments
- Skips exposure/gain changes when within tolerance
- Allows full-speed corrections when brightness significantly deviates
License
This filter is part of gst-plugins-vision and released under the GNU Library General Public License (LGPL).
Inspired by YASS (Yet Another Sunset Script) by waterwingz, based on work by Fbonomi and soulf2, released under GPL.
See Also
- YASS Documentation - Original CHDK script that inspired this filter
- idsueyesrc - IDS uEye camera source element