实时心率估算器
NOTE
僅限网页 SDK 实时估算功能目前僅适用於网页版 SDK(JavaScript、React、Vue)。不适用於行動装置 SDK(iOS、Android、Flutter、React Native)。
概述
实时估算器在影片撷取過程中提供实时心率反馈,最快可在 3-8 秒內显示结果,无需等待完整的 30 秒扫描。這創造了更具吸引力的使用者體驗,並幫助使用者调整位置和光线以获得最佳测量结果。
快速开始
typescript
import { createVitalSignCamera, RealtimeEstimatorType } from 'ts-vital-sign-camera';
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.Panoptic // 预设
},
onVideoFrameProcessed: (event) => {
// 实时估算可從事件中取得
if (event.realtimeEstimation) {
console.log(`心率:${event.realtimeEstimation.heartRate} BPM`);
console.log(`置信度:${event.realtimeEstimation.confidence}`);
console.log(`稳定:${event.realtimeEstimation.isStable}`);
}
}
});简单设置
想要以最简洁的方式使用 Panoptic 估算器默认值,请使用 enableRealtimeEstimation 布尔值:
typescript
import { createVitalSignCamera } from 'ts-vital-sign-camera';
const camera = createVitalSignCamera({
enableRealtimeEstimation: true,
onVideoFrameProcessed: (event) => {
if (event.realtimeEstimation) {
console.log(`心率:${event.realtimeEstimation.heartRate} BPM`);
}
}
});Vue SDK:
vue
<VitalSignCamera
:enableRealtimeEstimation="true"
@onVideoFrameProcessed="onVideoFrameProcessed"
/>这会以合理的默认值(signalQualityDelay: 0)启动 Panoptic 估算器。若需要自定义配置,请使用 realtimeEstimationConfig。
可用的估算器
ME-rPPG 估算器 🤖
AI 驱动的神經網路方法
- 最適合:消费者应用程序、变化的环境、现代装置
- 准确度:最先進(±2-3 BPM)
- 速度:約 3 秒內首次结果
- 动作容忍度:优秀
- 光线容忍度:优秀
- 授权:开源
- 需求:約 10 MB 模型文档
typescript
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.MeRppg
}
});Panoptic 估算器(预设)📈
信号处理方法
- 最適合:医疗应用程序、实时初始化、最小套件大小
- 准确度:医疗级(±2-3 BPM)
- 速度:約 5 秒內首次结果
- 动作容忍度:良好
- 光线容忍度:良好
- 授权:专有(PanopticAI)
- 需求:无(实时初始化)
typescript
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.Panoptic
}
});配置选项
基本配置
typescript
interface RealtimeEstimationConfig {
// 要使用的估算器
estimatorType?: RealtimeEstimatorType;
// 信号质量计算延迟(秒)
signalQualityDelay?: 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 和呼吸波形)的完整文档,请参阅信号可视化器指南。
信号可视化器会在相机画面旁显示滚动的 PPG/呼吸波形数据。它是一个独立组件,通过相机的 visualizer 属性或 onVideoFrameProcessed 回调进行连接。
如需完整的可视化选项(包括热图、边界框和面部网格叠加层),请参阅可视化选项总览。
SDK 行為
时间轴
0秒 ────────► 5秒 ────────► 8秒 ────────► 15秒 ────────► 30秒
│ │ │ │ │
│ │ │ │ └─ 完整扫描完成
│ │ │ └─ 达到最佳准确度(Panoptic 15秒)
│ │ └─ 首次实时估算(Panoptic 预热完成)
│ └─ 信号质量延迟
└─ 扫描开始估算生命周期
初始化(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
};
// 适用於需要实时初始化的医疗应用程序
const config = {
estimatorType: RealtimeEstimatorType.Panoptic,
signalQualityDelay: 10
};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
},
onVideoFrameProcessed: (event) => {
if (event.realtimeEstimation) {
updateWorkoutDisplay(event.realtimeEstimation.heartRate);
updateHeartRateZone(event.realtimeEstimation.heartRate);
}
}
});医疗应用程序
typescript
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.Panoptic,
signalQualityDelay: 10
},
onVideoFrameProcessed: (event) => {
const estimation = event.realtimeEstimation;
if (estimation?.isStable && estimation.confidence > 0.7) {
recordMeasurement(estimation);
}
}
});使用信号可视化
如需完整示例,请参阅信号可视化器指南。
疑難排解
无实时估算
问题:事件中未收到实时估算
解决方案:
- 等待预热完成(Panoptic 约 5-8 秒)
- 检查人脸是否正確侦测
- 验证光线条件是否充足
- 检查
event.realtimeEstimation不为 null
低置信度分数
问题:置信度持续低于阈值
解决方案:
- 改善光线(自然光最佳)
- 确保使用者保持静止
- 检查人脸是否居中且稳定
- 如果置信度持續較低,考虑使用 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;
}