Camera Control API

Camera Control Client

Comprehensive camera pipeline control: ISP, encoder, RTSP, OSD, stream management, profiles, capabilities, and hardware status.

class neoruntime_ipc_sdk.camera.CameraClient(endpoint=None)[source]

Bases: GrpcClient

Camera pipeline control client.

Usage:

cam = CameraClient()

# ISP
cam.set_isp(brightness=60, contrast=50)
isp = cam.get_isp()

# Encoder
cam.set_encoder("main", bitrate_bps=8_000_000)

# RTSP
cam.set_rtsp_enabled(True)

# Streams
streams = cam.get_stream_status()
cam.add_stream("third", 1920, 1080, 30, "h264", 4_000_000, 30)

# Profiles
cam.switch_profile("night")
cam.backup_profile()

# Capabilities
caps = cam.get_capabilities()
set_isp(config=None, **kwargs)[source]

Update ISP image pipeline settings.

get_isp()[source]

Get current ISP configuration.

get_transform()[source]
set_transform(cfg)[source]
set_encoder(stream_name='main', bitrate_bps=0, framerate=0, gop=0)[source]

Dynamic encoder config (no restart).

reconfigure_encoder(stream_name, width=0, height=0, codec='', bitrate_bps=0, fps=0, gop=0)[source]

Full encoder reconfiguration (brief restart, ~100ms).

set_rtsp_enabled(enabled)[source]
set_osd(streams)[source]

Update OSD text and datetime overlays per stream.

Parameters:

streams (list[dict]) – list of dicts with keys: stream_name, text_overlays (list of dicts), datetime_overlays (list of dicts)

set_ai_overlay(enabled, show_label=True, show_confidence=True, line_thickness=2)[source]
set_imaging_mode(mode)[source]

Switch day/night imaging mode.

Parameters:

mode (str) – “day”, “infrared” or “auto” (light-sensor driven).

Returns: the resulting InfraredStatus.

get_infrared_status()[source]

Current day/night imaging state (mode, PWMs, light sensor).

set_infrared_settings(auto_follow=None, near_pwm=None, far_pwm=None, night_enter=None, day_enter=None)[source]

Update IR light settings; omitted fields (None) are left unchanged.

Parameters:
  • auto_follow (bool | None) – tie IR output to optical zoom ratio.

  • far_pwm (near_pwm /) – manual IR intensities (0-100).

  • day_enter (night_enter /) – light-sensor thresholds for auto mode.

clear_infrared_manual()[source]

Drop manual IR overrides and return to profile-driven output.

list_ir_presets()[source]

Saved IR-light profiles (per zoom ratio).

save_ir_preset(name, zoom_ratio, near_pwm, far_pwm)[source]

Save (or overwrite) an IR preset and return the new list.

delete_ir_preset(name)[source]

Delete an IR preset by name and return the remaining list.

get_privacy_mask()[source]

Current static + dynamic (AI) privacy-mask configuration.

set_privacy_mask(settings=None, *, color=None, blur_radius=None, enabled=None, regions=None, dpm_enabled=None, dpm_labels=None, dpm_mode=None, dpm_color=None)[source]

Update privacy-mask configuration with merge semantics.

Only the fields given as arguments are changed; everything else (including existing regions) is read back from the device and preserved, so partial updates never wipe masks.

Parameters:
  • settings (PrivacyMaskSettings | None) – full PrivacyMaskSettings to apply wholesale (optional).

  • color (int | None) – 0x00RRGGBB fill color (used when blur_radius=0).

  • blur_radius (int | None) – pixelation block size 2-64; 0 = solid color.

  • enabled (bool | None) – global static-mask on/off.

  • regions (list[dict] | None) – list of {id, name, enabled, points_x, points_y} with normalized polygon coordinates (up to 8 points).

  • dpm_* – dynamic (AI) privacy-mask options.

get_osd()[source]

Read back OSD overlay config, shaped like set_osd() input.

Returns: list of {stream_name, text_overlays, datetime_overlays, image_overlays}; each overlay is a plain dict of its proto fields, so the result can be edited and fed straight back into set_osd().

get_config_field(field_path)[source]

Read one camera-daemon config field by dotted path.

Parameters:

field_path (str) – e.g. “frontend.hailort.use-hailort-service”.

Returns: the current value encoded as a string.

set_config_field(field_path, value)[source]

Write one camera-daemon config field by dotted path.

Parameters:
  • field_path (str) – dotted config path.

  • value – value encoded as a string (e.g. “true”, “42”, “1.5”); non-str values are converted with str().

