实时心率估算器
NOTE
僅限网页 SDK 实时估算功能目前僅适用於网页版 SDK(JavaScript、React、Vue)。不适用於行動装置 SDK(iOS、Android、Flutter、React Native)。
概述
实时估算器在影片撷取過程中提供实时心率反馈,最快可在 3-5 秒內显示结果,无需等待完整的 30 秒扫描。這創造了更具吸引力的使用者體驗,並幫助使用者调整位置和光线以获得最佳测量结果。
快速开始
typescript
import { createVitalSignCamera, RealtimeEstimatorType } from 'ts-vital-sign-camera';
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.MeRppg, // 预设:AI 驱动
earlyEstimation: true,
minDuration: 3,
minConfidence: 0.3
},
onVideoFrameProcessed: (event) => {
// 实时估算可從事件中取得
if (event.realtimeEstimation) {
console.log(`心率:${event.realtimeEstimation.heartRate} BPM`);
console.log(`置信度:${event.realtimeEstimation.confidence}`);
console.log(`稳定:${event.realtimeEstimation.isStable}`);
}
}
});可用的估算器
ME-rPPG 估算器(预设)🤖
AI 驱动的神經網路方法
- 最適合:消费者应用程序、变化的环境、现代装置
- 准确度:最先進(±2-3 BPM)
- 速度:約 3 秒內首次结果
- 动作容忍度:优秀
- 光线容忍度:优秀
- 授权:开源
- 需求:約 10 MB 模型文档
typescript
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.MeRppg
}
});FDA 估算器 📈
信号处理方法
- 最適合:医疗应用程序、实时初始化、最小套件大小
- 准确度:医疗级(±2-3 BPM)
- 速度:約 5 秒內首次结果
- 动作容忍度:良好
- 光线容忍度:良好
- 授权:专有(PanopticAI)
- 需求:无(实时初始化)
typescript
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.Fda
}
});配置选项
基本配置
typescript
interface RealtimeEstimationConfig {
// 要使用的估算器
estimatorType?: RealtimeEstimatorType;
// 在完整扫描完成前显示结果
earlyEstimation?: boolean;
// 显示结果前的最小秒數
minDuration?: number;
// 最小置信度阈值(0-1)
minConfidence?: number;
// 启用调试记录
debug?: boolean;
}ME-rPPG 特定选项
typescript
{
// 模型文档路径(可選,提供预设值)
modelPath?: string;
statePath?: string;
welchPath?: string;
hrPath?: string;
// 時間正规化参数
lambda?: number; // 预设:1.0
}估算结果
RealtimeEstimation 接口
typescript
interface RealtimeEstimation {
// 心率(BPM)
heartRate: number;
// 置信度(0-1)
confidence: number;
// 结果是否足夠稳定可显示
isStable: boolean;
// 信噪比(可選)
snr?: number;
// 信号质量分数 0-100(可選)
signalQuality?: number;
}使用估算结果
typescript
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (!estimation) return;
if (estimation.isStable && estimation.confidence > 0.6) {
// 高置信度 - 显著显示
displayHeartRate(estimation.heartRate);
} else if (estimation.confidence > 0.3) {
// 中等置信度 - 显示指示器
displayHeartRate(estimation.heartRate, '精炼中...');
} else {
// 低置信度 - 引导使用者
showMessage('调整中... 请保持静止');
}
};信号可视化
显示原始 PPG 信号以進行调试或使用者反馈。
基本用法
typescript
import { SignalVisualizer } from 'ts-vital-sign-camera';
// 建立可视化器
const container = document.getElementById('signal-container');
const visualizer = new SignalVisualizer(container, {
width: 600,
height: 200,
visualizationType: 'PPG', // 或 'ECG' 進行模拟
lineColor: '#00ff00',
backgroundColor: '#000000'
});
// 使用影片帧事件中的信号数据更新
camera.onVideoFrameProcessed = (event) => {
if (event.signalData) {
visualizer.updateSignal(event.signalData, event.realtimeEstimation);
}
};
// 清理
visualizer.destroy();配置选项
typescript
interface SignalVisualizerConfig {
width?: number; // 画布宽度(预设:600)
height?: number; // 画布高度(预设:200)
maxPoints?: number; // 最大数据点(预设:300)
lineColor?: string; // 信号线颜色
backgroundColor?: string; // 画布背景
gridColor?: string; // 网格线颜色
visualizationType?: 'PPG' | 'ECG'; // 信号类型
debug?: boolean; // 调试记录
}可视化类型
PPG 模式(预设):
- 显示來自相机的实际光体积描记信号
- 实时滚动波形
- 适用於调试信号质量
ECG 模式:
- 模拟心電圖动画
- 测量期間的視覺反馈
- 符合估算的心率
typescript
// PPG 可视化(实际信号)
const ppgVisualizer = new SignalVisualizer(container, {
visualizationType: 'PPG'
});
// ECG 模拟(动画)
const ecgVisualizer = new SignalVisualizer(container, {
visualizationType: 'ECG',
lineColor: '#ff6b6b'
});SDK 行為
时间轴
0秒 ────────► 3秒 ────────► 10秒 ────────► 30秒
│ │ │ │
│ │ │ └─ 完整扫描完成
│ │ └─ 达到最佳准确度
│ └─ 首次实时估算(ME-rPPG)
└─ 扫描开始估算生命周期
初始化(0-3秒)
- 相机开始撷取
- 人脸侦测启动
- 信号缓冲区填充
早期估算(3-5秒)
- 首次结果可用
- 较低置信度
- 持续精炼
稳定估算(10秒以上)
- 高置信度结果
- 最佳准确度
- 準備显示
扫描完成(30秒)
- 服务器端验证
- 最終结果可用
- 实时估算器可重置
事件流程
typescript
// 扫描生命周期
camera.onVideoFrameProcessed = (event) => {
// 实时估算在此可用
if (event.realtimeEstimation) {
console.log('实时更新:', event.realtimeEstimation);
}
};
camera.startScanning(); // 开始扫描
// 最終结果來自健康结果
camera.onVideoFrameProcessed = (event) => {
if (event.healthResult) {
console.log('最終结果:', event.healthResult);
}
};最佳實踐
1. 选择正確的估算器
typescript
// 适用於具有变化环境的消费者应用程序
const config = {
estimatorType: RealtimeEstimatorType.MeRppg,
earlyEstimation: true,
minDuration: 3,
minConfidence: 0.3
};
// 适用於需要实时初始化的医疗应用程序
const config = {
estimatorType: RealtimeEstimatorType.Fda,
earlyEstimation: false,
minDuration: 10,
minConfidence: 0.7
};2. 提供使用者反馈
typescript
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (!estimation) return;
// 显示置信度指示器
updateConfidenceBar(estimation.confidence);
// 根据质量引导使用者
if (estimation.confidence < 0.4) {
showTip('改善光线或保持静止');
}
// 稳定時显示
if (estimation.isStable) {
displayHeartRate(estimation.heartRate);
}
};3. 处理边缘情况
typescript
let noEstimationTimeout;
let hasReceivedEstimation = false;
camera.startScanning();
// 设定无估算的超时
noEstimationTimeout = setTimeout(() => {
if (!hasReceivedEstimation) {
showError('无法侦测心率。请调整光线。');
}
}, 15000); // 15 秒
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (estimation) {
hasReceivedEstimation = true;
clearTimeout(noEstimationTimeout);
if (estimation.confidence > 0.5) {
hideError();
}
}
};4. 最佳化效能
typescript
// 节流 UI 更新
let lastUpdate = 0;
const UPDATE_INTERVAL = 500; // 500毫秒
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (!estimation) return;
const now = Date.now();
if (now - lastUpdate > UPDATE_INTERVAL) {
updateUI(estimation);
lastUpdate = now;
}
};常见使用案例
健身应用程序
typescript
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.MeRppg,
earlyEstimation: true,
minDuration: 3,
minConfidence: 0.3
},
onVideoFrameProcessed: (event) => {
if (event.realtimeEstimation) {
updateWorkoutDisplay(event.realtimeEstimation.heartRate);
updateHeartRateZone(event.realtimeEstimation.heartRate);
}
}
});医疗应用程序
typescript
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.Fda,
earlyEstimation: false,
minDuration: 10,
minConfidence: 0.7
},
onVideoFrameProcessed: (event) => {
const estimation = event.realtimeEstimation;
if (estimation?.isStable && estimation.confidence > 0.7) {
recordMeasurement(estimation);
}
}
});使用信号可视化
typescript
const visualizer = new SignalVisualizer(container, {
visualizationType: 'PPG',
width: 800,
height: 300
});
camera.onVideoFrameProcessed = (event) => {
if (event.signalData) {
visualizer.updateSignal(event.signalData, event.realtimeEstimation);
}
};疑難排解
无实时估算
问题:事件中未收到实时估算
解决方案:
- 确保设定
earlyEstimation: true - 检查人脸是否正確侦测
- 验证光线条件是否充足
- 至少等待
minDuration秒 - 检查
event.realtimeEstimation不为 null
低置信度分数
问题:置信度持续低于阈值
解决方案:
- 改善光线(自然光最佳)
- 确保使用者保持静止
- 检查人脸是否居中且稳定
- 降低
minConfidence阈值 - 使用 ME-rPPG 以获得更好的动作容忍度
ME-rPPG 模型未加载
问题:模型加载失败
解决方案:
- 验证模型文档在正確的目录中
- 检查 CORS 标头允许模型加载
- 确保正確的文档路径(使用绝对路径)
- 检查浏览器控制台是否有错误
API 参考
RealtimeEstimator 接口
typescript
interface RealtimeEstimator {
readonly estimation: RealtimeEstimation | null;
readonly signalData: SignalData | null;
configure(config?: RealtimeEstimationConfig): void;
reset(): void;
}SignalVisualizer 類別
typescript
class SignalVisualizer {
constructor(container: HTMLElement, config?: SignalVisualizerConfig);
updateSignal(
signalData: SignalData | null,
realtimeEstimation?: RealtimeEstimation | null
): void;
resetScale(): void;
destroy(): void;
}VideoFrameProcessedEvent
typescript
interface VideoFrameProcessedEvent {
videoFrameInfo: VideoFrameInfo;
videoFrame: VideoFrame;
facebox?: NormalizedFacebox;
healthResult?: ScanResult;
scanConditions?: ScanConditions;
landmarks?: NormalizedLandmarkList;
// 实时估算数据
realtimeEstimation?: RealtimeEstimation | null;
signalData?: SignalData | null;
}