网络媒体设备控制协议

网络媒体设备控制协议

媒体设备接入 API

摄像机通过 MQTT 协议连接到云平台,可以实现按需推流和云台控制等功能

消息格式

摄像机和平台使用统一的物联网平台消息格式,具体请参考 设备接入协议

{
    "did": String,
    "mid": String,
    "type": String,
    "sign": String,
    "token": String,
    "timestamp": Number,
    "data": {

    }   
}

公共属性:

设备注册

推流摄像机

一台推流设备只能推送一支流

摄像机->MQ: 订阅 (actions/{did})
设备管理服务->MQ: 订阅 (messages/{did})
摄像机->MQ: 注册 (摄像机)
MQ->设备管理服务: 注册
设备管理服务->MQ: 注册结果
MQ->摄像机: 注册结果
消息上报主题

下面假设摄像机的设备 ID 为 001122334455

PUBLISH mqtt://{domain-name}/messages/001122334455

摄像机注册消息
{
    "did": "001122334455",
    "type": "register",
    "sign": "1234567890abcdef",
    "data": {

    }
}

应答消息:

{
    "did": "001122334455",
    "type": "register",
    "result": {
        "id": "3434689jkjsdf34398095829",
        "expires": 3600,
        "token": "39409080928349028592"
    }
}

推流网关

一台网关设备可以关联多台摄像机并推送多支流

网络摄像机->推流网关: 绑定
推流网关->MQ: 订阅 'actions/{gateway}'
设备管理服务->MQ: 订阅 'messages/+'
推流网关->MQ: 注册 (网关)
MQ->设备管理服务: 注册
设备管理服务->MQ: 注册结果
MQ->推流网关: 注册结果
推流网关->MQ: 注册子设备 (摄像机)
MQ->设备管理服务: 注册
设备管理服务->MQ: 注册结果
MQ->推流网关: 注册结果

设备通过注册来激活设备以及获取设备 token.

消息上报主题

下面假设网关的设备 ID 为 001122334455

PUBLISH mqtt://{domain-name}/messages/001122334455

网关注册消息
{
    "did": "001122334455",
    "type": "register",
    "sign": "012345678900123456789012:md5",
    "data": {
    }
}

应答消息:

{
    "did": "001122334455",
    "type": "register",
    "result": {
        "id": "3434689jkjsdf34398095829",
        "expires": 3600,
        "token": "39409080928349028592"
    }
}

设备控制

摄像机->网关: 绑定
网关->MQ: 订阅(actions/{did})
设备管理服务->MQ: 订阅 (messages/+)
应用程序->设备管理服务: 操作命令 (HTTP)
设备管理服务->MQ: 操作命令
MQ->网关: 操作命令
网关->摄像机: 执行操作
摄像机->网关: 返回结果
网关->MQ: 操作结果 (messages/{did})
MQ->设备管理服务: 返回结果
设备管理服务->应用程序: 返回结果 (HTTP)

设备启动后需要订阅下面的主题来接收云端控制命令

SUBSCRIBE mqtt://{domain-name}/actions/001122334455

应答消息回复地址

PUBLISH mqtt://{domain-name}/messages/001122334455

网络摄像机

通用监控摄像机

播放 - play

流媒体服务器通过发送 playstop 操作请求,控制摄像机按需推送音视频流,应用程序则只需直接连接和播放流媒体服务器的地址即可,不需要直接和摄像机通信。

流媒体服务器会定时发送通知,告知前端摄像机当前应用程序播放状态,前端摄像机可以根据请求自动开始或停止推送,以便节省带宽资源。

开始播放

由流媒体服务器发送消息给设备:

{
    "did": "001122334455",
    "mid": "1234",
    "token": "play-token",
    "type": "action",
    "data": {
        "play": {
            "url": String,
            "players": Number
        }
    }
}

应答消息:

PUBLISH messages/001122334455

{
    "did": "001122334455",
    "mid": "1234",
    "type": "action",
    "result": {
        "play": {
            "code": 0
        }
    }
}
心跳消息

为了使摄像机一直向服务端推送视频流,流媒体服务器需要定时 (每隔 60 秒) 重复发送 play 消息给设备

停止播放