get_stream_status()[source]
add_stream(stream_id, width, height, fps, codec='h264', bitrate=4000000, gop=30)[source]
remove_stream(stream_name)[source]
reconfigure_pipeline(streams)[source]
get_profile()[source]
list_profiles()[source]

Returns (profile_names, current_profile).

switch_profile(name)[source]
backup_profile(path='')[source]
get_sensor_info(sensor_index=0)[source]
get_capabilities()[source]
get_hardware_status()[source]
set_led_duty(led_id, duty_percent)[source]
get_led_duty(led_id)[source]
set_ircut(mode)[source]

Set IR-cut filter. mode: 0=day, 1=night. Returns current mode.

get_ircut()[source]
mcu_raw_request(cmd, payload=b'')[source]
set_fan(enable)[source]
get_fan()[source]
set_heat(enable)[source]
get_heat()[source]
set_radar(enable)[source]
get_radar()[source]
set_alarm_out(channel, enable)[source]
get_alarm_out(channel)[source]
get_alarm_outputs()[source]
rs485_init(baudrate=9600, config='8N1')[source]
rs485_deinit()[source]
rs485_tx(data)[source]

CameraClient

class neoruntime_ipc_sdk.CameraClient(endpoint=None)[source]

Bases: GrpcClient

Camera pipeline control client.

Usage:

cam = CameraClient()

# ISP
cam.set_isp(brightness=60, contrast=50)
isp = cam.get_isp()

# Encoder
cam.set_encoder("main", bitrate_bps=8_000_000)

# RTSP
cam.set_rtsp_enabled(True)

# Streams
streams = cam.get_stream_status()
cam.add_stream("third", 1920, 1080, 30, "h264", 4_000_000, 30)

# Profiles
cam.switch_profile("night")
cam.backup_profile()

# Capabilities
caps = cam.get_capabilities()
set_isp(config=None, **kwargs)[source]

Update ISP image pipeline settings.

get_isp()[source]

Get current ISP configuration.

get_transform()[source]
set_transform(cfg)[source]
set_encoder(stream_name='main', bitrate_bps=0, framerate=0, gop=0)[source]

Dynamic encoder config (no restart).

reconfigure_encoder(stream_name, width=0, height=0, codec='', bitrate_bps=0, fps=0, gop=0)[source]

Full encoder reconfiguration (brief restart, ~100ms).

set_rtsp_enabled(enabled)[source]
set_osd(streams)[source]

Update OSD text and datetime overlays per stream.

Parameters:

streams (list[dict]) – list of dicts with keys: stream_name, text_overlays (list of dicts), datetime_overlays (list of dicts)

set_ai_overlay(enabled, show_label=True, show_confidence=True, line_thickness=2)[source]
set_imaging_mode(mode)[source]

Switch day/night imaging mode.

Parameters:

mode (str) – “day”, “infrared” or “auto” (light-sensor driven).

Returns: the resulting InfraredStatus.

get_infrared_status()[source]

Current day/night imaging state (mode, PWMs, light sensor).

set_infrared_settings(auto_follow=None, near_pwm=None, far_pwm=None, night_enter=None, day_enter=None)[source]

Update IR light settings; omitted fields (None) are left unchanged.

Parameters:
  • auto_follow (bool | None) – tie IR output to optical zoom ratio.

  • far_pwm (near_pwm /) – manual IR intensities (0-100).

  • day_enter (night_enter /) – light-sensor thresholds for auto mode.

clear_infrared_manual()[source]

Drop manual IR overrides and return to profile-driven output.

list_ir_presets()[source]

Saved IR-light profiles (per zoom ratio).

save_ir_preset(name, zoom_ratio, near_pwm, far_pwm)[source]

Save (or overwrite) an IR preset and return the new list.

delete_ir_preset(name)[source]

Delete an IR preset by name and return the remaining list.

get_privacy_mask()[source]

Current static + dynamic (AI) privacy-mask configuration.

set_privacy_mask(settings=None, *, color=None, blur_radius=None, enabled=None, regions=None, dpm_enabled=None, dpm_labels=None, dpm_mode=None, dpm_color=None)[source]

Update privacy-mask configuration with merge semantics.

Only the fields given as arguments are changed; everything else (including existing regions) is read back from the device and preserved, so partial updates never wipe masks.

