录音录像与媒体播放
约 3373 字大约 11 分钟
2026-10-16
本页包含已接线核心流程及可选扩展;具体子能力必须按设备、平台与用户授权求交集。参见支持范围、场景索引和命令手册。图中S编号只用于本文定位,不放入实际JSON。
前置条件
通话录制由独立云端录制器处理;IPC本地录像策略仍是物模型。本页还定义recordPlayback/mediaPlayback的播放器控制,二者不是录制控制。
录制同意须涵盖所有被录者、来源、用途与有效期;加入新人时先暂停再补同意。撤权立即停止取流并执行policyId保留/删除策略。生成文件不代表播放;seek返回实际关键帧位置。应用本地播放器按同一playbackState语义回报,不能以服务器转发位置冒充用户播放位置。
D/D2是不同设备参与端,A是应用端,P是平台和媒体节点。各端分别使用鉴权Topic/登录态,不能冒用另一端身份。基础会话与媒体协商见S01/S06,复用时保留本场景sessionId并独立分配密钥和token。
完整时序
报文索引
编号按图阅读;编号保留历史引用,不要求数值连续。字段定义以命令链接为准。
| 编号 | 发送→接收 | Topic/接口 | 方法及契约 | 应答/等待 | 状态或作用 |
|---|---|---|---|---|---|
| S15-M01 | D→P | SIG↑ | recordingControl | recordingState;10秒受理,媒体协商15秒 | |
| S15-M02 | P→D | SIG↓ | recordingState | 应答/状态事件;不等待ACK | |
| S15-M03 | P→D | SIG↓ | recordingState | 应答/状态事件;不等待ACK | |
| S15-M04 | D→P | SIG↑ | recordingControl | recordingState;10秒受理,媒体协商15秒 | |
| S15-M05 | P→D | SIG↓ | recordingState | 应答/状态事件;不等待ACK | |
| S15-M06 | D→P | SIG↑ | recordingControl | recordingState;10秒受理,媒体协商15秒 | |
| S15-M07 | P→D | SIG↓ | recordingState | 应答/状态事件;不等待ACK | |
| S15-M08 | D→P | SIG↑ | recordingControl | recordingState;10秒受理,媒体协商15秒 | |
| S15-M09 | P→D | SIG↓ | recordingState | 应答/状态事件;不等待ACK | |
| S15-M10 | P→D | SIG↓ | recordingState | 应答/状态事件;不等待ACK | |
| S15-M11 | P→A | APP↓ | interaction.controlState | 应答/状态事件;不等待ACK | |
| S15-M12 | P→D | SIG↓ | recordingState | 应答/状态事件;不等待ACK | |
| S15-M13 | A→P | APP↑ | interaction.control | interaction.result;10秒受理,媒体协商15秒 | |
| S15-M14 | P→D | SIG↓ | playbackControl | playbackState;10秒受理,媒体协商15秒 | |
| S15-M15 | D→P | SIG↑ | playbackState | 应答/状态事件;不等待ACK | |
| S15-M16 | P→A | APP↓ | interaction.result | 应答/状态事件;不等待ACK | |
| S15-M17 | P→D | SIG↓ | playbackControl | playbackState;10秒受理,媒体协商15秒 | |
| S15-M18 | D→P | SIG↑ | playbackState | 应答/状态事件;不等待ACK | |
| S15-M19 | P→D | SIG↓ | playbackControl | playbackState;10秒受理,媒体协商15秒 | |
| S15-M20 | D→P | SIG↑ | playbackState | 应答/状态事件;不等待ACK | |
| S15-M21 | P→D | SIG↓ | playbackControl | playbackState;10秒受理,媒体协商15秒 | |
| S15-M22 | D→P | SIG↑ | playbackState | 应答/状态事件;不等待ACK | |
| S15-M23 | P→D | SIG↓ | playbackControl | playbackState;10秒受理,媒体协商15秒 | |
| S15-M24 | D→P | SIG↑ | playbackState | 应答/状态事件;不等待ACK | |
| S15-M25 | P→D | SIG↓ | playbackControl | playbackState;10秒受理,媒体协商15秒 | |
| S15-M26 | D→P | SIG↑ | playbackState | 应答/状态事件;不等待ACK | |
| S15-M27 | D→P | SIG↑ | playbackState | 应答/状态事件;不等待ACK | |
| S15-M28 | D→P | SIG↑ | sessionEnd | 对应应答见命令;10秒受理,媒体协商15秒 | |
| S15-M29 | P→D | SIG↓ | sessionEnded | 应答/状态事件;不等待ACK | |
| S15-M30 | P→D | SIG↓ | playbackControl | playbackState;10秒 | |
| S15-M31 | D→P | SIG↑ | playbackState | 实际状态应答;不等待ACK |
逐条JSON
S15-M01 · recordingControl
{
"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-M02 · recordingState
{
"msgToken": "s15-35",
"method": "recordingState",
"sessionId": "s15-session",
"data": {
"state": "starting",
"revision": 1,
"recordingId": "rec-1"
},
"code": 200
}S15-M03 · recordingState
{
"msgToken": "s15-36",
"method": "recordingState",
"sessionId": "s15-session",
"data": {
"state": "active",
"revision": 2,
"recordingId": "rec-1",
"requestToken": "s15-35"
},
"eventSeq": 1
}S15-M04 · recordingControl
{
"msgToken": "s15-37",
"method": "recordingControl",
"sessionId": "s15-session",
"params": {
"operation": "pause",
"expectedRevision": 2,
"recordingId": "rec-1"
}
}S15-M05 · recordingState
{
"msgToken": "s15-37",
"method": "recordingState",
"sessionId": "s15-session",
"data": {
"state": "paused",
"revision": 3,
"recordingId": "rec-1"
},
"code": 200
}S15-M06 · recordingControl
{
"msgToken": "s15-38",
"method": "recordingControl",
"sessionId": "s15-session",
"params": {
"operation": "resume",
"expectedRevision": 3,
"recordingId": "rec-1",
"consentIds": [
"consent-a",
"consent-b"
]
}
}S15-M07 · recordingState
{
"msgToken": "s15-38",
"method": "recordingState",
"sessionId": "s15-session",
"data": {
"state": "active",
"revision": 4,
"recordingId": "rec-1"
},
"code": 200
}S15-M08 · recordingControl
{
"msgToken": "s15-39",
"method": "recordingControl",
"sessionId": "s15-session",
"params": {
"operation": "stop",
"expectedRevision": 4,
"recordingId": "rec-1"
}
}S15-M09 · recordingState
{
"msgToken": "s15-39",
"method": "recordingState",
"sessionId": "s15-session",
"data": {
"state": "finalizing",
"revision": 5,
"recordingId": "rec-1"
},
"code": 200
}S15-M10 · recordingState
{
"msgToken": "s15-40",
"method": "recordingState",
"sessionId": "s15-session",
"data": {
"state": "ready",
"revision": 6,
"recordingId": "rec-1",
"contentRef": "<authorized-recording>",
"durationMs": 30000
},
"eventSeq": 2
}S15-M11 · interaction.controlState
{
"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-M12 · recordingState
{
"msgToken": "s15-41",
"method": "recordingState",
"sessionId": "s15-session",
"data": {
"state": "failed",
"revision": 2,
"recordingId": "rec-1",
"reason": "recordingConsentMissing"
},
"eventSeq": 4
}S15-M13 · interaction.control
{
"msgToken": "s15-42",
"method": "interaction.control",
"sessionId": "s-player",
"params": {
"command": "playbackControl",
"arguments": {
"operation": "load",
"expectedRevision": 0,
"playbackId": "player-1",
"contentRef": "<authorized-recording>"
}
}
}S15-M14 · playbackControl
{
"msgToken": "s15-43",
"method": "playbackControl",
"sessionId": "s-player",
"params": {
"operation": "load",
"expectedRevision": 0,
"playbackId": "player-1",
"contentRef": "<authorized-recording>"
},
"eventSeq": 1
}S15-M15 · playbackState
{
"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-M16 · interaction.result
{
"msgToken": "s15-42",
"method": "interaction.result",
"sessionId": "s-player",
"data": {
"operation": "interaction.control",
"state": "applied",
"result": {
"state": "loaded",
"revision": 1,
"playbackId": "player-1",
"positionMs": 0,
"rate": 1
}
},
"code": 200
}S15-M17 · playbackControl
{
"msgToken": "s15-44",
"method": "playbackControl",
"sessionId": "s-player",
"params": {
"operation": "play",
"expectedRevision": 1,
"playbackId": "player-1"
},
"eventSeq": 2
}S15-M18 · playbackState
{
"msgToken": "s15-44",
"method": "playbackState",
"sessionId": "s-player",
"data": {
"state": "playing",
"revision": 2,
"playbackId": "player-1",
"positionMs": 0,
"rate": 1
},
"code": 200
}S15-M19 · playbackControl
{
"msgToken": "s15-45",
"method": "playbackControl",
"sessionId": "s-player",
"params": {
"operation": "pause",
"expectedRevision": 2,
"playbackId": "player-1"
},
"eventSeq": 3
}S15-M20 · playbackState
{
"msgToken": "s15-45",
"method": "playbackState",
"sessionId": "s-player",
"data": {
"state": "paused",
"revision": 3,
"playbackId": "player-1",
"positionMs": 0,
"rate": 1
},
"code": 200
}S15-M21 · playbackControl
{
"msgToken": "s15-46",
"method": "playbackControl",
"sessionId": "s-player",
"params": {
"operation": "seek",
"expectedRevision": 3,
"playbackId": "player-1",
"positionMs": 10000
},
"eventSeq": 4
}S15-M22 · playbackState
{
"msgToken": "s15-46",
"method": "playbackState",
"sessionId": "s-player",
"data": {
"state": "paused",
"revision": 4,
"playbackId": "player-1",
"positionMs": 9800,
"rate": 1
},
"code": 200
}S15-M23 · playbackControl
{
"msgToken": "s15-47",
"method": "playbackControl",
"sessionId": "s-player",
"params": {
"operation": "setRate",
"expectedRevision": 4,
"playbackId": "player-1",
"rate": 1.5
},
"eventSeq": 5
}S15-M24 · playbackState
{
"msgToken": "s15-47",
"method": "playbackState",
"sessionId": "s-player",
"data": {
"state": "paused",
"revision": 5,
"playbackId": "player-1",
"positionMs": 9800,
"rate": 1.5
},
"code": 200
}S15-M25 · playbackControl
{
"msgToken": "s15-48",
"method": "playbackControl",
"sessionId": "s-player",
"params": {
"operation": "play",
"expectedRevision": 5,
"playbackId": "player-1"
},
"eventSeq": 6
}S15-M26 · playbackState
{
"msgToken": "s15-48",
"method": "playbackState",
"sessionId": "s-player",
"data": {
"state": "playing",
"revision": 6,
"playbackId": "player-1",
"positionMs": 9800,
"rate": 1.5
},
"code": 200
}S15-M27 · playbackState
{
"msgToken": "s15-49",
"method": "playbackState",
"sessionId": "s-player",
"data": {
"state": "ended",
"revision": 7,
"playbackId": "player-1",
"positionMs": 30000,
"rate": 1.5,
"durationMs": 30000
}
}S15-M28 · sessionEnd
{
"msgToken": "s15-50",
"method": "sessionEnd",
"sessionId": "s-player",
"params": {
"reason": "userHangup"
}
}S15-M29 · sessionEnded
{
"msgToken": "s15-50",
"method": "sessionEnded",
"sessionId": "s-player",
"data": {
"state": "ended",
"reason": "userHangup"
},
"code": 200
}S15-M30 · playbackControl
{
"msgToken": "s15-extra-29",
"method": "playbackControl",
"sessionId": "s15-another-player",
"params": {
"operation": "stop",
"expectedRevision": 0,
"playbackId": "player-stop"
},
"eventSeq": 1
}S15-M31 · playbackState
{
"msgToken": "s15-extra-29",
"method": "playbackState",
"sessionId": "s15-another-player",
"code": 200,
"data": {
"state": "stopped",
"revision": 1,
"playbackId": "player-stop",
"positionMs": 2000,
"rate": 1
}
}文件子会话结束与实际释放
前置:固定文件子会话存在;只关闭本实例,不停主AI输入或其他观看者。释放上报已分层实现Core收录、Things鉴权转发及共享C++生成;正式MQTT文件宿主、焦点/MCP及完整网络联调仍待实现。
| 编号 | 发送→接收 | Topic | 命令、应答与超时 | 实现 |
|---|---|---|---|---|
| S15-M32 | P→D | SIG↓ | sessionEnded;事件无ACK,终态保留窗口内投递 | 当前实现 |
| S15-M33 | D→P | SIG↑ | playbackState;事实无ACK,保留窗口外拒绝 | Core/Things/C++分层实现;完整E2E待验收 |
S15-M32 · sessionEnded
{"msgToken":"s15-file-terminal","method":"sessionEnded","sessionId":"s15-file-child","eventSeq":9,"data":{"state":"ended","reason":"parentEnded"}}S15-M33 · playbackState
{"msgToken":"s15-file-terminal","method":"playbackState","sessionId":"s15-file-child","data":{"playbackId":"player-1","released":true,"endEventSeq":9}}本地先关闭仍需关联随后原平台终态。重复不覆盖首次收录时间;错误主体/实例/水位/token、混合字段、未结束或过期会话拒绝。释放不代表stop工具执行成功,不把unknown改写成未执行或播完。
媒体与本地动作
| 编号 | 路径 | 格式与约束 |
|---|---|---|
| S15-R01 | P→P | 授权媒体副本送录制器,不修改主通话转发 |
| S15-R02 | D→A | WebRTC历史媒体轨或鉴权HTTPS文件播放,不是MQTT |
异常、状态与资源释放
路由与信封见公共约定;阶段性状态不代表最终完成。操作终态时限见命令手册;编号、超时等元信息不发送。
能力不足422、无权限403、资源/修订号冲突409、超时504按S11处理,不静默开启设备能力。同token只重放原结果;事件按eventSeq去重,旧会话/端代次不可恢复。验证本页正常路径、alt分支及支持范围断言。文档通过不代表代码或硬件已实现。
验证入口
更新日志
2026/10/16 16:04
查看所有更新日志
fe3a7-docs(AI与音视频): 按场景整理完整接入流程与命令契约于
