HRV analysis with ppg-js
Analyze RMSSD, SDNN, frequency-domain HRV, nonlinear metrics, and the camera measurement noise floor.
HRV analysis
@sontakey/ppg-js/hrv works with interval numbers in milliseconds or { ibiMs, t } records. Beat times let the module handle gaps correctly.
import { hrv } from '@sontakey/ppg-js';
const report = hrv.analyzeHRV(beats, {
rmssdFloorMs: ppg.getMetrics().rmssdFloorMs,
});Modules and output
timeDomain: mean RR and HR, SDNN, RMSSD, lnRMSSD, NN50 and pNN50, minimum and maximum HR, triangular index, least-squares TINN, and RR range.frequencyDomain: Welch PSD on a 4 Hz linear resample using real beat times, LF/HF, normalized units, HF-peak respiration, and coherence. It refuses recordings with more than 20% gaps. VLF is available only for recordings of at least 5 minutes.nonlinear: Poincaré SD1 and SD2, sample entropy, and DFA alpha 1.stressIndex: Baevsky SI and its square root, the form reported by Kubios.ansIndices: experimental PNS and SNS z-scores against cited references.ultraShortRmssd: RMSSD over the last 60 seconds.lnRmssdBaseline: 7-day rolling mean, coefficient of variation, and smallest-worthwhile-change band.
Pass respirationRateBpm to frequency analysis. respirationInLf indicates when breathing below 9 breaths per minute has moved respiratory sinus arrhythmia into the LF band.
RMSSD and SDNN
Live rmssd and sdnn use the last 60 seconds of accepted beats. Both are zero when the quality gate fails.
The camera noise floor
rmssdFloorMs estimates how much RMSSD the pipeline's beat-timing noise would create on a perfectly regular pulse. It is estimated for each window and is accurate to roughly plus or minus 50%. Report it next to RMSSD rather than hiding the limit.
A camera measures pulse-rate variability. At rest it tracks heart-rate variability closely. Posture and temperature changes can make the two diverge.