Parameters:
  • settings (PrivacyMaskSettings | None) – full PrivacyMaskSettings to apply wholesale (optional).

  • color (int | None) – 0x00RRGGBB fill color (used when blur_radius=0).

  • blur_radius (int | None) – pixelation block size 2-64; 0 = solid color.

  • enabled (bool | None) – global static-mask on/off.

  • regions (list[dict] | None) – list of {id, name, enabled, points_x, points_y} with normalized polygon coordinates (up to 8 points).

  • dpm_* – dynamic (AI) privacy-mask options.

get_osd()[source]

Read back OSD overlay config, shaped like set_osd() input.

Returns: list of {stream_name, text_overlays, datetime_overlays, image_overlays}; each overlay is a plain dict of its proto fields, so the result can be edited and fed straight back into set_osd().

get_config_field(field_path)[source]

Read one camera-daemon config field by dotted path.

Parameters:

field_path (str) – e.g. “frontend.hailort.use-hailort-service”.

Returns: the current value encoded as a string.

set_config_field(field_path, value)[source]

Write one camera-daemon config field by dotted path.

Parameters:
  • field_path (str) – dotted config path.

  • value – value encoded as a string (e.g. “true”, “42”, “1.5”); non-str values are converted with str().

get_stream_status()[source]
add_stream(stream_id, width, height, fps, codec='h264', bitrate=4000000, gop=30)[source]
remove_stream(stream_name)[source]
reconfigure_pipeline(streams)[source]
get_profile()[source]
list_profiles()[source]

Returns (profile_names, current_profile).

switch_profile(name)[source]
backup_profile(path='')[source]
get_sensor_info(sensor_index=0)[source]
get_capabilities()[source]
get_hardware_status()[source]
set_led_duty(led_id, duty_percent)[source]
get_led_duty(led_id)[source]
set_ircut(mode)[source]

Set IR-cut filter. mode: 0=day, 1=night. Returns current mode.

get_ircut()[source]
mcu_raw_request(cmd, payload=b'')[source]
set_fan(enable)[source]
get_fan()[source]
set_heat(enable)[source]
get_heat()[source]
set_radar(enable)[source]
get_radar()[source]
set_alarm_out(channel, enable)[source]
get_alarm_out(channel)[source]
get_alarm_outputs()[source]
rs485_init(baudrate=9600, config='8N1')[source]
rs485_deinit()[source]
rs485_tx(data)[source]

Data Types

ISPConfig

class neoruntime_ipc_sdk.ISPConfig(brightness: 'int' = -1, contrast: 'int' = -1, saturation: 'int' = -1, sharpness: 'int' = -1, manual_mode: 'bool | None' = None, auto_exposure: 'bool | None' = None, backlight: 'int' = -1, exposure_time_us: 'int' = -1, gain: 'int' = -1, noise_reduction: 'int' = -1, wdr_value: 'int' = -1, powerline_freq: 'int' = -1, awb_index: 'int' = -1)[source]
brightness: int = -1
contrast: int = -1
saturation: int = -1
sharpness: int = -1
manual_mode: bool | None = None
auto_exposure: bool | None = None
backlight: int = -1
exposure_time_us: int = -1
gain: int = -1
noise_reduction: int = -1
wdr_value: int = -1
powerline_freq: int = -1
awb_index: int = -1
__init__(brightness=-1, contrast=-1, saturation=-1, sharpness=-1, manual_mode=None, auto_exposure=None, backlight=-1, exposure_time_us=-1, gain=-1, noise_reduction=-1, wdr_value=-1, powerline_freq=-1, awb_index=-1)

TransformConfig

class neoruntime_ipc_sdk.TransformConfig(rotation: 'int' = 0, flip: 'int' = 0, dewarp: 'bool' = False, grayscale: 'bool' = False)[source]
rotation: int = 0
flip: int = 0
dewarp: bool = False
grayscale: bool = False
__init__(rotation=0, flip=0, dewarp=False, grayscale=False)

Capabilities

class neoruntime_ipc_sdk.Capabilities(has_video: 'bool' = False, has_codec: 'bool' = False, has_led: 'bool' = False, has_sensor: 'bool' = False, has_mcu: 'bool' = False, has_env_ctrl: 'bool' = False, has_alarm: 'bool' = False, has_rs485: 'bool' = False, has_osd: 'bool' = False, has_draw: 'bool' = False, has_audio: 'bool' = False)[source]
has_video: bool = False
has_codec: bool = False
has_led: bool = False
has_sensor: bool = False
has_mcu: bool = False
has_env_ctrl: bool = False
has_alarm: bool = False
has_rs485: bool = False
has_osd: bool = False
has_draw: bool = False
has_audio: bool = False
__init__(has_video=False, has_codec=False, has_led=False, has_sensor=False, has_mcu=False, has_env_ctrl=False, has_alarm=False, has_rs485=False, has_osd=False, has_draw=False, has_audio=False)

