第三方 API:直播播放
直播对接分成三件事:找到通道、让流真正上线、向当前播放器签发短时地址。API 返回“已受理”时不要马上拼 URL。
sequenceDiagram
participant Backend as 第三方后端
participant API as AKStream.Next
participant Device as 摄像机或国标设备
participant Media as MediaServer
Backend->>API: 查询安全通道视图
opt 流未上线且有控制权限
Backend->>API: 启动通道或 GB28181 INVITE
API->>Device: 拉流或发起点播
Device->>Media: 发送媒体
end
Backend->>API: 查询流状态
API-->>Backend: Online
Backend->>API: 申请短时播放地址
API-->>Backend: HLS/FLV/fMP4 URLs
查询和启动通道
查询单个通道:
GET /api/v2/third-party/channels/{channelId}
Authorization: Bearer ak_pat_<TOKEN>
普通 RTSP/ONVIF 通道使用:
POST /api/v2/third-party/channels/{channelId}/start
Authorization: Bearer ak_pat_<TOKEN>
GB28181 实时点播需要 SIP INVITE、RTP 端口和 SSRC 状态机,使用原生入口:
POST /api/v2/gb28181/live/invite
Authorization: Bearer ak_pat_<TOKEN>
Content-Type: application/json
{
"deviceId": "34020000001320000001",
"channelId": "34020000001320000002",
"mediaServerId": "zlm-prod-01",
"rtpWithTcp": false,
"timeoutSeconds": 30
}
普通通道启动要求 channels.manage;GB28181 点播要求 devices.control。两者都只是受理动作,随后查询:
GET /api/v2/third-party/streams?mediaServerId=zlm-prod-01&streamId=camera-001&state=Online
Authorization: Bearer ak_pat_<TOKEN>
GB28181 设备历史录像
GET /api/v2/gb28181/records/query/{taskId} 返回的是设备侧 RecordInfo 清单。设备原始 file:///、FilePath 和 Address 只是设备内部定位值,不是浏览器播放地址;安全响应不会再返回这些原值,而会为每条录像提供 playback 动作:
- 按
playback.method/endpoint/request调用POST /api/v2/gb28181/playback/invite。 - 保存响应中的
session.id,等待该 Session 的 app/stream 变为 Online。 - 调用
POST /api/v2/third-party/gb28181/playback-sessions/{sessionId}/playback-lease。 - 使用返回
sources中的 HTTP-FLV、HTTP-fMP4 或 HLS 地址播放,并按renewAfter续租。
查询设备录像需要 devices.view,创建 Playback INVITE 需要 devices.control,签发 Web 播放租约需要 streams.play。
申请播放地址
流为 Online 后,推荐创建 URL 不变的播放租约:
POST /api/v2/third-party/channels/{channelId}/playback-lease
Authorization: Bearer ak_pat_<TOKEN>
Content-Type: application/json
{
"protocols": ["http-flv", "http-fmp4", "hls"],
"leaseSeconds": 120,
"absoluteLifetimeSeconds": 43200
}
响应示例:
{
"leaseId": "01234567-89ab-cdef-0123-456789abcdef",
"resourceKind": "live",
"resourceId": "camera-001",
"state": "Active",
"createdAt": "2026-08-24T10:00:00Z",
"expiresAt": "2026-08-24T10:02:00Z",
"renewAfter": "2026-08-24T10:01:24Z",
"absoluteExpiresAt": "2026-08-24T22:00:00Z",
"sources": [
{
"protocol": "http-flv",
"url": "https://media.example.com/live/camera-001-main.live.flv?ak_ticket=<短时票据>",
"contentType": "video/x-flv",
"browserNative": false,
"hint": "网页使用 flv.js;H.265 通常不兼容。"
}
]
}
| 协议 | 适合场景 | 客户端注意 |
|---|---|---|
| HLS | 兼容性优先、跨网络播放 | 延迟通常更高;多画面每个播放器使用独立 ak_viewer |
| HTTP-FLV | PC 浏览器低延迟预览 | 使用 flv.js/MSE;H.265 通常不能播放 |
| HTTP-fMP4 | 网页低延迟、部分 H.265 环境 | .live.mp4 是直播长连接,不是普通 MP4 文件 |
续签、停流和错误
滑动租期允许 60—600 秒,默认 120 秒;绝对寿命最长 12 小时,并且不会超过原 API Token 到期时间。服务端通常在本轮租期约 70% 处给出 renewAfter,客户端应直接使用该值,不要自己推算。到点后由后端调用:
POST /api/v2/third-party/playback-leases/{leaseId}/renew
Authorization: Bearer ak_pat_<TOKEN>
Content-Type: application/json
{"leaseSeconds":120}
续租不返回新 URL,也不会改变原 ak_ticket。HTTP-FLV 和 HTTP-fMP4 已建立的是单条长连接,无法注入新 URL,也不需要注入;HLS 继续使用同一 URL 和 MediaServer Cookie。连接断开时仍用原 URL 重连,只要租约已经续期即可。租约过期后不能复活,应创建新租约。
主动撤销使用 DELETE /api/v2/third-party/playback-leases/{leaseId}。撤销会拒绝新连接;默认不会强制踢断已经建立的播放连接。原 /playback 一次性地址继续兼容无需续租的短场景。
停止普通通道:
POST /api/v2/third-party/channels/{channelId}/stop
Authorization: Bearer ak_pat_<TOKEN>
GB28181 停流使用 /api/v2/gb28181/live/stop。如果通道配置了自动拉流,先按业务要求暂停自动恢复,避免设备收到 BYE 后又被重新 INVITE。
| 状态/错误 | 表示什么 | 怎么处理 |
|---|---|---|
401 api_token_required |
不是有效 API Token | 检查 Token、有效期、IP 白名单和吊销状态 |
403 permission_denied |
缺少当前动作权限 | 由管理员按最小权限调整,客户端不要自动扩大权限 |
409 stream_not_ready |
通道、流或媒体节点尚不可播放 | 查询通道、流命令和流会话,不要循环申请票据 |
409 playback_lease_conflict |
租约已过期、撤销、达到绝对寿命或并发冲突 | 过期/撤销时创建新租约;并发冲突可立即回读状态后重试 |
| 播放请求 401/403 | 票据过期、错流、原 Token 已失效或权限收回 | 后端重新授权;不要重放旧地址 |
| API 成功但播放器 404 | 流已掉线或媒体域名、端口、vhost/app/stream 不匹配 | 先重新查询 Online 状态和媒体节点候选地址 |
生产环境还要验证 HTTPS 混合内容、CORS、反向代理缓冲和长连接超时。API 域名不一定是媒体域名。