The Embedded Stream Processor reads one YAML file per stream, passed as the argument of the sfe_stream_processor executable, and watches it for changes: edits to most sections apply without a restart, while changes to solvers, license and log need one. When the device is registered in Face Matcher, Station manages the processing sections for you (see What Station overrides); you still set connection on the device. The former on-device settings-server web UI is no longer part of the product since version 3.0.0.
./sfe_stream_processor /path/to/settings.yaml
connection
MQTT connection to the broker. With Face Matcher, follow Connect to Face Matcher for the values.
| Key | Type | Default | Description |
|---|
broker_address | string | 127.0.0.1 | IP address or hostname of the MQTT broker. Face Matcher host for edge streams; 127.0.0.1 with a local broker for standalone use |
broker_port | int | 1883 | 1883 for plain MQTT, 8883 when tls_enable is true |
client_id | string | random UUID | Identifies this stream on the broker. Must be unique per stream and, with Face Matcher, equal to the Station Client ID |
topic | string | edge-stream | Root topic; all topics become <topic>/<client_id>/.... Keep edge-stream for Face Matcher |
keep_alive | seconds | 60 | Maximum interval between MQTT packets sent by the client |
timeout | seconds | 10 | How long a connection attempt waits before failing |
tls_enable | bool | false | Encrypts the MQTT session. Strongly recommended on any network you do not control |
username, password | string | — | Broker credentials; the Face Matcher broker rejects anonymous logins |
face_detection
| Key | Type | Default | Description |
|---|
detection_threshold | 0.0–1.0 | 0.06 | Detections below this confidence are dropped before tracking. 0.06 is the recommended value |
max_detections | int | 10 | Maximum faces detected, tracked and processed per frame; lower it to save processing time |
order_by | enum | DetectionConfidence | Processing order when more faces than max_detections are present: DetectionConfidence or FaceSize |
min_face_size | number or null | null | Smallest face to process: pixels if greater than 1.0, otherwise a fraction of the frame width. null disables the filter |
max_face_size | number or null | null | Largest face to process, same units |
tracking
| Key | Type | Default | Description |
|---|
threshold | 0.0–1.0 | 0.1 | Minimum detection confidence for a face to stay in a tracklet and reach landmarks and extraction. Keep it below detection_threshold's Station equivalent |
stability | 0.0–1.0 | 0.85 | Kalman-filter association strictness. Low values let tracking jump between detections; high values create more tracklets |
max_frames_lost | int | 25 | Frames a lost face is kept before its tracklet is closed and reported as lost |
| Key | Type | Default | Description |
|---|
enable | bool | true | Extract a face template on the device and include it in FrameData. With false, no template is sent and the server extracts one from the crop; on-device identification then cannot run |
The extraction algorithm is chosen by the solver in solvers.face_extraction (fast, balanced or accurate_mask). Templates from different algorithms are not compatible with each other.
face_liveness_passive
| Key | Type | Default | Description |
|---|
enable | bool | false | Compute a passive liveness score on the device and include it in FrameData |
strategy | enum | OnEachExtractedFace | OnEachExtractedFace scores every face with a template; OnEachIdentifiedFace only faces that matched the on-device watchlist |
conditions | list | see below | Minimum image quality for a trustworthy score. Each entry has parameter, and lower_threshold and/or upper_threshold. When a condition fails, no score is computed and the FrameData reports conditions_met: false |
The liveness mode (Distant for walk-through and access-control distances, Nearby for selfie distances) is chosen by the solver in solvers.face_liveness_passive. Recommended conditions and decision thresholds per mode:
Condition parameter | Distant | Nearby |
|---|
FaceSize (pixels between eyes) | ≥ 30 | ≥ 60 |
FaceRelativeArea | ≥ 0.009 | ≥ 0.25 |
FaceRelativeAreaInImage | ≥ 0.9 | — |
YawAngle (degrees) | −20 to 20 | −20 to 20 |
PitchAngle (degrees) | −20 to 20 | −20 to 20 |
Sharpness | ≥ 0.6 | ≥ 0.7 |
Brightness | — | 0.11 to 0.75 |
Contrast | — | 0.25 to 0.8 |
| Recommended score threshold | 0.842 | 0.913 |
Only one liveness mode runs on a device at a time. The condition types available on the device are FaceSize, FaceRelativeArea, FaceRelativeAreaInImage, YawAngle, PitchAngle, RollAngle, Sharpness, Brightness and Contrast. Server-side liveness and its thresholds are described on Liveness.
face_identification
| Key | Type | Default | Description |
|---|
enable | bool | true | Match each extracted template against the on-device database and include candidates in FrameData |
storage | path | package-specific | File that holds the on-device database of templates and metadata (for example /emmc/plugin/Inno/records_storage.bin on cameras) |
candidate_count | int | 1 | Maximum candidates returned per face |
threshold | 0.0–1.0 | 0.40 | Minimum matching score for a candidate. 0.40 is the recommended value and corresponds to the platform default of 40 |
With Face Matcher, the database is filled by watchlist synchronization (guide); standalone, you fill it through the user and db topics.
messaging
| Key | Type | Default | Description |
|---|
enable | bool | true | Publish FrameData messages |
format | enum | Protobuf | Serialization: Protobuf (required for Face Matcher), Json or Yaml |
strategy | enum | OnNewAndInterval | The only supported strategy: publish when a new face appears and at least every interval |
interval | milliseconds | 250 | Maximum time between messages while faces are tracked |
allow_empty_messages | bool | false | Also publish when no face is detected or tracked. Debugging only |
crop
| Key | Type | Default | Description |
|---|
enable | bool | true | Include a crop of each face in FrameData. Required when the server extracts templates or runs liveness |
size_extension | 0–5 | 2 | Crop size as a multiple of the detection box, centred on the face. Server-side template extraction needs 2; server-side passive liveness needs 5 |
max_size | pixels | 50.0 | Maximum face size inside the crop; the crop is scaled down to respect it |
image_format | enum | Raw | Raw (BGR), Jpeg or Png |
image_quality | 0.0–1.0 | 0.85 | Compression quality for Jpeg; 1.0 is lossless-quality |
full_frame
| Key | Type | Default | Description |
|---|
enable | bool | false | Include the whole frame in FrameData. Costs a lot of bandwidth — debugging only |
image_width, image_height | pixels or null | null | Resize the frame before sending; null keeps the source resolution |
image_format | enum | Raw | Raw, Jpeg or Png |
image_quality | 0.0–1.0 | 0.85 | Compression quality |
solvers
Solvers are the accelerator-specific binaries that run each neural network. Each entry takes a solver path (relative to the working directory or absolute) and a parameters list of name/value pairs. Changing this section requires a restart. Solver files are named by task, algorithm and accelerator (for example face_detect_accurate_mask.onnxrt.solver, face_template_extract_balanced.ambarella.solver); use only the solvers shipped in your device package.
| Key | Description |
|---|
frame_input | Video source: the vendor camera solver on smart cameras, camera_input or gstreamer_input on AI boxes (parameters below) |
frame_output | Optional annotated output stream for debugging; null in production |
face_detection | Face detector |
face_landmarks | Landmark detector (0.25 or 0.50 model) |
face_extraction | Template extractor: fast, balanced or accurate_mask |
face_liveness_passive | Passive liveness: face_liveness_passive_distant or face_liveness_passive_nearby; null when disabled or not available on the accelerator |
Common solver parameters (ONNX Runtime on Jetson and x86): runtime_provider (cpu, cuda, tensorrt), intra_threads, inter_threads, execution_mode (parallel or sequential), device_id. TensorFlow Lite on NXP: tflite_solver.delegate (cpu, gpu, nnapi, vx), tflite_solver.num_threads, tflite_solver.vx_delegate.cache. Environment variables of the same name in upper case override the parameters. The full list per accelerator is in the Embedded Toolkit solvers documentation.
camera_input solver parameters (USB camera, used on NXP i.MX 8M Plus):
| Parameter | Type | Default | Description |
|---|
camera_index | u32 | 0 | Index of the Linux video device |
camera_width | u32 | 640 | Capture width |
camera_height | u32 | 480 | Capture height |
camera_fps | u32 | 5 | Capture frame rate |
camera_format | string | YUYV | Pixel format: MJPEG, YUYV, GRAY, RAWRGB or NV12 |
gstreamer_input solver parameters (file, RTSP or USB on Hailo and Jetson boxes):
| Parameter | Type | Description |
|---|
gst_pipeline | string | Complete GStreamer pipeline; when set it overrides every other parameter |
gst_width, gst_height | u32 | Resolution of the frames leaving the pipeline |
gst_video_device | string | Linux video device for the default pipeline, for example /dev/video1 |
gst_app_sink_name | string | Name of the app sink the solver attaches (normally left default) |
Pipeline rules and examples are on GStreamer input, which also shows how one box runs several streams by passing several settings files.
license
| Key | Type | Default | Description |
|---|
data | base64 string or null | null | License file content encoded with base64 -w0. With null, the device looks for iengine.lic on disk or the ILICENSE / ILICENSE_DATA environment variables. Station writes this key when you upload a license |
Changing the license requires a restart.
log
| Key | Type | Default | Description |
|---|
level | enum | Info | Off, Error, Warn, Info, Debug or Trace |
path | path or unset | unset (stderr) | Log file; on cameras typically /emmc/plugin/Inno/log/sfe_stream_processor.log |
Changing logging requires a restart. Devices also publish their log lines to the log MQTT topic (see MQTT API).
What Station overrides
When the device is a Face Matcher edge stream, Station pushes the following sections to the device; edit them in Station rather than on the device, otherwise your local change is overwritten. Station shows several values on a 0–10 000 or 0–100 scale where the device uses 0.0–1.0.
| Station section and field | Device key |
|---|
| General → Client ID | connection.client_id (must match; Station does not write the connection section) |
| Face processing → Order by, Confidence threshold, Min/Max face size, Max faces | face_detection.order_by, detection_threshold, min_face_size, max_face_size, max_detections |
| Face processing → Tracking threshold, Tracking stability, Maximum frames lost | tracking.threshold, stability, max_frames_lost |
| Face processing → Template generator resource = On Edge | face_extraction.enable: true (server resources set it to false) |
| Spoof detection → Distant/Nearby detector resource = On Edge, Spoof execution on edge | face_liveness_passive.enable, solvers.face_liveness_passive, face_liveness_passive.strategy |
| Watchlists for matching and synchronisation → Selected watchlists, Matching threshold | Device database contents (through the db topics) and face_identification.enable, face_identification.threshold |
| Messaging → Strategy, Interval, Allow empty messages | messaging.strategy, interval, allow_empty_messages |
| Logging → Log level | log.level |
| Send crop images → Image quality, Max size, Format | crop.enable, image_quality, max_size, image_format |
| Send full frame images → Image quality, Resolution, Format | full_frame.enable, image_quality, image_width/image_height, image_format |
| License → upload | license.data |
Annotated example
A complete file for an AI box reading an RTSP camera on the CPU with ONNX Runtime solvers. Camera packages ship their own example with vendor solver paths.
connection:
broker_address: 192.0.2.10
broker_port: 1883
client_id: lobby-cam-1
topic: edge-stream
keep_alive: 60
timeout: 10
tls_enable: false
username: <MQTT__Username>
password: <MQTT__Password>
face_detection:
detection_threshold: 0.06
max_detections: 10
order_by: DetectionConfidence
min_face_size: null
max_face_size: null
tracking:
threshold: 0.1
stability: 0.85
max_frames_lost: 25
face_extraction:
enable: true
face_liveness_passive:
enable: false
strategy: OnEachExtractedFace
conditions:
- parameter: FaceSize
lower_threshold: 30.0
- parameter: FaceRelativeArea
lower_threshold: 0.009
- parameter: FaceRelativeAreaInImage
lower_threshold: 0.9
- parameter: YawAngle
lower_threshold: -20.0
upper_threshold: 20.0
- parameter: PitchAngle
lower_threshold: -20.0
upper_threshold: 20.0
- parameter: Sharpness
lower_threshold: 0.6
face_identification:
enable: true
storage: ./records_storage.bin
candidate_count: 1
threshold: 0.40
messaging:
enable: true
format: Protobuf
strategy: OnNewAndInterval
interval: 250
allow_empty_messages: false
crop:
enable: true
size_extension: 2
max_size: 50.0
image_format: Jpeg
image_quality: 0.85
full_frame:
enable: false
image_width: null
image_height: null
image_format: Jpeg
image_quality: 0.85
solvers:
frame_input:
solver: ./solver/gstreamer_input.cpu.solver
parameters:
- name: gst_pipeline
value: "rtspsrc location=rtsp://user:pass@192.0.2.40:554/stream latency=30 ! rtph264depay ! h264parse ! avdec_h264 ! videorate ! videoconvert ! videoscale ! video/x-raw,format=BGR,framerate=10/1,width=1280,height=720"
- name: gst_width
value: 1280
- name: gst_height
value: 720
frame_output:
solver: null
parameters: []
face_detection:
solver: ./solver/face_detect_accurate_mask.onnxrt.solver
parameters:
- name: runtime_provider
value: cpu
- name: intra_threads
value: '6'
- name: inter_threads
value: '1'
face_landmarks:
solver: ./solver/face_landmarks_0.25.onnxrt.solver
parameters:
- name: runtime_provider
value: cpu
face_extraction:
solver: ./solver/face_template_extract_accurate_mask.onnxrt.solver
parameters:
- name: runtime_provider
value: cpu
face_liveness_passive:
solver: ./solver/face_liveness_passive_distant.onnxrt.solver
parameters:
- name: runtime_provider
value: cpu
license:
data: null
log:
level: Info
path: ./sfe_stream_processor.log