ECG 长程分析 API
长程分析(Holter Analysis)支持 24 小时及以上的连续心电数据分析,提供专业的长程心电报告。
长程分析采用异步模式,提交任务后通过轮询查询接口获取结果。分析时长取决于数据量和分析处理进度。
分析流程
接口列表
| 接口 | 方法 | 说明 |
|---|---|---|
/api/v1/advanced/ecg/holter/upload-url | GET | 获取文件上传地址 |
/api/v1/advanced/ecg/holter/submit | POST | 提交一条长程分析记录 |
/api/v1/advanced/ecg/holter/result/:id | GET | 查询长程分析结果 |
Step 1:获取上传地址
GET /api/v1/advanced/ecg/holter/upload-url
用于获取心电二进制文件的上传地址。
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
fileType | string | 是 | 文件类型,当前仅支持 BINARY16、BIN3_16 |
请求示例
curl -X GET "https://api.heartvoice.com.cn/api/v1/advanced/ecg/holter/upload-url?fileType=BINARY16" \
-H "Authorization: Bearer YOUR_API_KEY"
响应示例
{
"errorCode": "0",
"msg": "成功",
"data": "https://ecgdata-1255716792.cos.ap-shanghai.myqcloud.com/openapi/2039546102478438400/2604021132295727.BINARY16?sign=xxx"
}
说明
- 返回值
data为文件上传地址。 - 客户端拿到地址后,自行完成文件上传。
- 上传文件格式说明如下。
文件上传示例
客户端获取到上传地址后,可直接使用该地址上传原始心电文件。示例如下:
curl -X PUT --location "https://ecgdata-1255716792.cos.ap-shanghai.myqcloud.com/openapi/2039546102478438400/2604021132295727.BINARY16?sign=xxx" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d @/path/to/your/file.BINARY16
说明:
- 将命令中的 URL 替换为 Step 1 接口实际返回的上传地址。
- 将
/path/to/your/file.BINARY16替换为本地待上传文件路径。 - 文件扩展名应与申请上传地址时传入的
fileType保持一致。
上传文件格式说明
当前支持以下两种二进制文件格式:
BINARY16 格式(单导联)
- 2 个字节为一组,表示 1 个 ECG 信号点。
- 第 1、2 字节表示第 1 个信号点。
- 第 3、4 字节表示第 2 个信号点。
- 以此类推。
- 字节按大端有符号数转换为十进制值。
字节1 字节2 -> 第1个信号点
字节3 字节4 -> 第2个信号点
字节5 字节6 -> 第3个信号点
...
BIN3_16 格式(三导联)
- 6 个字节为一组。
- 第 1、2 字节表示第 1 个导联的第 1 个点。
- 第 3、4 字节表示第 2 个导联的第 1 个点。
- 第 5、6 字节表示第 3 个导联的第 1 个点。
- 后续按相同顺序依次表示下一采样点的三导联数据。
- 字节按大端有符号数转换为十进制值。
字节1 字节2 -> 第1导联第1个点
字节3 字节4 -> 第2导联第1个点
字节5 字节6 -> 第3导联第1个点
字节7 字节8 -> 第1导联第2个点
字节9 字节10 -> 第2导联第2个点
字节11 字节12 -> 第3导联第2个点
...
Step 2:提交长程分析记录
POST /api/v1/advanced/ecg/holter/submit
文件上传完成后,调用该接口提交分析任务。
请求体参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
fileUrl | string | 是 | 文件的上传地址 |
adcGain | number | 是 | 增益系数 |
adcZero | number | 是 | 基线电压 |
sampleRate | integer | 是 | 采样率 |
deviceId | string | 否 | 设备 ID |
startTime | string | 否 | 记录开始时间,格式必须为 yyyy-MM-dd HH:mm:ss |
subject | object | 否 | 受检者信息 |
subject 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 否 | 姓名,最长 20 个字符 |
age | integer | 否 | 年龄 |
gender | string | 否 | 性别,最长 5 个字符 |
请求示例
curl -X POST "https://api.heartvoice.com.cn/api/v1/advanced/ecg/holter/submit" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fileUrl": "https://ecgdata-1255716792.cos.ap-shanghai.myqcloud.com/openapi/2039546102478438400/2604021132295727.BINARY16?sign=xxx",
"adcGain": 1000,
"adcZero": 0,
"sampleRate": 256,
"deviceId": "DEVICE_001",
"startTime": "2026-04-02 10:00:00",
"subject": {
"name": "张三",
"age": 56,
"gender": "男"
}
}'
响应示例
{
"errorCode": "0",
"msg": "成功",
"data": "123456"
}
说明
- 返回值
data为本次长程分析记录 ID。 - 后续查询结果时,使用该 ID 调用结果接口。
Step 3:查询长程分析结果
GET /api/v1/advanced/ecg/holter/result/:id
根据提交接口返回的记录 ID 查询分析结果。请将路径中的 :id 替换为实际记录 ID。
路径参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | long | 是 | 长程分析记录 ID |
请求示例
curl -X GET "https://api.heartvoice.com.cn/api/v1/advanced/ecg/holter/result/123456" \
-H "Authorization: Bearer YOUR_API_KEY"
未分析完成示例
{
"errorCode": "0",
"msg": "success",
"data": null
}
分析完成示例
{
"errorCode": "0",
"msg": "成功",
"data": {
"longRangeId": "123456",
"adcGain": 1000,
"adcZero": 0.0,
"sampleRate": 256,
"deviceId": "DEVICE_001",
"startTime": "2026-01-27T05:51:49.000+00:00",
"duration": 4423.675,
"report": "{\"diagDescription\":\"记录全过程为窦性心律,心率介于60~60次/分,平均心率60次/分,心率正常。偶发房性早搏,单发房早1次。\",\"hr\":{\"avgHr\":60,\"maxHr\":60,\"maxHrIdx\":67559,\"maxTopHr\":[{\"hr\":60,\"idx\":67559},{\"hr\":60,\"idx\":69159},{\"hr\":60,\"idx\":70359}],\"minHr\":60,\"minHrIdx\":67559,\"minTopHr\":[{\"hr\":60,\"idx\":877904},{\"hr\":60,\"idx\":879104},{\"hr\":60,\"idx\":880304}]},\"hrvPer1Hours\":[{\"avgNn\":997,\"duration\":\"PT1H13M43S\",\"hrv\":{\"highFrequencyPower\":0.73,\"histogram\":{\"x\":[0.0,7.81,15.63,23.44,31.25,39.06],\"y\":[0.0,0.0,0.0,0.0,0.0,0.0]},\"lowFrequencyPower\":1.6,\"pnn50\":0.8,\"rmssd\":37.71,\"sdann\":11.36,\"sdnn\":43.47,\"sdnnIndex\":11.42,\"spectrum\":{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05],\"y\":[27.17198685934816,0.39541511692910203,0.19464690395184117,0.0815961821718201,0.03969849117036164,0.042867407692248775]},\"totalPower\":30.39,\"triIndex\":1.03,\"veryLowFrequencyPower\":6.16},\"startTime\":\"2026-01-27T13:51:49\",\"type\":\"全程\"},{\"avgNn\":996,\"duration\":\"PT1H\",\"hrv\":{\"highFrequencyPower\":0.9,\"histogram\":{\"x\":[0.0,7.81,15.63,23.44,31.25,39.06],\"y\":[0.0,0.0,0.0,0.0,0.0,0.0]},\"lowFrequencyPower\":2.05,\"pnn50\":1.0,\"rmssd\":42.1,\"sdann\":12.68,\"sdnn\":48.49,\"sdnnIndex\":14.38,\"spectrum\":{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05],\"y\":[35.09696860777187,0.5082682315253021,0.24911680280378853,0.10403246731350774,0.049413477273076205,0.05310185996700735]},\"totalPower\":39.17,\"triIndex\":1.03,\"veryLowFrequencyPower\":7.95},\"startTime\":\"2026-01-27T13:51:49\",\"type\":\"小时\"}],\"labelIdx\":{\"PAUSE\":[{\"idx\":[7565,7979]},{\"idx\":[46155,46559]}],\"SINGLE_PAC\":[{\"idx\":[46155,46559]}],\"SN\":[{\"idx\":[3200,5200]},{\"idx\":[6400,8400]},{\"idx\":[11200,13200]}],\"IVB\":[{\"idx\":[171200,643600]},{\"idx\":[753600,883600]}]},\"labelIdxList\":{\"SINGLE_PAC\":[46155],\"SN\":[3200,6400,11200,19200,25600,32000],\"IVB\":[171200,172800,174400,176000,177600,179200]},\"labels\":[\"SINGLE_PAC\",\"SN\",\"IVB\"],\"premature\":{\"bigeminyPAC\":0,\"bigeminyPACCnt\":0,\"bigeminyPJC\":0,\"bigeminyPJCCnt\":0,\"bigeminyPVC\":0,\"bigeminyPVCCnt\":0,\"pairedPAC\":0,\"pairedPACCnt\":0,\"pairedPJC\":0,\"pairedPJCCnt\":0,\"pairedPVC\":0,\"pairedPVCCnt\":0,\"singlePAC\":1,\"singlePJC\":0,\"singlePVC\":0,\"totalJT\":0,\"totalJTCnt\":0,\"totalPAC\":1,\"totalPJC\":0,\"totalPVC\":0,\"totalSVT\":0,\"totalSVTCnt\":0,\"totalVT\":0,\"totalVTCnt\":0,\"triadPAC\":0,\"triadPACCnt\":0,\"triadPJC\":0,\"triadPJCCnt\":0,\"triadPVC\":0,\"triadPVCCnt\":0},\"qtc\":{\"maxTopQtc\":[{\"idx\":4,\"qtc\":492},{\"idx\":16,\"qtc\":506},{\"idx\":7,\"qtc\":515}],\"minTopQtc\":[{\"idx\":41,\"qtc\":339},{\"idx\":37,\"qtc\":344},{\"idx\":50,\"qtc\":379}]},\"totalValidBeats\":4204,\"totalValidDuration\":4220.0}",
"pdfUrl": "https://ecgdata-1255716792.cos.ap-shanghai.myqcloud.com/openapi/2015617052407152640/260325163718451.BIN3_16_AI.pdf?sign=xxx"
}
}
返回字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
longRangeId | string | 长程分析记录 ID |
adcGain | number | 增益系数 |
adcZero | number | 基线电压 |
sampleRate | integer | 采样率 |
deviceId | string | 设备 ID |
startTime | datetime | 记录开始时间 |
duration | number | 记录时长,单位为秒 |
report | string | 分析结果 JSON 字符串,包含诊断描述、心率、HRV、标签、早搏统计、QTc 等结果 |
pdfUrl | string | AI 分析报告 PDF 地址 |
说明
- 分析未完成时,返回
data: null。 - 分析完成后,
data.report中返回该条记录的分析结果字符串,data.pdfUrl为对应的 PDF 报告地址。 - 如需结构化结果,需对
report字段中的 JSON 字符串再做一次解析。
长程心电分析结果 JSON 字段说明
接口返回的动态心电(长程)分析结果,是一段序列化后的 JSON 字符串。 使用前请先将该字符串反序列化(解析)为对象,再按下文说明读取各字段。
阅读说明
📌 按需出现 每份结果只包含本次检测实际出现的内容。值为空或本次未发生的项(如本次无房颤、无窦性心动过速/过缓)不会出现在 JSON 中,属正常现象。
📌 位置(idx) 字段名中带
Idx的表示事件在记录中的位置,单位为采样点序号;区间用[起点, 终点]表示。
📌 位置换算时间
时刻 = 记录开始时间 + idx ÷ 采样率(秒)。采样率由每条记录自身决定,须以该记录实际采样率为准。
📌 qtc 的 idx 为例外
qtc中的idx是分析片段序号(每片固定 8 秒,与采样率无关),换算为:记录开始时间 + idx × 8(秒)。
📌 时长格式
duration采用 ISO-8601 时间间隔格式,如PT47M6S表示 47 分 6 秒。
一、字段总览
| 字段 | 类型 | 说明 | 详见 |
|---|---|---|---|
totalValidBeats | 整数 | 去除干扰后的有效心搏总数 | — |
totalValidDuration | 小数(秒) | 去除干扰后的有效信号时长 | — |
diagDescription | 字符串 | 根据节律标签与心率自动生成的诊断结论文字 | — |
hr | 对象 | 整段记录的心率统计 | 2.1 |
SNT | 对象 | 窦性心动过速统计(本次无则不出现) | 2.2 |
SNB | 对象 | 窦性心动过缓统计(本次无则不出现) | 2.2 |
labels | 数组 | 本次检出的节律类型集合 | 2.3 |
labelIdx | 映射对象 | 各节律出现的位置区间 | 2.3 |
premature | 对象 | 各类早搏 / 异位心律统计 | 2.4 |
hrvPer1Hours | 数组 | 心率变异性(全程 + 逐小时) | 2.5 |
qtc | 对象 | QT 间期校正值 | 2.6 |
labelIdxList | 映射对象 | 已废弃,请勿使用 | — |
结构示意:
结果对象(root)
├─ totalValidBeats / totalValidDuration / diagDescription
├─ hr ──────────────► { avgHr, minHr, maxHr, minTopHr[], maxTopHr[] }
├─ SNT / SNB ───────► { totalDuration, maxBeatCount, maxDuration, idx[] }
├─ labels[] / labelIdx{ 节律 → [ {idx} ] }
├─ premature ───────► { 室性 / 房性 / 交界性 早搏统计 }
├─ hrvPer1Hours[] ──► { type, startTime, duration, avgNn, hrv{...} }
└─ qtc ─────────────► { maxTopQtc[], minTopQtc[] }
二、字段详解
2.1 hr(心率统计)
汇总整段记录的心率信息。
| 字段 | 类型 | 说明 |
|---|---|---|
avgHr | 整数(次/分) | 平均心率 |
minHr | 整数(次/分) | 最慢心率 |
minHrIdx | 整数 | 最慢心率出现的位置 |
maxHr | 整数(次/分) | 最快心率 |
maxHrIdx | 整数 | 最快心率出现的位置 |
minTopHr | 数组 | 最慢的前 5 个心率,元素结构见下 |
maxTopHr | 数组 | 最快的前 5 个心率,元素结构见下 |
minTopHr / maxTopHr 数组元素:
| 字段 | 类型 | 说明 |
|---|---|---|
hr | 整数(次/分) | 心率 |
idx | 整数 | 该心率出现的位置 |
2.2 SNT / SNB(窦性心动过速 / 过缓)
SNT(过速)、SNB(过缓)结构相同,本次记录若无则对应字段不出现。
| 字段 | 类型 | 说明 |
|---|---|---|
totalDuration | 小数(秒) | 总持续时间 |
maxBeatCount | 整数 | 最长一阵连续发作的心搏数 |
maxDuration | 整数(秒) | 最长一阵连续发作的持续时间 |
idx | [起点, 终点] | 最长一阵的起止位置 |
2.3 labels / labelIdx(异常标签)
二者共同描述"AI算法检出了哪些异常,并从中选择出代表性的心电图片段发生的时间点"。
| 字段 | 类型 | 说明 |
|---|---|---|
labels | 数组 | 本次检出的异常类型集合(取值见附录) |
labelIdx | 映射对象 | 键为异常类型,值为该异常出现的区间列表(数量较多时会挑选具 有代表性的发生点) |
labelIdx 值(区间列表)的元素:
| 字段 | 类型 | 说明 |
|---|---|---|
idx | [起点, 终点] | 该次出现的起止位置 |
2.4 premature(早搏统计)
统计室性、房性、交界性三类早搏及其衍生节律。本次记录若无则各计数为 0。其中 Idx 字段的元素均为 [起点, 终点] 位置区间。
房性早搏 PAC:
| 字段 | 类型 | 说明 |
|---|---|---|
totalPAC | 整数 | 房性早搏总数 |
singlePAC | 整数 | 单发房早次数 |
singlePACIdx | 数组 | 各次单发房早的位置 |
pairedPAC | 整数 | 成对房早次数 |
pairedPACCnt | 整数 | 成对房早阵数 |
pairedPACIdx | 数组 | 各阵成对房早的位置 |
bigeminyPAC | 整数 | 房早二联律次数 |
bigeminyPACCnt | 整数 | 房早二联律阵数 |
bigeminyPACIdx | 数组 | 各阵房早二联律的位置 |
triadPAC | 整数 | 房早三联律次数 |
triadPACCnt | 整数 | 房早三联律阵数 |
triadPACIdx | 数组 | 各阵房早三联律的位置 |
totalSVT | 整数 | 室上性(房性)心动过速次数 |
totalSVTCnt | 整数 | 室上性心动过速阵数 |
SVTIdx | 数组 | 各阵室上性心动过速的位置 |
室性早搏 PVC:
| 字段 | 类型 | 说明 |
|---|---|---|
totalPVC | 整数 | 室性早搏总数 |
singlePVC | 整数 | 单发室早次数 |
singlePVCIdx | 数组 | 各次单发室早的位置 |
pairedPVC | 整数 | 成对室早次数 |
pairedPVCCnt | 整数 | 成对室早阵数 |
pairedPVCIdx | 数组 | 各阵成对室早的位置 |
bigeminyPVC | 整数 | 室早二联律次数 |
bigeminyPVCCnt | 整数 | 室早二联律阵数 |
bigeminyPVCIdx | 数组 | 各阵室早二联律的位置 |
triadPVC | 整数 | 室早三联律次数 |
triadPVCCnt | 整数 | 室早三联律阵数 |
triadPVCIdx | 数组 | 各阵室早三联律的位置 |
totalVT | 整数 | 室性心动过速次数 |
totalVTCnt | 整数 | 室性心动过速阵数 |
VTIdx | 数组 | 各阵室性心动过速的位置 |
交界性早搏 PJC:
| 字段 | 类型 | 说明 |
|---|---|---|
totalPJC | 整数 | 交界性早搏总数 |
singlePJC | 整数 | 单发交界性早 搏次数 |
singlePJCIdx | 数组 | 各次单发交界性早搏的位置 |
pairedPJC | 整数 | 成对交界性早搏次数 |
pairedPJCCnt | 整数 | 成对交界性早搏阵数 |
pairedPJCIdx | 数组 | 各阵成对交界性早搏的位置 |
bigeminyPJC | 整数 | 交界性早搏二联律次数 |
bigeminyPJCCnt | 整数 | 交界性早搏二联律阵数 |
bigeminyPJCIdx | 数组 | 各阵交界性早搏二联律的位置 |
triadPJC | 整数 | 交界性早搏三联律次数 |
triadPJCCnt | 整数 | 交界性早搏三联律阵数 |
triadPJCIdx | 数组 | 各阵交界性早搏三联律的位置 |
totalJT | 整数 | 交界性心动过速次数 |
totalJTCnt | 整数 | 交界性心动过速阵数 |
JTIdx | 数组 | 各阵交界性心动过速的位置 |
2.5 hrvPer1Hours(心率变异性)
数组,每个元素是某时段的心率变异性统计:type="全程" 为整段统计,type="小时" 为逐小时统计。
| 字段 | 类型 | 说明 |
|---|---|---|
type | 字符串 | 统计范围:全程 / 小时 |
startTime |