Skip to Content
PlatformsLinux (Headless Python)

Linux (Headless Python SDK)

This SDK is headless. There is no embedded UI or camera handling. You must capture frames, submit them to the SDK, and provide your own user guidance.

This SDK targets arm64 Linux and provides a Python wrapper over the headless C SDK built with ctypes. It has feature parity with the C API.

Download

See the Customer Portal for SDK downloads.

See system requirements for runtime dependencies.

Install

Unzip the package and add it to PYTHONPATH, or copy shenai_sdk/ into your project:

export PYTHONPATH=/path/to/shenai-sdk-python-linux-arm64

Quickstart (minimal flow)

from shenai_sdk import ( ShenaiSDK, MeasurementPreset, PrecisionMode, OperatingMode, MeasurementState, ) with ShenaiSDK(api_key="YOUR_API_KEY_OR_TOKEN", offline=False) as sdk: print("Version:", sdk.get_version()) sdk.precision_mode = PrecisionMode.STRICT sdk.measurement_preset = MeasurementPreset.ONE_MINUTE_ALL_METRICS sdk.operating_mode = OperatingMode.MEASURE while True: frame = get_next_frame() # BGR24 bytes if frame is None: break sdk.submit_frame(frame, width=1280, height=720) state = sdk.get_measurement_state() if state in (MeasurementState.FINISHED, MeasurementState.FAILED): break results = sdk.get_measurement_results() if results: print("HR:", results.heart_rate_bpm) sdk.destroy_runtime()

Replace get_next_frame() with your camera or video capture pipeline.

Library discovery

The wrapper searches for libShenaiSDK.so in this order:

  1. lib_path argument in ShenaiSDK(...)
  2. SHENAI_SDK_LIB environment variable (file or directory)
  3. SHENAI_SDK_DIR environment variable (directory)
  4. shenai_sdk/lib/ (packaged alongside the module)
  5. ctypes.util.find_library("ShenaiSDK")
export SHENAI_SDK_LIB=/path/to/libShenaiSDK.so

Initialization and configuration

The Python wrapper mirrors the C API:

from shenai_sdk import ( ShenaiSDK, CustomMeasurementConfig, Metric, PrecisionMode, MeasurementPreset, ) sdk = ShenaiSDK(api_key="YOUR_API_KEY_OR_TOKEN", offline=True) sdk.precision_mode = PrecisionMode.RELAXED sdk.measurement_preset = MeasurementPreset.ONE_MINUTE_ALL_METRICS sdk.apply_sdk_config(load_config_json()) print(sdk.get_sdk_config_string()) cfg = CustomMeasurementConfig(duration_seconds=30.0, instant_metrics=[Metric.HEART_RATE]) sdk.set_custom_measurement_config(cfg) cfg = sdk.get_custom_measurement_config()

Frame input

submit_frame accepts BGR frames:

  • pixel_format: PixelFormat.BGR24 (8-bit, 3 channels, B-G-R order)
  • stride_bytes: defaults to width * 3
  • timestamp_ns: optional, default 0
from shenai_sdk import PixelFormat sdk.submit_frame(frame, width=width, height=height, pixel_format=PixelFormat.BGR24)

Provide a fresh, stable buffer per frame. Do not reuse or overwrite the same memory for subsequent frames after submission. Keep the buffer alive until the SDK finishes processing the frame; use a new buffer per frame or a ring buffer and only reuse slots after processing completes.

Operating mode and state

from shenai_sdk import OperatingMode sdk.operating_mode = OperatingMode.POSITIONING sdk.operating_mode = OperatingMode.MEASURE mode = sdk.operating_mode state = sdk.get_measurement_state() progress = sdk.get_progress_percent() face_state = sdk.get_face_state() bbox = sdk.get_face_bbox() pose = sdk.get_face_pose()

Realtime metrics and heartbeats

metrics = sdk.get_realtime_metrics(30.0) hr_10s = sdk.get_heart_rate_10s() hr_4s = sdk.get_heart_rate_4s() heartbeats = sdk.get_realtime_heartbeats(30.0)

Results, history, and health risks

results = sdk.get_measurement_results() results_with_hb = sdk.get_measurement_results_with_heartbeats() history = sdk.get_measurement_results_history() risks = sdk.get_health_risks()

MeasurementResults includes optional fields for blood pressure confidence, weight, and height in addition to the standard metrics.

Raw data, reports, and FHIR

sdk.recording_enabled = True signal_quality = sdk.get_current_signal_quality_metric() bad_signal_seconds = sdk.get_total_bad_signal_seconds() png = sdk.get_face_texture_png() quality_png = sdk.get_signal_quality_map_png() meta_png = sdk.get_meta_prediction_image_png() ppg = sdk.get_full_ppg_signal() sdk.request_measurement_results_pdf_url() pdf_url = sdk.get_measurement_results_pdf_url() sdk.request_measurement_results_pdf_bytes() pdf_bytes = sdk.get_measurement_results_pdf_bytes() fhir_json = sdk.get_result_as_fhir_observation()

Metadata and debug helpers

version = sdk.get_version() initialized = sdk.is_initialized plan = sdk.get_pricing_plan() trace_id = sdk.get_trace_id() measurement_id = sdk.get_measurement_id()

Cleanup

Call close() (or use the context manager) to deinitialize, and call destroy_runtime() once after the final deinitialize to tear down the SDK runtime:

sdk.close() sdk.destroy_runtime()