当所有应用程序都停止播放后,流媒体服务器会通知摄像机停止推流 (通常会延时 60 秒后发送,以免频繁关停推流)

由流媒体服务器发送给设备:

{
    "did": "001122334455",
    "mid": "1234",
    "token": "play-token",
    "type": "action",
    "data": {
        "stop": {
            "reason": "It's all play done"
        }
    }
}

应答消息:

PUBLISH messages/001122334455

{
    "did": "001122334455",  // 必需, 设备 ID
    "mid": "1234",          // 必需, 消息 ID
    "type": "action",       // 必需, 消息类型
    "result": {
        "stop": {
            "code": 0       // 必需, 表示调用成功
        }
    }
}

云台 - ptz

开始转动

通过这个命令可以控制摄像机镜头上下左右摆动,或者放大缩小

{
    "did": "001122334455",
    "mid": "1234",
    "token": "ptz-token",
    "type": "action",
    "data": {
        "ptz": {
            "start": {
                "direction": Number,
                "speed": Number
            }
        }
    }
}

应答消息:

{
    "did": "001122334455",
    "mid": "1234",
    "type": "action",
    "result": {
        "ptz": {
            "code": 0
        }
    }
}

停止转动

通过这个命令可以控制摄像机镜头停止摆动或缩放,就算摄像机没有成功收到这个命令,也需要在超过一定时间后自动停止摆动或缩放 (巡航等模式除外)

由流媒体服务器发送给设备:

{
    "did": "001122334455",
    "mid": "1234",
    "token": "ptz-token",
    "type": "action",
    "data": {
        "ptz": {
            "stop": {}
        }
    }
}

应答消息:

{
    "did": "001122334455",
    "mid": "1234",
    "token": "ptz-token",
    "type": "action",
    "result": {
        "ptz": {
            "code": 0
        }
    }
}

错误应答消息

{
    "did": "001122334455",
    "mid": "1234",
    "type": "action",
    "result": {
        "ptz": {
            "code": Number,
            "error": String
        }
    }
}

错误码:

CODE ERROR
60000 该设备不支持云台控制
60001 没有云台控制权限
60002 设备云台旋转达到上限位
60003 设备云台旋转达到下限位
60004 设备云台旋转达到左限位
60005 设备云台旋转达到右限位
60006 云台当前操作失败,请稍后再试
60009 正在调用预置点
60020 不支持该命令

预置位 - preset

设置预置位

将当前云台位置设置为指定的预置位

由流媒体服务器发送给设备:

{
    "did": "001122334455",
    "mid": "1234",
    "token": "preset-token",
    "type": "action",
    "data": {
        "preset": {
            "set": {
                "index": 1,
                "name": "[name]"
            }
        }
    }
}

返回结果:

{
    "did": "001122334455",
    "mid": "1234",
    "type": "action",
    "result": {
        "preset": {
            "code": 0
        }
    }
}

查询预置位列表

查询摄像机已设置的预置位列表

由流媒体服务器发送给设备:

{
    "did": "001122334455",
    "mid": "1234",
    "token": "preset-token",
    "type": "action",
    "data": {
        "preset": {
            "list": {}
        }
    }
}

返回结果:

{
    "did": "001122334455",
    "mid": "1234",
    "token": "preset-token",
    "type": "action",
    "result": {
        "preset": {
            "presets": [{
                "index": 1,
                "name": "[name]"
            }]
        }
    }
}

调用预置位

转到指定的预置位

由流媒体服务器发送给设备:

{
    "did": "001122334455",
    "mid": "1234",
    "token": "preset-token",
    "type": "action",
    "data": {
        "preset": {
            "goto": {
                "index": Number
            }
        }
    }
}

应答消息:

{
    "did": "001122334455",
    "mid": "1234",
    "type": "action",
    "result": {
        "preset": {
            "code": 0
        }
    }
}

删除预置位

删除指定的预置位

由流媒体服务器发送给设备:

{
    "did": "001122334455",
    "mid": "1234",
    "token": "preset-token",
    "type": "action",
    "data": {
        "preset": {
            "remove": {
                "index": Number
            }
        }
    }
}

应答消息:

{
    "did": "001122334455",
    "mid": "1234",
    "type": "action",
    "result": {
        "preset": {
            "code": 0
        }
    }
}