SensorInfo

class neoruntime_ipc_sdk.SensorInfo(available: 'bool', sensor_model: 'str', i2c_bus: 'int', i2c_address: 'str', pixel_format: 'int')[source]
available: bool
sensor_model: str
i2c_bus: int
i2c_address: str
pixel_format: int
__init__(available, sensor_model, i2c_bus, i2c_address, pixel_format)

StreamStatus

class neoruntime_ipc_sdk.StreamStatus(stream_id: 'str', status: 'str', has_encoder: 'bool', codec: 'str', width: 'int', height: 'int', fps: 'int', bitrate_bps: 'int', gop: 'int')[source]
stream_id: str
status: str
has_encoder: bool
codec: str
width: int
height: int
fps: int
bitrate_bps: int
gop: int
__init__(stream_id, status, has_encoder, codec, width, height, fps, bitrate_bps, gop)

HardwareStatus

class neoruntime_ipc_sdk.HardwareStatus(light_sensor_mv: 'int', light_sensor_lux: 'int', mcu_temp_millic: 'int', ain_mv: 'int', mcu_version: 'str', white_light_duty: 'int', ir_led_duty: 'int', ircut_mode: 'int')[source]
light_sensor_mv: int
light_sensor_lux: int
mcu_temp_millic: int
ain_mv: int
mcu_version: str
white_light_duty: int
ir_led_duty: int
ircut_mode: int
__init__(light_sensor_mv, light_sensor_lux, mcu_temp_millic, ain_mv, mcu_version, white_light_duty, ir_led_duty, ircut_mode)

EnvStatus

class neoruntime_ipc_sdk.EnvStatus(enabled: 'bool')[source]
enabled: bool
__init__(enabled)

PipelineStreamConfig

class neoruntime_ipc_sdk.PipelineStreamConfig(stream_id: 'str', input_width: 'int' = 0, input_height: 'int' = 0, input_framerate: 'int' = 0, codec: 'str' = 'h264', encoder_width: 'int' = 0, encoder_height: 'int' = 0, encoder_framerate: 'int' = 0, encoder_bitrate: 'int' = 0, encoder_gop: 'int' = 0)[source]
stream_id: str
input_width: int = 0
input_height: int = 0
input_framerate: int = 0
codec: str = 'h264'
encoder_width: int = 0
encoder_height: int = 0
encoder_framerate: int = 0
encoder_bitrate: int = 0
encoder_gop: int = 0
__init__(stream_id, input_width=0, input_height=0, input_framerate=0, codec='h264', encoder_width=0, encoder_height=0, encoder_framerate=0, encoder_bitrate=0, encoder_gop=0)

EncoderReconfigResult

class neoruntime_ipc_sdk.EncoderReconfigResult(success: 'bool', message: 'str', interrupt_ms: 'int' = 0)[source]
success: bool
message: str
interrupt_ms: int = 0
__init__(success, message, interrupt_ms=0)

InfraredStatus

class neoruntime_ipc_sdk.InfraredStatus(mode, transition, output_source, auto_follow, follow_active, manual_override, degraded, requested_near_pwm, requested_far_pwm, applied_near_pwm, applied_far_pwm, zoom_ratio, active_profile, selected_mode, light_percent, light_mv, light_milli, light_valid, night_enter, day_enter)[source]

Day/night imaging state reported by the camera pipeline.

mode: str
transition: str
output_source: str
auto_follow: bool
follow_active: bool
manual_override: bool
degraded: bool
requested_near_pwm: int
requested_far_pwm: int
applied_near_pwm: int
applied_far_pwm: int
zoom_ratio: float
active_profile: str
selected_mode: str
light_percent: int
light_mv: int
light_milli: int
light_valid: bool
night_enter: int
day_enter: int
__init__(mode, transition, output_source, auto_follow, follow_active, manual_override, degraded, requested_near_pwm, requested_far_pwm, applied_near_pwm, applied_far_pwm, zoom_ratio, active_profile, selected_mode, light_percent, light_mv, light_milli, light_valid, night_enter, day_enter)

IrPreset

class neoruntime_ipc_sdk.IrPreset(name, zoom_ratio, near_pwm, far_pwm)[source]

Saved IR-light profile bound to a zoom ratio.

