Understanding Results
All VitalLens clients (Python, JavaScript, iOS, Android) and the Direct API return results with the same structure and the same keys. This page explains that structure, when each value is available, and how to use the confidence scores. Details that differ between clients, such as type names, are in each client's API reference.
Not a Medical Device
VitalLens is NOT a medical device. The estimates provided are for general wellness and informational purposes only.
Result Structure
A result describes one face. The Python client returns a list with one result per detected face; the JavaScript, iOS and Android clients process a single face.
{
"face": {
"coordinates": [[247, 52, 444, 332], ...],
"confidence": [0.6115, 0.9207, 0.9183, ...],
"note": "Face detection coordinates..."
},
"vitals": {
"heart_rate": {
"value": 60.21,
"unit": "bpm",
"confidence": 0.9205,
"note": "Global estimate of Heart Rate..."
},
"hrv_sdnn": {
"value": 53.79,
"unit": "ms",
"confidence": 0.8712,
"note": "Global estimate of Heart Rate Variability (SDNN)..."
},
...
},
"waveforms": {
"ppg_waveform": {
"data": [0.12, 0.15, 0.18, ...],
"unit": "unitless",
"confidence": [0.99, 0.99, ...],
"note": "..."
},
...
},
"message": "The provided values are estimates..."
}
| Field | Contents |
|---|---|
face |
Per-frame face coordinates [x0, y0, x1, y1] and the confidence that a face is present. |
vitals |
One entry per vital sign (see the keys below), each with a single value, its unit, a confidence between 0 and 1, and a note. |
waveforms |
The continuous signals the vitals are derived from: data and confidence per frame, plus unit and note. |
message |
A reminder that the values are estimates. |
Streams and Files
- Video files give one result for the whole video. Each vital is estimated from all of it.
- Live streams give results continuously. Each vital is estimated from a window of the most recent data (see the table below), so the values follow changes over time.
Availability
A vital is only present in the result when the model supports it and enough video has been processed. Otherwise its key is missing or its value is null.
| Vital Sign | Key | Unit | Models | Minimum Duration | Recommended Duration | Window in Streams |
|---|---|---|---|---|---|---|
| PPG Waveform | ppg_waveform |
unitless | All | – | – | – |
| Respiratory Waveform | respiratory_waveform |
unitless | VitalLens 1.0+ | – | – | – |
| Heart Rate | heart_rate |
bpm | All | 5 s | 10+ s | Last 10 s |
| Respiratory Rate | respiratory_rate |
bpm (breaths per minute) | VitalLens 1.0+ | 10 s | 15+ s | Last 30 s |
| HRV (SDNN) | hrv_sdnn |
ms | VitalLens 2.0 | 20 s | 30+ s | Last 120 s |
| HRV (RMSSD) | hrv_rmssd |
ms | VitalLens 2.0 | 20 s | 30+ s | Last 60 s |
| HRV (LF/HF) | hrv_lfhf |
ratio | VitalLens 2.0 | 120 s | 180+ s | Last 120 s |
"All" includes the simple methods that run on the device without the API (pos, chrom, g in the Python and JavaScript clients). They estimate the PPG waveform and heart rate only. See Supported Vital Signs for what each metric means and why HRV needs longer recordings.
Confidence
Every value comes with a confidence between 0 and 1. A vital can also be returned with a low confidence, or as null, when the duration is sufficient but the video quality is not, for example because of motion or poor light.
As a guide, the VitalLens apps show heart rate and respiratory rate from a confidence of 0.8, and show HRV only when it and the heart rate both reach 0.8. Consider applying a similar rule: an HRV value next to a heart rate with low confidence is not reliable.
For how to record video that gives accurate results, see Accuracy & Guidelines.