错误应答消息

{
    "did": "001122334455",
    "mid": "1234",
    "type": "action",
    "result": {
        "{action}": {
            "code": Number,
            "error": String
        }
    }
}

错误码:

CODE ERROR
60000 该设备不支持云台控制
60001 没有云台控制权限
60006 云台当前操作失败,请稍后再试
60009 正在调用预置点
60020 不支持该命令
60007 预置点个数超过最大值
60010 该预置点已经是当前位置
60011 预置点不存在

图像抓拍

请求消息

由流媒体服务器发送给设备:

{
    "did": "001122334455",
    "mid": "1234",
    "token": "capture-token",
    "type": "action",
    "data": {
        "capture": {
            "url": "https://{domain-name}/v2/storage/upload"
        }
    }
}

应答消息

{
    "did": "001122334455",
    "mid": "1234",
    "type": "action",
    "result": {
        "capture": {
            "url": "https://{domain-name}/v2/storage/file/20191010-101010.jpeg"
        }
    }
}

参数设置

应用程序可以设置部分最常用的摄像机设置,方便日常使用

读取设置

{
    "did": "001122334455",
    "mid": "1234",
    "type": "action",
    "token": "config-token",
    "data": {
        "read": ["config"]
    }
}

修改设置

{
    "did": "001122334455",
    "mid": "1234",
    "type": "action",
    "token": "config-token",
    "data": {
        "write": {
            "config": {
                "name": <value>
            }
        }
    }
}

网络录像机

录像和回放

摄像机或网络录像机设备可以包含录像组件,通过录像组件可以实现录像查询以及回放等功能。

查询录像时间段列表

查询指定时间范围内有录像的时间段

通过消息队列发送给前端设备:

{
    "did": "001122334455",
    "mid": "1234",
    "token": "replay-token",
    "type": "action",
    "data": {
        "segment": {
            "find": {
                "start": Date,
                "end": Date,
                "channel": Number,
                "stream": Number,
                "type": Number
            }
        }
    }
}

应答消息

{
    "did": "001122334455",
    "mid": "1234",
    "type": "action",
    "result": {
        "segment": {
            "find": {
                "params": {},
                "segments": [{
                    "start": Date,
                    "end": Date,
                    "type": Number
                }]
            }
        }
    }
}

录像回放推流

回放推流地址

rtmp://{domain}:{port}/v2/meida/live/{did}_replay_{channel}_{stream}_{start}_{end}

回放地址

http://{domain}/v2/meida/live/{did}_replay_{channel}_{stream}_{start}_{end}.flv

上传录像文件

注意:这个接口还在实验中,随时可能更改

录像文件推送消息

{
    "did": "001122334455",
    "mid": "1234",
    "token": "upload-token",
    "type": "action",
    "data": {
        "upload": {
            "url": 'http://{domain-name}/v2/live/upload/:did/',
            "file": '{filename}'
        }
    }
}

摄像机推送文件

POST http://{domain-name}/v2/media/upload/:did/?token={token}

服务器缓存时间

默认情况下服务器会缓存 7 天,缓存期间可随时访问,期满后会自动删除

拉取录像文件

注意:这个接口还在实验中,随时可能更改

应用程序下载录像文件

GET http://{domain-name}/v2/media/upload/:did/:filename?token={token}

安全

设备密钥

设备密钥由云服务生成,保存在数据库中。同时需要烧录到相应 ID 的摄像机设备中。

设备需要对发往服务端的注册消息使用设备密钥进行签名,这样服务器可以用来验证是否是合法的请求。

同样服务器也可以使用设备密钥对发往设备的消息进行签名,防止其他人仿冒服务器发送消息给摄像机。

注册签名

认证时不可以直接在网上传输设备密钥,而是使用密钥签名的方式:

简单签名方式:

sign = md5string(did + ':' + deviceSecret)

基于时间戳签名方式:

sign = md5string(did + ':' + deviceSecret + ':' + timestamp)

基于时间戳的签名方式更安全,但需要设备有时间同步能力

注册成功后服务器会返回一个设备访问 token, 可以用来和服务器通信,这个 token 只有注册有效期内可用。

推流凭证

推流时使用设备访问 token 即可:

rtmp://{domain-name}/live/test?token={token}