扩展场景控制契约
约 16833 字大约 56 分钟
2026-10-16
本页按 Topic、method 和方向定义完整契约。字段表与JSON中的可选扩展不等于当前全部启用,实际接入前请查支持范围;应用REST封装见应用接入。
公共行为
本章只补充基础命令无法完整表达的状态;物模型和媒体不迁移到信令。SIG↑/SIG↓分别为 $thing/up/signaling/{productID}/{deviceName} / $thing/down/signaling/{productID}/{deviceName}。APP↑为鉴权POST,APP↓为WS interaction.event。没有协议版本字段。
Control/Update/Sync为请求,State/Updated/Snapshot为应答或独立事件:带code是同token应答,无code是独立事件,SIG↓事件有eventSeq;下行设备执行命令也有eventSeq。扩展请求需sessionId;包装capabilityReport的会话前能力登记除外。revision是业务状态修订号,不是协议版本、eventSeq或媒体序号。
expectedRevision是并发前置条件;不匹配409 staleRevision及data.currentRevision。先按token去重再判断revision,不能重试执行第二次。一个计划pending→applied可保持revision,事件有更高eventSeq;新操作/所有者变化增加revision。新实例初始0。
受理10秒;失败返回对应应答method、原token、code/data.reason,不要求成功字段。设备playback/focus必须真实回报,不能以云端期望代替。转接45秒、接续30秒、媒体变更15秒、录制封装60秒;超时明确failed/unknown并释放候选资源,保留未撤权的原业务。不支持的能力422,不把未知命令当成功。
人际转接的45秒是首次操作总预算,不是邀请期限:接听邀请最多30秒,未接听即撤候选;及时接听后仅使用原45秒剩余预算协商。接听、邀请重投、操作重放及取消均不续期。旧邀请超时回调不得撤已接听或新代次候选。
类型与修订号作用域
| 类型 | 定义 |
|---|---|
| Party | kind:user/device/service/endpoint、id:string均必填;设备ID是平台资源ID,不是可自报身份;endpoint仅限同用户授权终端 |
| Recipient | endpointId:string、state:pending/connected/failed/ended必填;failed时reason:string必填;名单只向有管理权的发布者披露 |
| ControlSnapshot | call/focus/floor为null或完整对应State正文;recordings/playbacks/processors/broadcasts/handoffs为对应状态数组;mediaPlan含revision:uint和tracks:Track[];ai为null或含inputId:string、inputState:active/paused、activeRespIds:string[]。上述字段均必填 |
| Track扩展 | sourceType:microphone/camera/screen/systemAudio/file可选;缺省从已注册sourceId解析,不猜测;屏幕/系统音频/摄像头分别授权 |
| Consent引用 | 平台校验同意的签署者、会话、源轨、用途、接收者、有效期及撤销状态;不接受客户端自签声明;录制同意不等于AI读流同意 |
call按呼叫组、floor按(sessionId,floorId)、mediaUpdate按(sessionId,endpointId)、recording按recordingId、playback按playbackId、broadcast按broadcastId、endpoint按handoffId、focus按设备资源集合递增。sessionSnapshot.revision是快照修订号,不是所有子对象expectedRevision;子对象不存在时为null/空数组,mediaPlan仍须提供revision。endpointEpoch由平台端注册首次分配1,接续提交递增并废除旧绑定。控制身份和优先级取服务端授权,不能相信payload自报权限。
应用端映射
interaction.control.command仅允许本章设备请求方法以及capabilityReport/sessionAccept/sessionReject/inputSend/toolCallSubmit/audioStart/audioStop/respCancel;禁止包装interaction.control自身。arguments复用对应正文。应用接听使用interaction.invite的token;登录态必须匹配被邀请端。云端控制直接处理,需要设备执行时记录应用token→设备token映射,收到真实结果后才返回最终interaction.result。
interaction.result.data.result:object是对应State/Updated/Snapshot成功正文;原operation/state和失败data.reason不变。后续独立状态通过interaction.controlState投递,事件自身token新建,result.requestToken可关联原操作。录制ready可在原通话结束后投递,不能据此恢复媒体会话。
callControl · SIG↑
- 方向:设备→平台;应答:callState。
- 触发、权限与状态:不带candidateSessionId的cancel只允许尚未接通的呼叫;已接通用sessionEnd。带candidateSessionId的cancel仅撤本端原转接账本绑定的候选,原主通话保持active。hold只保留会话/信令,停止本端发声与转发麦克风;resume重新获得焦点。转接先新建候选呼叫并得到对方接听/媒体连通,再提交替换;失败保留原通话。AI转人工不默认共享转写/图像。
- 正常设备转接保留原被叫会话腿,以新候选替换转接发起方;成功仅结束发起方原腿,原被叫与候选继续同一呼叫组。候选会话只授权候选本人接听/协商/结束,不授予发起设备冒用该会话的权限。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S13。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| operation | string | 必填 | cancel/hold/resume/transfer/escalate |
| expectedRevision | uint | 必填 | 本呼叫控制修订号 |
| target | Party | 转接或转人工必填 | 服务端可解析的目标 |
| candidateSessionId | string | cancel时可选,其他操作禁止 | 撤销原主体、原本端session、原转接账本代次共同绑定的候选;不是发起者身份,expectedRevision仍核原主通话 |
| consentIds | string[] | 仅escalate且shareContext=true时必填;其他情况禁止 | 1至16项不重复的同意引用,每项为不超过128字节的合法ID;仅语法合法不代表授权成立 |
| shareContext | boolean | 仅escalate时可选;其他操作禁止 | 缺省false;false不携带consentIds,不共享上下文 |
{
"msgToken": "s13-8",
"method": "callControl",
"sessionId": "s13-session",
"params": {
"operation": "cancel",
"expectedRevision": 0
}
}对应S13-M03;其他操作按条件字段校验。
AI转人工的候选关联与第三屏障(部分实现,端云待验)
escalate作用于原AI会话,不套用人际transfer的“发起方退出”规则。平台校验原AI主体、目标权限及双方实际人际媒体能力后,一次性分配候选人工腿、本端新人工腿和呼叫组;用原AI会话的callState受理回执关联,随后分别发送普通sessionInvite。新邀请只使用现有邀请字段,不得把原AI sessionId、人工候选sessionId或呼叫组当本端新腿身份。
目标service必须有服务端真实解析与授权结果;当前该解析及AI转人工入口未实现,不默认选管理员、设备所有者或其他在线端。shareContext=false保持不共享;true及consentIds的签署者/接收者/用途/范围/到期/撤销校验和实际交付全部待实现,未支持时明确拒绝,不静默忽略也不因接听而授予转写/图像权限。
先发原callState关联再发邀请,但接收端不能依赖跨回调绝对到达顺序:同一鉴权Topic上的候选邀请最多有界暂存一个、最长到原候选截止;仅在原token、原AI session、localSessionId和callGroupId全部匹配后准入,未关联邀请不抢占AI。普通人工来电仍走普通来电策略,不自动绑定正在进行的AI转人工。
候选等待与媒体协商期间原AI保持运行。本端候选可准备Peer,但不启动第二套物理麦克风采集、不向候选预送AI音频/正文;原采集归属仍是AI。双方原腿的accept、ICE/DTLS、匹配mediaRevision的实际mediaState只是网络屏障,不证明麦克风/扬声器已经移交。第三屏障复用focusControl/focusState:平台再次核原授权、候选代次与截止后,先对原AI实际租约发送完整["microphone","speaker"]组的suspend,收到原token的实际suspended回执,才对原关联本端新人际腿发送同组acquire。共享驱动复用唯一物理采集实例、围栏旧AI转发并实际安装新人际采集/播放归属;只在整组完成后报告acquired,不能把排队、SDP或单轨active作为完成。
平台收到原acquired后还须再次核当前授权、原连接、候选/媒体代次、绝对期限及设备全局CAS,将整组回执和人际路由提交结果持久确认。此后才发送两个人际腿的sessionEstablished,再发送原AI的callState.transferred与sessionEnded。sessionEstablished是最终提交确认,不是触发尚未证实的本地移交。候选在提交前不得转发真实人际音频;原AI模型/会话保留到提交已明确成功,旧AI结束不得关闭已移交的人际驱动或Peer。
已实现三屏障协调核心、完整microphone/speaker仲裁驱动及实际输入票据接口;现行独立桌面焦点宿主仍只装配speaker/display,新共享宿主与后端最终移交尚未闭环,不能声明端云整组移交完成。缺原AI真实租约、缺实际microphone/speaker整组能力、缺唯一共享驱动或缺候选授权关联均不能准入,不凭当前会话补造focusId。通用后端焦点入口只接已established会话;后继专属入口仅可对原已授权escalate账本绑定的prepared候选特批建立前的原焦点请求与回执,且固定原本端腿/呼叫组/连接/能力/代次/截止,不泛化接纳negotiating会话。详情及逐报文见S13-M65起,实际实现与验收范围见支持范围。
失败按阶段处理:尚未实际suspend时,只清候选、原仍授权AI保持运行;已suspend且明确未acquire、路由明确未提交时,复核原AI授权/用户意图/截止与当前CAS,发送原完整组restore,收到实际restored才可呈现AI输入/播放恢复。恢复拒绝或未知不假报active。acquire或路由提交未知时,保留原操作、原字节和截止作有界查询/原token重放,不盲恢复造成双重采集,也不报transferred。路由已经提交后发生本地媒体故障,按新人际失败路径收尾,不擅自回滚已变路由或复活旧AI。原AI自身被撤权或用户结束AI则按原终态结束,取消尚未提交候选,不能借“保留AI”绕过授权。原token重放不新建腿、不续期、不重复切换;旧候选/旧定时器不影响新意图。
callState · SIG↓
- 方向:平台→设备;应答:—。
- 触发、权限与状态:应答或独立事件。held等属于呼叫子状态,业务session仍为established;cancelled随后结束相关呼叫腿。设备主动转接请求不授予目标权限。等待呼叫30秒,转接45秒;候选失败恢复原活动通话,不抢占新通话。
- 转接异步
failed必须关联原requestToken,只表示本次操作失败;原呼叫组与原两会话腿继续,不能据该事件清理原媒体或忙线。人际transfer的transferred后只结束发起方原腿,不结束留存方与候选;AIescalate则保留原设备作为新人工腿参与者,仅在两腿实际切换完成后结束旧AI腿。 - 撤候选成功返回
state=active、原candidateSessionId和reason=candidateCancelled;独立结果事件还关联撤候选请求的requestToken。这不是cancelled呼叫终态,不结束原任一腿;同token回放优先,不以旧候选ID或旧计时器撤新候选。 - 请求失败与呼叫失败分开:原token去重优先于修订检查。过期修订返回409、
reason=staleRevision;接听已先提交(包括媒体仍在协商)或已建立后请求cancel返回409、reason=invalidState。两者均携带当前呼叫控制currentRevision,不返回成功state/revision、不发state=failed、不关闭或改变原呼叫;权限拒绝仍走原鉴权错误语义。 - 公共入口拒绝与上述业务拒绝分开:入口尚未核实原呼叫修订时,沿用
reason=requestConflict等有限公共错误,不填或伪造currentRevision。这类reason-only错误仍关联原session/token,不表示当前呼叫状态改变。 - 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S13。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| state | string | 成功应答或独立状态事件必填 | ringing/waiting/held/active/transferring/transferred/cancelled/failed;控制请求被拒绝不填 |
| revision | uint | 成功应答或独立状态事件必填 | 单调呼叫控制修订号;不是mediaRevision |
| reason | string | 失败应答或取消必填 | 固定原因;已核实修订的409使用staleRevision/invalidState,入口沿用公共错误原因;原取消使用callerCancelled,候选取消使用candidateCancelled;设备转接操作失败限定transferRejected/transferTimeout/transferMediaFailed/transferUnavailable/transferRevisionChanged/transferPermissionRevoked |
| currentRevision | uint | 409且reason为staleRevision/invalidState时必填 | 服务器已核实的当前呼叫控制修订号,可为0;拒绝不推进此修订;未知修订的入口错误不填 |
| candidateSessionId | string | transferring/transferred/候选取消必填;failed已分配时携带 | 候选呼叫,不能作为原本端身份 |
| localSessionId | string | 已分配双腿的escalate受理/完成/失败/候选取消必填;其他操作省略 | 适用能力见支持范围:接收者获授权的新humanCall会话腿,非原AI腿、非候选人工腿;请求不能自报 |
| callGroupId | string | 与上述localSessionId同时必填;其他操作不强加 | 适用能力见支持范围:平台持久绑定两个人际腿的组,与两份sessionInvite.callGroupId一致;不授予另一腿身份 |
| requestToken | string | 转接完成、失败或候选取消的独立事件必填;旧控制事件可选 | 原操作token |
escalate分支的条件关联字段不修改旧人际控制应答;未声明对应能力的设备和未支持AI转人工的消费者不能突然收到这些字段或候选邀请。原AI会话上eventSeq继续其现有水位(不重置为1);新两腿各自独立水位。失败示例和完整双腿报文见S13-M48至M64。
此设计复用既有会话方法但不是已实现字段扩展:escalate操作失败复用transferRejected/transferTimeout/transferMediaFailed/transferUnavailable/transferRevisionChanged/transferPermissionRevoked,并明确仅作用于该原操作。撤候选成功仍用active/candidateCancelled,不产生原AI结束。成功切换后旧AI sessionEnded.reason=transferred是本扩展对基础终态契约的条件设计补充,不能推广至任意会话;当前基础终态表未包含该新增分支,生产接线时须同步严格解析器并回归旧消费者,未实现前不向其发送。候选失败使用基础既有userRejected/inviteTimeout/mediaFailed/permissionRevoked/userHangup原因,不创造候选成功或旧AI失败事实。
{
"msgToken": "s13-8",
"method": "callState",
"sessionId": "s13-session",
"data": {
"state": "cancelled",
"revision": 1,
"reason": "callerCancelled"
},
"code": 200
}对应S13-M04;其他操作按条件字段校验。
接听先提交时,同一cancel请求仅收到请求拒绝,调用者如要结束已接听呼叫须另发sessionEnd:
{
"msgToken": "s13-8",
"method": "callState",
"sessionId": "s13-session",
"code": 409,
"data": { "reason": "invalidState", "currentRevision": 0 }
}floorControl · SIG↑
- 方向:设备→平台;应答:floorState。
- 触发、权限与状态:只有获得有效租约的端才能上行并被转发;先到先得,冲突409不排隐式队列。释放、失联或租约到期撤销,平台停转发、设备停采集;续约不改变优先权,半租期续约。PTT属于人际/群组发言控制,不使用AI interactionMode。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S12。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| operation | string | 必填 | acquire/renew/release |
| expectedRevision | uint | 必填 | 当前发言权修订号 |
| floorId | string | 必填 | 会话内抢麦组 |
| leaseId | string | renew/release必填 | 平台授予租约 |
| leaseMs | uint | acquire/renew必填 | 1000至10000毫秒 |
{
"msgToken": "s12-1",
"method": "floorControl",
"sessionId": "s12-session",
"params": {
"operation": "acquire",
"expectedRevision": 0,
"floorId": "room-a",
"leaseMs": 5000
}
}对应S12-M01;其他操作按条件字段校验。
floorState · SIG↓
- 方向:平台→设备;应答:—。
- 触发、权限与状态:平台应答或撤销事件;即使控制丢失也按租约到期停发。优先级强制抢麦只允许经平台配置的紧急角色,先撤旧租约再发新租约,不能信任payload自报角色。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S12。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| state | string | 必填 | granted/released/expired/denied |
| revision | uint | 必填 | 发言权修订号 |
| floorId | string | 必填 | 组ID |
| leaseId | string | granted必填 | 租约ID |
| holderId | string | granted必填 | 已鉴权参与者 |
| expiresAt | int64 | granted必填 | Unix毫秒 |
| reason | string | denied/expired必填 | 原因 |
{
"msgToken": "s12-1",
"method": "floorState",
"sessionId": "s12-session",
"data": {
"state": "granted",
"revision": 1,
"floorId": "room-a",
"leaseId": "lease-a",
"holderId": "member-a",
"expiresAt": 1900000000000
},
"code": 200
}对应S12-M02;其他操作按条件字段校验。
mediaUpdate · SIG↑
- 方向:设备→平台;应答:mediaUpdated。
- 触发、权限与状态:平台先校验轨、源权限和编解码,返回pending计划;端随后mediaOffer/Answer完成重协商,再以trackState报告实际状态。replace新轨必须新trackId;停旧摄像头后才启新源,撤权立即停发,不等待SDP。音频升级视频需对端明确同意,不因对端有摄像头默认同意。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S14、S19。
计划修订不匹配返回原请求 msgToken 的 mediaUpdated(code=409,data={reason:"staleRevision",currentRevision:…});修订匹配但前一计划未结束则为 reason:"updatePending"。409不带成功形态的 state/tracks,不关闭主通话。相同 token 和正文重放原结果,不能自动换 token 重做动作。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| operation | string | 必填 | add/remove/replace/setQuality |
| expectedRevision | uint | 必填 | 媒体计划修订号 |
| tracks | Track[] | add/replace必填 | 新轨含sourceType |
| trackIds | string[] | replace/remove/setQuality必填 | 目标轨 |
| consentIds | string[] | 新增屏幕/摄像头必填 | 新源授权 |
| profile | string | setQuality必填 | audioOnly/low/standard/high |
{
"msgToken": "s14-20",
"method": "mediaUpdate",
"sessionId": "s14-session",
"params": {
"operation": "add",
"expectedRevision": 0,
"tracks": [
{
"trackId": "video-new",
"kind": "video",
"sourceId": "front",
"sourceType": "camera",
"direction": "sendonly",
"codec": "H264",
"state": "requested"
}
],
"consentIds": [
"camera-consent",
"peer-video-consent"
]
}
}对应S14-M01;其他操作按条件字段校验。
mediaUpdated · SIG↓
- 方向:平台→设备;应答:—。
- 触发、权限与状态:应答pending不是媒体已变更;15秒协商失败后failed,旧合法轨可继续;被撤权的轨不得回滚恢复。applied仅在端状态和平台观测一致后发。仅质量约束且不改SDP时保持mediaRevision。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S14、S19。
IPC setQuality 当前区分:pending 是原 token、code=200、无事件水位的受理应答;applied/failed 是独立 msgToken、无 code、带 eventSeq 和原 requestToken 的终态事件。端侧编码器读回只证明约束已接受,不证明现场画质、实际码率或硬件驱动验收;平台以匹配原计划的逐轨事实收敛,不宣称独立测量了端侧编码参数。失败只携带 state/revision/requestToken/reason,不携带成功形态的 tracks/mediaRevision。当前公开质量原因是 qualityFailed/qualityUnsupported/qualityTimeout。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| state | string | 必填 | pending/applied/failed |
| revision | uint | 必填 | 媒体计划修订号 |
| mediaRevision | uint | pending/applied必填 | 将使用或已使用的Peer代次 |
| tracks | Track[] | pending/applied必填 | 本操作影响集合中仍保留的确认轨,remove可为空;不覆盖无关轨 |
| reason | string | failed必填 | 原因 |
| requestToken | string | 后续事件必填 | 关联原计划请求 |
{
"msgToken": "s14-20",
"method": "mediaUpdated",
"sessionId": "s14-session",
"data": {
"state": "pending",
"revision": 1,
"mediaRevision": 2,
"tracks": [
{
"trackId": "video-new",
"kind": "video",
"sourceId": "front",
"sourceType": "camera",
"direction": "sendonly",
"codec": "H264",
"state": "requested"
}
],
"requestToken": "s14-20"
},
"code": 200
}对应S14-M02;其他操作按条件字段校验。
recordingControl · SIG↑
- 方向:设备→平台;应答:recordingState。
- 触发、权限与状态:指令要求云端录制器,不推断设备本地录像能力。本地IPC录像计划仍走物模型。start先核验所有参与者同意再取流;新成员未同意暂停录制,撤权先停止取流。pause保留实例,不保存暂停期媒体;stop异步封装文件。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S15。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| operation | string | 必填 | start/pause/resume/stop |
| expectedRevision | uint | 必填 | 录制实例修订号 |
| recordingId | string | 必填 | 幂等录制实例ID |
| sourceTrackIds | string[] | start必填 | 授权轨 |
| consentIds | string[] | start/resume必填 | 所有被录者同意 |
| policyId | string | start必填 | 保留/访问/删除策略引用 |
{
"msgToken": "s15-35",
"method": "recordingControl",
"sessionId": "s15-session",
"params": {
"operation": "start",
"expectedRevision": 0,
"recordingId": "rec-1",
"sourceTrackIds": [
"mic-a",
"mic-b"
],
"consentIds": [
"consent-a",
"consent-b"
],
"policyId": "retention-policy"
}
}对应S15-M01;其他操作按条件字段校验。
recordingState · SIG↓
- 方向:平台→设备;应答:—。
- 触发、权限与状态:所有被录参与者收到状态通知;不能把受理当开始录制,或finalizing当文件可用。封装最多60秒,超时failed并回收临时数据;结束通话先停录,最终文件结果仍可按原session/recordingId投递,不能复活媒体会话。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S15。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| state | string | 必填 | starting/active/paused/finalizing/ready/failed |
| revision | uint | 必填 | 录制实例修订号 |
| recordingId | string | 必填 | 实例ID |
| contentRef | string | ready必填 | 鉴权录制文件引用 |
| durationMs | uint | ready必填 | 实际可播放时长 |
| reason | string | failed/自动paused必填 | 原因 |
| requestToken | string | 主动paused且无reason必填;其他后续事件可选 | 关联原控制token;自动paused仍必须reason,failed始终必须reason |
主动 pause 的独立事实携带 requestToken 且不携带 reason;自动暂停必须给出固定原因。无原因又无 requestToken 的 paused 拒绝,不能将未知中断解释为用户主动暂停。失败终态即使有关联 token 也仍要求原因。Go/C++ 严格解析器采用同一条件。
{
"msgToken": "s15-35",
"method": "recordingState",
"sessionId": "s15-session",
"data": {
"state": "starting",
"revision": 1,
"recordingId": "rec-1"
},
"code": 200
}对应S15-M02;其他操作按条件字段校验。
playbackControl · SIG↓
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| operation | string | 必填 | load/play/pause/seek/setRate/stop |
| expectedRevision | uint | 必填 | 播放器修订号 |
| playbackId | string | 必填 | 播放实例 |
| contentRef | string | 仅load允许且必填 | 1~512字节授权文件或录像的opaque引用,不是下载URL或本地文件路径 |
| positionMs | uint | 仅seek允许且必填 | 目标位置,0是合法起点 |
| rate | number | 仅setRate允许且必填 | 0.5/1/1.5/2,不能用近似值 |
| mediaRevision | uint | 历史流必填,文件流禁止 | 本Peer媒体代次;初始1,seek按原持久在途意图切换到m+1,不等于expectedRevision |
所有uint取0~9007199254740991,mediaRevision必须大于0;缺必填字段、重复键、未知字段、显式null和字符串数字均拒绝。平台下行必须有正eventSeq及sessionId,不接messageSeq或code。play/pause/stop不携带contentRef、positionMs或rate,load不能夹带seek或倍率字段。引用可以有命名空间(例如asset:media-1),但不能把下载URL、绝对路径、路径回退或data:内嵌Base64直接塞入contentRef;此语法检查不替代媒体模块的归属、授权期限、重定向及SSRF检查。
历史分支仍设计接线待实现:仅load/play/pause/seek/stop,倍率固定1,setRate明确拒绝。seek在当前m受理,原token只保留一次m+1,先关闭旧Peer及播放缓冲再新建两个Peer;未完成新协商前不发新媒体。两端新Peer实际就绪后报告实际位置并保留原playing/paused意图,不能因重协商解除暂停。失败关闭新旧资源,不回退旧m;其他历史实例和实时预览不受影响。文件默认解析/执行入口仍拒绝mediaRevision,不将历史许可套为本地输出焦点。
实现状态:Go和可移植C++已有独立严格解析入口,共享C++另有异步文件实例执行层;生产播放器分派、真实驱动、焦点和MCP调用链尚未接通。 本组件不让设备上报已支持mediaPlayback,也不让播放命令开启麦克风或摄像头。现行AI及IPC运行时不因为存在解析器或执行状态机而自动支持播放器;接入与验证边界见支持范围。
{
"msgToken": "s15-43",
"method": "playbackControl",
"sessionId": "s-player",
"params": {
"operation": "load",
"expectedRevision": 0,
"playbackId": "player-1",
"contentRef": "<authorized-recording>"
},
"eventSeq": 1
}对应S15-M14;其他操作按条件字段校验。
playbackState · SIG↑
- 方向:设备→平台;应答:—。
- 触发、权限与状态:原token应答指实际状态,执行长操作先seeking,完成新事件playing;自然播放结束为ended,主动停止stopped,不能用网络发送完成替代。设备主动状态上报无code;平台按来源校验并通知原控制应用。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S15。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| state | string | 成功应答或主动事件必填 | loaded/playing/paused/seeking/ended/stopped/failed;失败应答不携带 |
| revision | uint | 成功应答或主动事件必填 | 播放器修订号;失败应答不携带 |
| playbackId | string | 成功应答或主动事件必填 | 实例;失败应答不携带 |
| positionMs | uint | 成功必填 | 实际位置 |
| rate | number | 成功必填 | 实际倍率 |
| reason | string | 失败应答或主动failed必填 | 固定脱敏原因;成功状态不携带 |
| durationMs | uint | 已知时必填 | 真实时长 |
| mediaRevision | uint | recordPlayback成功应答及主动状态必填;文件禁止 | 实际Peer代次;seeking为原m+1,迟到旧m由历史Owner/客户端隔离 |
原命令成功应答code=200,data必须含state/revision/playbackId/positionMs/rate(位置及修订号即使为0也不能省略);state不得为failed。失败应答code=4xx/5xx且data仅有reason,不夹带playing等成功字段;不使用202代替实际状态。设备主动状态事件不带code/eventSeq/messageSeq,loaded/playing/paused/seeking/ended/stopped沿用成功字段;主动failed仅含state/revision/playbackId/reason。已知durationMs不得小于实际positionMs。平台必须另核对原会话/实例/在途token/修订号和终态,语法通过不能让迟到playing复活已停止实例。
历史成功/普通自主状态另外必须含正mediaRevision且rate=1,自主failed另外含mediaRevision但不伪造位置;失败ACK仍严格仅reason,通过原token绑定旧操作。released是整个播放器所有代次的资源事实,不带mediaRevision或成功播放字段;不能以当前Peer关闭声称旧编码器/回调也已停止。解析通过不等于实际档案或当前媒体获得许可。
文件资源释放事实(独立正文)
复用playbackState,data仅下列三个字段,不含state/revision/位置/倍率,不带code/eventSeq/messageSeq。msgToken复用成功接收的原平台sessionEnded事件token,不是stop应答,不产生ACK。
| 字段 | 类型 | 必填条件 | 含义 |
|---|---|---|---|
| playbackId | string | 释放事实必填 | 原子会话固定播放器实例 |
| released | boolean | 释放事实必填且仅true | 驱动确认本实例整组输出实际释放 |
| endEventSeq | uint | 释放事实必填,大于0且不超过9007199254740991 | 原sessionEnded事件水位 |
{"msgToken":"s15-file-terminal","method":"playbackState","sessionId":"s15-file-child","data":{"playbackId":"player-1","released":true,"endEventSeq":9}}未知/断连/固定等待不能代替事实;缺省不代表释放,false/null和混合播放字段拒绝。平台按已鉴权Topic关联原企业/主体、固定播放器、Owner、终态token/水位及保留窗口;原事实幂等,不续租、不延长保留、不改变播放Actual或影响父AI。媒体许可到期不阻止实际释放收敛。Core解析/持久快照/正式RPC、Things严格鉴权转发及共享C++生成已分层实现;正式桌面MQTT文件宿主、焦点归还和完整MCP/E2E待接线。本地发布受理不保证平台持久收录,背压重试保持原字节。对应S15-M33。
主动失败示例(不是load命令失败的应答):
{"msgToken":"decode-failed-event","method":"playbackState","sessionId":"media-child","data":{"state":"failed","revision":3,"playbackId":"player-1","reason":"decodeFailed"}}原控制失败示例:
{"msgToken":"play-1","method":"playbackState","sessionId":"media-child","code":409,"data":{"reason":"resourceBusy"}}{
"msgToken": "s15-43",
"method": "playbackState",
"sessionId": "s-player",
"data": {
"state": "loaded",
"revision": 1,
"playbackId": "player-1",
"positionMs": 0,
"rate": 1,
"durationMs": 30000
},
"code": 200
}对应S15-M15;其他操作按条件字段校验。
broadcastControl · SIG↑
- 方向:设备→平台;应答:broadcastState。
- 触发、权限与状态:liveBroadcast使用WebRTC媒体,不等于文件群发。平台按每个接收设备建会话腿和权限,支持音频或音视频;分区名单取平台配置快照。emergency必须有紧急广播权限,仅抢占输出,不能因此开启被叫麦克风/摄像头。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S16。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| operation | string | 必填 | start/subscribe/unsubscribe/stop |
| expectedRevision | uint | 必填 | 广播组修订号 |
| broadcastId | string | 必填 | 业务广播组ID |
| zoneIds | string[] | start必填 | 授权分区 |
| sourceTrackId | string | start必填 | 已协商音视频源 |
| priority | string | start必填 | normal/emergency |
{
"msgToken": "s16-51",
"method": "broadcastControl",
"sessionId": "s16-session",
"params": {
"operation": "start",
"expectedRevision": 0,
"broadcastId": "broadcast-1",
"zoneIds": [
"zone-a"
],
"sourceTrackId": "broadcast-audio",
"priority": "emergency"
}
}对应S16-M01;其他操作按条件字段校验。
broadcastState · SIG↓
- 方向:平台→设备;应答:—。
- 触发、权限与状态:start受理为starting;各接收端媒体就绪才active或partial,离线端不阻塞其他端。实时广播不对离线端补播;若要补播需独立异步messageDeliver。结束释放各腿和焦点,恢复遵循focusState。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S16。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| state | string | 必填 | starting/active/partial/stopped/failed |
| revision | uint | 必填 | 组修订号 |
| broadcastId | string | 必填 | 组ID |
| recipients | Recipient[] | 必填 | 每端pending/connected/failed/ended及reason |
| requestToken | string | 后续事件可选 | 原控制token |
{
"msgToken": "s16-51",
"method": "broadcastState",
"sessionId": "s16-session",
"data": {
"state": "starting",
"revision": 1,
"broadcastId": "broadcast-1",
"recipients": [
{
"endpointId": "speaker-a",
"state": "pending"
},
{
"endpointId": "speaker-b",
"state": "pending"
}
]
},
"code": 200
}对应S16-M02;其他操作按条件字段校验。
endpointControl · SIG↑
- 方向:设备→平台;应答:endpointState。
- 触发、权限与状态:跨端接续先邀请目标并独立协商,目标连通/用户确认前保留原端。commit原子转移参与者端绑定并撤销未声明对应能力的端发送权限;同一用户不双端同时发声。不同用户接管属于callControl.transfer,不复用接续权限。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S18。
AI接续通知与失败收尾(组件已验): 原prepare成功的endpointState应答是已受理操作的历史事实,不因候选已推进ready而失效。平台仍按原队列次序投递原应答、再投递ready,不跳过前序;历史应答只保留原token、原修订和原字节,不提升当前输入许可、模型scope或设备权限。源端投递核其已绑定的控制能力,不要求源端具有目标接听能力;目标准入仍独立严格核验。原模型致命失败时,原会话结束、尚未提交候选的failed/mediaFailed及目标公开腿唯一sessionEnded同事务提交;写入失败全部回滚,不靠设备本地邀请期限代替平台终态。该收尾不迁移scope、不创建新模型、不恢复已停止的采集,也不重复关闭实际资源。
原scope请求已经发送但尚未收到模型确认时,平台只停止原模型和双端资源,不将未知结果视作ready或commit,也不回退并重签旧授权。失败终态仅凭同一原请求、候选修订、Owner、实际停止事实及原源绑定提交;第二次接续使用最后已确认提交的源公开腿,不能以新候选身份替换原源。父会话、候选和唯一目标终态仍同事务收敛,重复结束与迟到scope确认不得复活。已经committed或模型已确认的记录不走此未提交候选分支,其当前端终止仍遵循已提交路径。上述是后端组件契约与测试结果,不表示完整三端实际媒体接续已验收。
同模型UDP成功移交立即撤销旧媒体许可并停止原桥,但旧监听socket在原候选固定剩余预算内只弃包,随后回收,不以提前关端口代替正式源退场通知。原单调截止与原deadline剩余量取最短,不从commit重新计时;实际设备采集/播放停止仍核原驱动和focus回执。退休端口不授权旧输入/回复,超时不表示设备released;未知scope失败和普通终止仍全部关闭。详见支持范围。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| operation | string | 必填 | prepare/commit/abort |
| expectedRevision | uint | 必填 | 端切换修订号 |
| handoffId | string | 必填 | 幂等接续事务 |
| target | Party | prepare必填 | 同一用户授权终端 |
| candidateSessionId | string | commit必填 | 目标已建立会话腿 |
{
"msgToken": "s18-62",
"method": "endpointControl",
"sessionId": "s18-session",
"params": {
"operation": "prepare",
"expectedRevision": 0,
"handoffId": "handoff-1",
"target": {
"kind": "endpoint",
"id": "tablet-a"
}
}
}对应S18-M01;其他操作按条件字段校验。
应用interaction.open的候选显式关联
对目标端明确确认的应用IPC预览或IM额外成员open增加可选params.handoff。普通open省略该字段行为不变;不能传入null或空对象,拒绝未知/重复字段。它不新增method或Topic,不传入设备sessionInvite,也不是客户端上报ready。应用HTTP外层及普通open其余字段见应用接口。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| params.handoff | object | 普通open可省;明确接续时必填 | purpose=ipcLiveView或已有额外会议成员ipcTalk;只含下列两字段 |
| params.handoff.sourceSessionId | string | handoff存在时必填 | 64字符内合法原会话ID;必须仍属原prepare及同一摄像头/监听范围,会议还要求原callId/成员实例/设备锚点 |
| params.handoff.handoffId | string | handoff存在时必填 | 128字符内合法原prepare事务ID,固定30秒内唯一绑定候选 |
{"msgToken":"target-open-original","method":"interaction.open","target":{"productID":"example-product","deviceName":"example-device"},"params":{"purpose":"ipcLiveView","cameraId":"front","handoff":{"sourceSessionId":"source-preview","handoffId":"handoff-original"}}}源端不得代目标确认;目标必须用自己同用户已注册端点提交。同事务另一候选或代次不允许替换已绑定腿,资源配额不足仍拒绝并保持原端。重复原open重放原结果,不分配第二媒体或推进ready;过期、无授权、并行串腿冲突不降级为普通open。
会议接续不创建第二IM成员,不放宽原人数或单设备扬声器预算;目标即使真实连通也没有混音输入/输出,待正式commit移交同一原AudioLeg。原MAC禁麦许可不会因换端解除,结束旧APP或候选仅通知该应用,不能向原共享设备发送sessionEnded。初始设备双端控制者不能使用额外成员入口规避设备生命周期。
endpointState · SIG↓
- 方向:平台→设备;应答:—。
- 触发、权限与状态:prepare最多30秒,超时保留原端;commit同token幂等,重复不能二次切换。未声明对应能力的端收到committed后停止本地采集播放并结束旧腿;迟到未声明对应能力的端媒体因端授权失效被丢弃。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S18。
revision是原会话范围的独立接续修订号;无code的主动状态使用原会话全局eventSeq,不以接续revision充当事件水位。原操作成功应答code=200且无eventSeq,failed应答须code>=400,主动失败/超时事件无code。公开reason白名单为handoffTimeout、userCancelled、mediaFailed、permissionRevoked、sourceChanged;执行层分别表达超时、取消、媒体故障、权限撤销、原源变化,不将任意失败统写为超时。仅failed/aborted携带reason,只有ready/committed携带candidateSessionId。准备或ready均不撤销原端;abort/超时仅清理该事务已绑定且Owner代次匹配的候选,不得误停同ID新代次。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| state | string | 必填 | preparing/ready/committed/aborted/failed |
| revision | uint | 必填 | 接续修订号 |
| handoffId | string | 必填 | 事务 |
| candidateSessionId | string | ready/committed必填 | 目标腿 |
| reason | string | failed/aborted必填 | handoffTimeout/userCancelled/mediaFailed/permissionRevoked/sourceChanged;其余状态禁止 |
{
"msgToken": "s18-62",
"method": "endpointState",
"sessionId": "s18-session",
"data": {
"state": "preparing",
"revision": 1,
"handoffId": "handoff-1"
},
"code": 200
}对应S18-M02;其他操作按条件字段校验。
focusControl · SIG↓
- 方向:平台→设备;应答:focusState。
- 触发、权限与状态:仅平台在鉴权业务动作后发起,不能自行续长授权;优先级emergency>call>conversation>background,紧急类仅默认抢speaker。suspend保存恢复令牌和用户意图版本;restore只有原会话存活、授权有效、意图未变化且无更高优先级时允许。隐私或用户停止永远优先。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S16、S18。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| operation | string | 必填 | acquire/suspend/restore/release |
| expectedRevision | uint | 必填 | 设备资源修订号 |
| focusId | string | 必填 | 焦点租约ID |
| resources | string[] | 必填 | 1~16项且不重复:microphone/speaker/display/camera:ID;camera:ID整体最多128字节,ID非空且不含空白、控制字符、斜杠或反斜杠;display为设备默认显示输出,不是摄像头采集 |
| priority | string | 必填 | background/conversation/call/emergency |
| resumePolicy | string | 必填 | never/explicit/ifUnchanged |
| expiresAt | int64 | 仅acquire/restore必填 | 正整数Unix毫秒截止,最大9007199254740991;suspend/release不得携带,不隐含续租 |
{
"msgToken": "s16-52",
"method": "focusControl",
"sessionId": "s16-music-receiver",
"params": {
"operation": "suspend",
"expectedRevision": 0,
"focusId": "music-focus",
"resources": [
"speaker"
],
"priority": "emergency",
"resumePolicy": "ifUnchanged"
},
"eventSeq": 1
}对应S16-M03;其他操作按条件字段校验。
display用于视频播放与视频通话的显示输出,和camera:ID采集资源独立。音乐仅申请speaker;无声视频仅申请display;带音轨视频须一次申请["speaker","display"],按整组原子取得或拒绝,不能部分取得后谎报成功。设备没有显示驱动时拒绝display,不得退化成摄像头资源或仅播声音却回报视频播放成功。能力集合不是每次必须占用的全集;C++分派与后端能力检查已支持声明内的非空申请组,各原租约随后固定完整组,缺项回执仍失败。完整实际全局驱动及端到端联调仍待完成,不改变现行设备协议。
AI转人工第三屏障复用原操作,不新增transfer焦点动作或自报来源字段。原AIsuspend与本端新人际腿acquire必须由平台原escalate账本关联;设备各自按原sessionId/focusId执行,不能按“当前会话”猜目标。两请求都携带完整microphone/speaker组,全局expectedRevision从原实际回执推进;priority=call本身不能覆盖旧租约,须先完成原组suspend。原租约不存在或端未实际声明整组驱动能力时明确拒绝,不以speaker租约补造microphone。后端已接入原prepared出处的有限条件准入,普通negotiating会话及未声明对应能力的端规则不变;完整宿主实态移交与最终路由仍待闭环。
完整取得包括两端:双Peer prepared后,先在目标原remote腿发M67同合同的focusControl.acquire,收到该目标原token/M68同合同的完整focusState.acquired,才发本端M65/M66,再发本端M67/M68。目标取得使用目标自己的首次完整idle账本、全局CAS、focusId和原连接,不使用本端AI租约;目标已有AI占用、未知状态或在途控制均拒绝,不自动暂停或抢占。两端acquire.expiresAt同为原持久HumanBusinessDeadline,操作和实际ACK均受原FocusDeadline及各自短Owner租约约束;最终三CAS仍须复核两端当前实际租约。已实现的Queue/ACK与生成RPC回归不等于真实双端物理资源取得或最终transferred。
AI转人工须分别持久化业务授权截止和在途阶段截止:内部HumanBusinessDeadline创建时固定为原AI已配置、已授权的会话Deadline(若当前IM双方授权另有更早截止,取最早),与两个人际腿的业务Deadline一致;不从设备请求、Redis忙线TTL或固定长常量生成。30秒邀请、45秒候选、首次双Peer准备后的15秒FocusDeadline只限制在途,最终提交不续期。M67 acquire.expiresAt使用原持久人工业务截止,操作和原回执仍须在焦点阶段截止前完成;旧意图省略这些内部来源时不能补长授权或完成最终移交。这些不是新增公开报文字段,短Owner租约、当前连接及双方权限仍须持续复验,业务截止真正关闭Peer;原AI模型结束不能删除已独立获准的人际组。当前已实现期限分离与准备阶段持久化,最终路由及持续生命周期仍须实际屏障接线验证。
设备资源修订号为连接内全局安全整数0~9007199254740991;原请求实际成功改变资源状态后才报告expectedRevision+1,不能因接纳或MQTT确认推进。重复原token重放原结果,不再次推进;达到整数上界不能溢出或回零。请求eventSeq必填,原应答不回显平台事件序号。租约的sessionId/focusId和完整资源组必须保持原关联,集合顺序不同不构成资源变化,但同token改写报文仍按公共幂等冲突处理。priority不是设备自行提权的授权,悬挂/恢复仍须核验原会话、当前权限与用户意图;这些条件不是JSON解析器的职责。
关闭与重新开启分开授权:Live子会话平台终态、源许可到期或父AI结束后,不再允许acquire/restore/suspend;同一原连接的已实际持有租约仍可按原完整组、原focusId/sessionId及当前CAS执行有限release。端侧必须保有原授信会话、已校验平台子会话终态、实际媒体退出及固定保留窗口;本地关闭、未知连接或仅取消受理不能产生此证明。父AI切换也不能借新父重新开启旧节目。原物理组已停止不等于租约released,须新的完整关闭票据实际完成后才回原focusState;未完成释放的执行器不能因槽容量被退役。云端Owner清理根据原持久媒体清理记录派生,不依赖存活的媒体注册表、不刷新源许可;在途关闭保留原token、字节和截止,不改作新请求。内部关闭来源和release_only不增加设备字段或模型输入。断网、当前主人/连接失效或证明不足保持未知,不伪造成功。
AI转人工的旧AI正式关闭另核原最终四通知ID/SHA均已投递,之后才排原AI session/focusId的完整组release,固定十秒内原最早截止且不延长业务或Owner许可。原实际成功回执才写释放墓碑并推进连接全局资源修订;新人际租约实态可能仍是较早修订,后继人工控制必须采用当前全局水位,不把旧AI释放当作释放人工资源。原token重放不推进修订;错误连接实例、半组、迟到或未知均不能恢复旧AI或造关闭成功。此专属ended来源不放宽普通终态会话的焦点准入;原本人授权私有投递仍须核精确墓碑、人工实际路由、原目录及原接收实例。上述已补受控SQL/RedisLua/Pion与生成RPC回归,仍非真实共享宿主端云验收。
正式旧AI释放墓碑缺失、在途或未知时,合法人际hold/resume保持在途拒绝,不排双方焦点命令、不停原RTP、不新增控制账本;不能依赖页面按钮阻止竞态。原staleRevision/invalidState拒绝及已完成响应精确重放仍不执行资源操作。人工业务截止或原Owner失效照常关闭原实际组,不能被释放在途遮蔽。
AI跨设备接续的目标取得是另一条独立出处:endpointState.committed及实际UDP/Peer交换完成后,目标仍不得输入;平台向目标公开sessionId发送完整microphone/speaker组的acquire,priority=conversation、resumePolicy=explicit,沿原连接全局修订执行。Owner仅固定一次token、正文和不超过两秒的请求截止;acquire.expiresAt保留原业务期限,重投不续长。只有该原token的完整实际acquired回执、当前物理连接及fresh核权均成立才解除媒体屏障,初建未要求focus不构成目标端豁免。这里不借旧创建sessionId向目标另建模型,也不增加报文字段。
当前目标挂断时,平台沿同一原组排独立release(无expiresAt),设备须两资源实际停止后才回完整released。已持久的原释放允许在模型终态后的固定请求期限内收尾;精确公开腿、token、当前epoch/instance、完整组和原Pending缺一即拒绝,不接受新的取得或恢复。模型终态只证明模型结束,不证明HAL已释放;未知、过期或未取得不得伪造released。正式Owner/SQL/UDP及DMS定向竞态证据见支持范围,C++端云仍待验收。
实现状态:Go及C++已有严格focusControl/focusState解析与原请求全组关联,另有支持范围、支持范围和支持范围。独立原回执已接支持范围。正式桌面已接三组实际末端与首次idle;后端持续Owner和有限终态释放已补定向集成,当前完整验证记录见支持范围,MCP实际媒体端云验收继续。首次idle及Owner续租仍核验全部管理资源,不因允许单资源申请放宽。C++固定原租约异步执行器仍须显式许可及全局共享驱动;端侧优先级仲裁、完整资源组实际驱动与MCP合并E2E继续实施,见支持范围。不能以报文解析或夹具通过宣称焦点已取得,不隐含增加设备能力。
focusState · SIG↑
- 方向:设备→平台;应答:—。
- 触发、权限与状态:设备实际停播/停采集后确认,不能只靠云端逻辑报告已切换。租约到期本地释放;断线不凭旧restore重启麦克风。全双工AI的AEC能力与资源焦点是两个门槛;文件输出不因申请speaker而隐含要求AEC或取得microphone。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S16、S18。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| state | string | 必填 | acquired/suspended/restored/released/denied |
| revision | uint | 必填 | 设备资源修订号 |
| focusId | string | 必填 | 焦点ID |
| resources | string[] | 必填 | 原请求完整集合;成功不得缩减集合,拒绝也须保留完整目标组;成功时为实际确认组,denied时仅标识被拒绝的目标组,不表示已持有;display只表示显示输出 |
| reason | string | 仅denied必填 | 固定公开原因:permissionDenied/resourceBusy/unsupportedResource/staleRevision/leaseExpired/invalidState/userIntentChanged/sessionEnded/timeout/driverFailed;成功不得携带,不能透传驱动错误、URL或凭据 |
原操作应答带原msgToken/sessionId和完整focusId/resources:成功code=200及动作对应状态,拒绝code=400~599和state=denied。拒绝不推进资源修订号,返回设备当前实际修订号;例如过期请求expectedRevision=0被拒时当前可能已经是5,不能回显0伪造当前状态。实际主动状态事件可无code,但不能拿来完成一个正在等待原回执的操作;停流未知、驱动断连或排队成功不得报released。成功应答资源集合必须等于原完整请求,返回speaker但遗漏display不能认定带音轨视频已取得输出组。
用于AI转人工时,整组acquired是第三屏障的设备完成事实,仍不是平台路由已提交。平台须持久关联原token、两端腿/呼叫组、原连接、全组资源与全局修订号,复核授权/截止后确认路由提交;才能发最终sessionEstablished及原AI transferred/ended。失败补偿的restore也必须有原token的完整组实际restored回执,不以模型仍在线冒充采集已恢复;未知结果或已经提交的路由不得盲目回滚。无code主动事件、单轨trackState和mediaState.connected均不能完成这条屏障。
{
"msgToken": "s16-52",
"method": "focusState",
"sessionId": "s16-music-receiver",
"data": {
"state": "suspended",
"revision": 1,
"focusId": "music-focus",
"resources": [
"speaker"
]
},
"code": 200
}对应S16-M04;其他操作按条件字段校验。
当前原code回执已接设备入口及Core Runtime持久关联,详见支持范围。无code主动事件仍为扩展契约,须确认支持,不是可信空闲基线;共享解析器支持该结构不等于后端受理。原字节幂等只读确认不重投递或恢复资源,实际全组驱动及MCP端云媒体E2E仍待完成。
sessionSync · SIG↑
- 方向:设备→平台;应答:sessionSnapshot。
- 触发、权限与状态:用于后台恢复/事件缺口/断线后查询,不自动恢复采集和播放。重新鉴权并确认端绑定;未声明对应能力的端epoch失效403。平台返回绝对快照,不无限重放历史内容或设备写操作。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S19。
IPC 对讲全量名册子集正在实现,尚未完成端云验收。须独立声明并协商 participantRosterSync(依赖 participantRoster),旧增量名册消费者不会自动接收新快照。该子集只读查询本腿展示,授权与资产核验在原 Owner 锁外,最多 2 秒;不代替本场景设计中的 15 秒重连、旧 socket 围栏或媒体代次恢复。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| lastEventSeq | uint | 必填 | 已应用信令水位 |
| lastMessageSeq | uint | 必填 | 已应用内容水位 |
| endpointEpoch | uint | 必填 | 平台分配的公开端腿绑定代次;由可信 sessionInvite/sessionCreated 条件返回,不由设备猜 1,也不是内部 ConnectionEpoch 时间戳 |
| mediaRevision | uint | 必填 | 本端已知媒体代次 |
{
"msgToken": "s19-72",
"method": "sessionSync",
"sessionId": "s19-session",
"params": {
"lastEventSeq": 12,
"lastMessageSeq": 8,
"endpointEpoch": 1,
"mediaRevision": 1
}
}对应S19-M01;其他操作按条件字段校验。
sessionSnapshot · SIG↓
- 方向:平台→设备;应答:—。
- 触发、权限与状态:安装快照后丢弃不大于水位的迟到事件,再应用更高序号;缺增量文本时以快照内最终文本恢复;快照不含正文时将缺口标不可恢复,不能拼接残缺文本,也不重播旧音频。resumeAllowed仍需焦点和媒体重新协商,不能直接恢复收费Provider或后台录音。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S19。
成功快照使用原请求 msgToken/本接收腿 sessionId、code:200 和新的共享 eventSeq,其中 eventWatermark == eventSeq。原 token 重放原字节,不生成第二份快照、不推进水位、不延长任何期限。若等待期间已安装更高水位,旧快照不得回滚该实态;原 token 结果过期或水位落后时标同步未知,使用下一新 token 查询,不自动重做设备操作。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| state | string | 必填 | negotiating/established/ending/ended |
| revision | uint | 必填 | 会话快照修订号 |
| eventWatermark | uint | 必填 | 快照信令水位 |
| messageWatermark | uint | 必填 | 内容水位 |
| endpointEpoch | uint | 必填 | 当前端代次 |
| mediaRevision | uint | 必填 | 当前媒体代次 |
| tracks | Track[] | 必填 | 本端授权轨 |
| controls | ControlSnapshot | 必填 | 呼叫、焦点、抢麦、媒体计划、AI输入、录制、播放、处理器、广播和接续完整快照 |
| capabilityRevision | uint | 必填 | 此端已接受的最新能力上报revision |
| resumeAllowed | boolean | 必填 | 仅允许尝试恢复 |
| reason | string | ended或不准恢复必填 | ended为权威终止原因;established且resumeAllowed=false为snapshotOnly。established且resumeAllowed=true必须省略该键,不能发送空字符串或null |
| participants | Participant[] | participantRosterSync 已协商时必填 | 本腿当前完整展示名册,最多 32 项且 participantId 唯一;当前 IPC 生产子集每项 tracks 明确 []。[] 合法,原子撤全部展示但不自动关闭主媒体;null/缺省/部分合法数组不得安装 |
| expiresAt | uint | participantRosterSync 已协商时必填 | Unix 毫秒,安全整数且非 0;不晚于本次原 2 秒权威许可、Owner/session 租约和 deadline。重投不刷新;旧未协商快照不增加此字段 |
公开绑定在新端初建时由平台分配 endpointEpoch=1、采用实际能力 capabilityRevision,只在协商了同步的可信邀请/创建结果中返回。旧持久能力没有两字段视为未协商,不回填或猜值。设备普通控制重连与端替换是不同事实:内部鉴权 ConnectionEpoch 必须独立复验;完整断网接续、代次递增与旧 socket 围栏仍待后继实施,不能据同连接查询称完成。
当前 IPC 活会话投影使用 state=established、mediaRevision=1、resumeAllowed=true 且省略 reason;设备也接受显式 resumeAllowed=false、reason=snapshotOnly 的只读形态。两者安装快照本身都不恢复媒体,许可不等于驱动已恢复。state=ended 必须 resumeAllowed=false,保留持久终止原因并撤空轨和名册,由设备释放原资源。controls 仍须完整:本独立腿没有 call/focus/floor/AI 控制对象,用 null;recordings/playbacks/processors/broadcasts/handoffs 明确 [];mediaPlan 包含原轨及实态。这些 null/[] 只描述本腿,不意味着已有 IM 会议没有呼叫或 MAC,也不授发言资格。活快照不启停麦克风、Peer、订阅、计费模型或驱动。
正常媒体周期续验可使内存短期授权证据及已生效MAC版本晚于持久记录;查询事务只保存同一IM加入实例的单调MAC版本和新证据截止(仍不超过当前2秒窗口),禁止版本回退或同版本改变话权,其余身份、源轨、控制、会话deadline及租约不变。这不是由查询延长媒体许可或新增发言资格;查询不调用媒体授权更新接口。慢查询期间若媒体续验已替换原证据,查询失败且不覆盖新许可;原通话继续,后续查询使用新token重新读取。
端侧一次校验全部字段、当前腿、原 token、公开绑定、截止和共享水位,再原子替换名册;使用既有墙钟高水位及单调窗口防时钟倒退。过期或迟到保留原已消费名册和主媒体,不能把未知推成 members=[] 或权限撤销。明确权威撤权仍由原授权终止路径停流。
新子集可解析的拒绝示例(没有成功快照水位,也没有媒体恢复许可):
{"msgToken":"roster-sync-1","method":"sessionSnapshot","sessionId":"ipc-device-leg","code":409,"data":{"requestMethod":"sessionSync","reason":"requestConflict"}}{"msgToken":"roster-sync-2","method":"sessionSnapshot","sessionId":"ipc-device-leg","code":403,"data":{"requestMethod":"sessionSync","reason":"requestDenied"}}入口固定拒绝还包括 400/invalidRequest、422/unsupportedMethod、503/signalingNotEnabled,采用同样两字段data。设备只结束匹配原token的查询并显示failed,停止该请求重试;不清空当前名册或关闭主通话。未知/畸形应答不安装,仍由原30秒请求预算收敛为unknown。
新 IPC 同连接子集的完整成功示例(时间、会话及成员均为占位;名册为空合法,不能借此结束媒体):
{
"msgToken": "roster-sync-3",
"method": "sessionSnapshot",
"sessionId": "ipc-device-leg",
"code": 200,
"eventSeq": 12,
"data": {
"state": "established",
"revision": 11,
"eventWatermark": 12,
"messageWatermark": 0,
"endpointEpoch": 1,
"mediaRevision": 1,
"capabilityRevision": 3,
"tracks": [
{"trackId":"mic-1","kind":"audio","sourceId":"mic","direction":"sendonly","codec":"opus","state":"active"},
{"trackId":"speaker-1","kind":"audio","sourceId":"speaker","direction":"recvonly","codec":"opus","state":"paused"}
],
"controls": {
"call": null,
"focus": null,
"floor": null,
"ai": null,
"recordings": [],
"playbacks": [],
"processors": [],
"broadcasts": [],
"handoffs": [],
"mediaPlan": {
"revision": 1,
"tracks": [
{"trackId":"mic-1","kind":"audio","sourceId":"mic","direction":"sendonly","codec":"opus","state":"active"},
{"trackId":"speaker-1","kind":"audio","sourceId":"speaker","direction":"recvonly","codec":"opus","state":"paused"}
]
}
},
"participants": [],
"resumeAllowed": false,
"reason": "snapshotOnly",
"expiresAt": 1900000000000
}
}以下仍是通用控制恢复的设计示例,不是当前 IPC 名册子集的生产通过证明:
{
"msgToken": "s19-72",
"method": "sessionSnapshot",
"sessionId": "s19-session",
"data": {
"state": "established",
"revision": 5,
"eventWatermark": 18,
"messageWatermark": 10,
"endpointEpoch": 1,
"mediaRevision": 1,
"tracks": [
{
"trackId": "mic",
"kind": "audio",
"sourceId": "mic",
"sourceType": "microphone",
"direction": "sendonly",
"codec": "opus",
"state": "requested"
}
],
"controls": {
"call": {
"state": "active",
"revision": 1
},
"focus": {
"state": "suspended",
"revision": 2,
"focusId": "focus-before-sleep",
"resources": [
"microphone",
"speaker"
]
},
"floor": null,
"recordings": [],
"playbacks": [],
"processors": [],
"mediaPlan": {
"revision": 0,
"tracks": [
{
"trackId": "mic",
"kind": "audio",
"sourceId": "mic",
"sourceType": "microphone",
"direction": "sendonly",
"codec": "opus",
"state": "requested"
}
]
},
"broadcasts": [],
"handoffs": [],
"ai": null
},
"resumeAllowed": true,
"capabilityRevision": 1
},
"code": 200
}对应S19-M02;其他操作按条件字段校验。
interaction.control · APP↑
- 方向:应用→平台;应答:interaction.result。
- 触发、权限与状态:沿用鉴权API,服务端由登录态定位参与端,不能在arguments自报操作者。云端命令直接处理;设备执行命令转发并记录应用token与设备token映射。HTTP202后interaction.result.data.result原样给对应成功状态正文,失败仍顶层code/data.reason;独立状态经interaction.controlState投递。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S15、S17。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| command | string | 必填 | 本章设备Control/Update/Sync、capabilityReport/sessionAccept/sessionReject及inputSend/toolCallSubmit/audioStart/audioStop/respCancel;另有云端专属recordingConsent/recordingContent;禁止递归包装 |
| arguments | object | 必填 | 对应设备命令正文;下述云端专属子命令不向设备转发 |
{
"msgToken": "s15-42",
"method": "interaction.control",
"sessionId": "s-player",
"params": {
"command": "playbackControl",
"arguments": {
"operation": "load",
"expectedRevision": 0,
"playbackId": "player-1",
"contentRef": "<authorized-recording>"
}
}
}对应S15-M13;其他操作按条件字段校验。
云端录制应用子命令
| 子命令 | arguments 严格字段 | 权限、关联和效果 |
|---|---|---|
| recordingConsent / grant | operation=grant、recordingId、policyId、expiresAt(绝对毫秒,当前时点后且最多一小时) | JWT本人且属于当前正式参与者;返回consentId/revision/expiresAt/sourceTrackIds/policyRevision。绑定原会话、原器、媒体代次、全员加入epoch和策略代次;不接受自报userId。 |
| recordingConsent / revoke | operation=revoke、recordingId、consentId、expectedRevision | 仅该凭证本人;先阻断实际写入再持久撤销。重放原请求不刷新撤销时间。 |
| recordingControl | 本章原start/pause/resume/stop字段 | 原录制发起者控制;start/resume核验当前全部真实凭证。新成员加入先停副本,重新全员同意后必须显式resume。 |
| recordingContent | recordingId | 原端点、当前设备权限、本人所有权、ready、策略和未撤销/未到期同意均重读;不接收URL、对象路径或存储桶。 |
interaction.result.data 的录制受理正文固定有 operation=interaction.control、command、recordingId,并按上述子命令携带凭证元数据或录制 state/revision。受理完成和原 interaction.controlState(recordingState) 不是同一事件;文件只有实际封装、逐轨解码、私有上传及读回校验成功才进入 ready。停止后首次固定60秒封装截止,迟到产物不允许复活终态。
录制控制在受理前确认的修订冲突、原 token 不同正文冲突或合法 resume 引用失效授权集合,原 Commands HTTP 业务信封返回 code=409、固定脱敏消息 requestConflict;HTTP 状态仍沿原入口,不返回 accepted,也不等待异步 recordingState 才判断拒绝。此类拒绝不新增操作、授权或恢复副本。非法结构与其他接口错误保持原分类,未知存储错误不能冒充确定冲突;旧 AI、IM 与 action 的共享错误适配不改变。
撤权、保留到期、当前权限失败或组件未装配时,本条内容读取投影 code=403、state=failed、reason=permissionDenied,只保留 operation/command/recordingId/revision,不夹带旧contentRef/URL;无关事件仍正常交付。签名装饰内部失败用 code=500/reason=internalError。已签发URL可能在原30秒有效窗口内仍可用,后台按实际删除确认收口;不承诺撤权能回收已被客户端下载的文件。
interaction.controlState · APP↓
- 方向:平台→应用;应答:—。
- 触发、权限与状态:应用独立事件携带顶层sessionId/eventSeq;与设备状态同一事实来源,不冒充请求ACK。新邀请走interaction.invite,不能用纯通知代替用户接听。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S15。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| command | string | 必填 | 对应State/Snapshot/Updated方法 |
| result | object | 必填 | 对应正文,不丢字段 |
{
"msgToken": "recording-ready-app",
"method": "interaction.controlState",
"sessionId": "s15-session",
"eventSeq": 3,
"data": {
"command": "recordingState",
"result": {
"state": "ready",
"revision": 6,
"recordingId": "rec-1",
"contentRef": "<authorized-recording>",
"durationMs": 30000
}
}
}对应S15-M11;其他操作按条件字段校验。
interaction.invite · APP↓
- 方向:平台→应用;应答:interaction.control(sessionAccept/sessionReject)。
- 触发、权限与状态:应用收到完整邀请;msgToken就是邀请token,sessionId是本端候选腿。通过interaction.control答复时沿用token;服务端原子选中首个合格接听者,其余端只撤销候选腿,不挂断胜出者。
- 超时、幂等、迟到及清理采用本页公共行为和公共约定;成功应答不能代替独立完成状态。
- 场景:S17。
| 字段 | 类型 | 必填条件 | 值与含义 |
|---|---|---|---|
| invitation | object | 必填 | 与sessionInvite.params完全一致 |
| endpointId | string | 必填 | 此用户的目标登录终端 |
| callGroupId | string | 必填 | 统一呼叫组 |
{
"msgToken": "invite-a",
"method": "interaction.invite",
"sessionId": "door-leg-a",
"data": {
"invitation": {
"purpose": "humanCall",
"callType": "video",
"admission": "accept",
"transport": "webrtc",
"expiresAt": 1900000000000,
"tracks": [
{
"trackId": "video-new",
"kind": "video",
"sourceId": "front",
"sourceType": "camera",
"direction": "recvonly",
"codec": "H264",
"state": "requested"
}
],
"callGroupId": "door-call",
"sourceEventId": "door-event"
},
"endpointId": "phone-a",
"callGroupId": "door-call"
},
"eventSeq": 1
}对应S17-M01;其他操作按条件字段校验。
更新日志
2026/10/16 16:04
查看所有更新日志
fe3a7-docs(AI与音视频): 按场景整理完整接入流程与命令契约于