name: str
zoom_ratio: float
near_pwm: int
far_pwm: int
__init__(name, zoom_ratio, near_pwm, far_pwm)

PrivacyMaskSettings

class neoruntime_ipc_sdk.PrivacyMaskSettings(color, blur_radius, enabled, regions, dpm_enabled, dpm_labels, dpm_mode, dpm_color)[source]

Static and dynamic (AI) privacy-mask configuration.

regions is a list of dicts: {id, name, enabled, points_x, points_y} with normalized [0.0-1.0] polygon coordinates (up to 8 points).

color: int
blur_radius: int
enabled: bool
regions: list[dict]
dpm_enabled: bool
dpm_labels: str
dpm_mode: str
dpm_color: int
__init__(color, blur_radius, enabled, regions, dpm_enabled, dpm_labels, dpm_mode, dpm_color)

Usage Examples

ISP image adjustment

from neoruntime_ipc_sdk import CameraClient, ISPConfig

cam = CameraClient()

# Read the current ISP configuration
cfg = cam.get_isp()
print(f"brightness: {cfg.brightness}, contrast: {cfg.contrast}")

# Only set the fields you care about (-1 means "keep current")
cam.set_isp(ISPConfig(brightness=60, saturation=50))

# Or use keyword arguments
cam.set_isp(brightness=60, sharpness=128)

Image transform (flip / rotate / grayscale)

from neoruntime_ipc_sdk import CameraClient, TransformConfig

cam = CameraClient()

# Horizontal flip + 180° rotation + grayscale output
cam.set_transform(TransformConfig(rotation=180, flip=1, grayscale=True))

Infrared and night vision

from neoruntime_ipc_sdk import CameraClient

cam = CameraClient()

# Current day/night imaging status
status = cam.get_infrared_status()
print(status)

# Switch imaging mode ("auto" / "day" / "night", see daemon support)
cam.set_imaging_mode("night")

# Fine-tune IR LED brightness (PWM) manually
cam.set_infrared_settings(near_pwm=80, far_pwm=120)

# Save / list / delete IR presets by zoom ratio
cam.save_ir_preset("zoom_2x", zoom_ratio=2.0, near_pwm=60, far_pwm=90)
presets = cam.list_ir_presets()
cam.delete_ir_preset("zoom_2x")

Encoders and streams

from neoruntime_ipc_sdk import CameraClient, PipelineStreamConfig

cam = CameraClient()

# Stream status
for s in cam.get_stream_status():
    print(f"{s.stream_id}: {s.width}x{s.height}@{s.fps} {s.codec}")

# Adjust a stream's bitrate at runtime (no pipeline restart)
cam.set_encoder("main", bitrate_bps=6_000_000, gop=60)

# Structured reconfiguration (resolution/codec change; returns the
# interruption duration)
result = cam.reconfigure_encoder(
    "main", width=2560, height=1440, bitrate_bps=8_000_000,
)
print(f"success={result.success}, interrupted {result.interrupt_ms}ms")

# Add / remove streams
cam.add_stream("sub2", 704, 576, fps=15, codec="h265", bitrate=1_500_000)
cam.remove_stream("sub2")

Privacy mask

from neoruntime_ipc_sdk import CameraClient

cam = CameraClient()

# Enable static mask regions (normalized 0-1 coordinates)
cam.set_privacy_mask(
    enabled=True,
    color=0,
    blur_radius=21,
    regions=[
        {"id": 1, "x": 0.05, "y": 0.05, "w": 0.2, "h": 0.15},
        {"id": 2, "x": 0.7, "y": 0.7, "w": 0.25, "h": 0.2},
    ],
)

# Query the current settings
print(cam.get_privacy_mask())

Environment and peripherals

from neoruntime_ipc_sdk import CameraClient

cam = CameraClient()

# Light sensor / temperature and other hardware status
hw = cam.get_hardware_status()
print(f"{hw.light_sensor_lux} lux, MCU {hw.mcu_temp_millic/1000:.1f}°C")

# Fan / heater / radar
cam.set_fan(True)
cam.set_heat(False)
print(cam.get_radar())

# Alarm outputs
cam.set_alarm_out(0, True)
print(cam.get_alarm_outputs())

# RS485 passthrough
cam.rs485_init(baudrate=9600, config="8N1")
cam.rs485_tx(b"\x01\x02\x03")

Capability query

caps = cam.get_capabilities()
print(f"LED: {caps.has_led}, RS485: {caps.has_rs485}, audio: {caps.has_audio}")

Context manager

with CameraClient() as cam:
    print(cam.get_sensor_info())