实时广播分区与紧急插播
约 2556 字大约 9 分钟
2026-10-16
本页包含扩展设计,不能作为当前整场景已实现的承诺。参见支持范围、场景索引和命令手册。图中S编号只用于本文定位,不放入实际JSON。
前置条件
liveBroadcast源端先按S01建立WebRTC音视频源;发布者有目标分区权限。异步文件广播继续使用S10,实时流不离线补播。
平台把zoneIds解析成收件设备快照,每台建立独立接收腿、协商媒体并回报;订阅失败仅影响本端。紧急广播默认只抢输出;麦克风和摄像头仍需明确授权。广播源断线15秒超时停止所有腿,不无限播放旧缓冲。
D/D2是不同设备参与端,A是应用端,P是平台和媒体节点。各端分别使用鉴权Topic/登录态,不能冒用另一端身份。基础会话与媒体协商见S01/S06,复用时保留本场景sessionId并独立分配密钥和token。
完整时序
报文索引
编号按图阅读;编号保留历史引用,不要求数值连续。字段定义以命令链接为准。
| 编号 | 发送→接收 | Topic/接口 | 方法及契约 | 应答/等待 | 状态或作用 |
|---|---|---|---|---|---|
| S16-M01 | D→P | SIG↑ | broadcastControl | broadcastState;10秒受理,媒体协商15秒 | |
| S16-M02 | P→D | SIG↓ | broadcastState | 应答/状态事件;不等待ACK | |
| S16-M17 | P→D2 | SIG↓ | sessionInvite | 应答或事件,无ACK | 核对补齐,不以受理替代完成 |
| S16-M18 | D2→P | SIG↑ | sessionAccept | 按契约等待10秒 | 核对补齐,不以受理替代完成 |
| S16-M19 | P→D2 | SIG↓ | requestAck | 应答或事件,无ACK | 核对补齐,不以受理替代完成 |
| S16-M20 | D2→P | SIG↑ | mediaOffer | 按契约等待10秒 | 核对补齐,不以受理替代完成 |
| S16-M21 | P→D2 | SIG↓ | mediaAnswer | 应答或事件,无ACK | 核对补齐,不以受理替代完成 |
| S16-M22 | D2→P | SIG↑ | mediaState | 按契约等待10秒 | 核对补齐,不以受理替代完成 |
| S16-M23 | P→D2 | SIG↓ | requestAck | 应答或事件,无ACK | 核对补齐,不以受理替代完成 |
| S16-M24 | P→D2 | SIG↓ | sessionEstablished | 应答或事件,无ACK | 核对补齐,不以受理替代完成 |
| S16-M03 | P→D2 | SIG↓ | focusControl | focusState;10秒受理,媒体协商15秒 | |
| S16-M04 | D2→P | SIG↑ | focusState | 应答/状态事件;不等待ACK | |
| S16-M05 | P→D | SIG↓ | broadcastState | 应答/状态事件;不等待ACK | |
| S16-M06 | D→P | SIG↑ | broadcastControl | broadcastState;10秒受理,媒体协商15秒 | |
| S16-M07 | P→D | SIG↓ | broadcastState | 应答/状态事件;不等待ACK | |
| S16-M08 | P→D2 | SIG↓ | focusControl | focusState;10秒受理,媒体协商15秒 | |
| S16-M09 | D2→P | SIG↑ | focusState | 应答/状态事件;不等待ACK | |
| S16-M10 | P→D | SIG↓ | broadcastState | 应答/状态事件;不等待ACK | |
| S16-M11 | D→P | SIG↑ | sessionEnd | 对应应答见命令;10秒受理,媒体协商15秒 | |
| S16-M12 | P→D | SIG↓ | sessionEnded | 应答/状态事件;不等待ACK | |
| S16-M13 | D→P | SIG↑ | broadcastControl | broadcastState;10秒 | |
| S16-M14 | P→D | SIG↓ | broadcastState | 实际状态应答;不等待ACK | |
| S16-M15 | D→P | SIG↑ | broadcastControl | broadcastState;10秒 | |
| S16-M16 | P→D | SIG↓ | broadcastState | 实际状态应答;不等待ACK |
逐条JSON
S16-M01 · broadcastControl
{
"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-M02 · broadcastState
{
"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-M17 · sessionInvite
{
"msgToken": "s16-s16-receiver-invite",
"method": "sessionInvite",
"sessionId": "s16-receiver",
"eventSeq": 1,
"params": {
"purpose": "liveBroadcast",
"transport": "webrtc",
"admission": "direct",
"tracks": [
{
"trackId": "broadcast-out",
"kind": "audio",
"sourceId": "broadcast-audio",
"direction": "recvonly",
"codec": "opus",
"state": "requested"
}
],
"expiresAt": 1900000000000
}
}S16-M18 · sessionAccept
{
"msgToken": "s16-s16-receiver-invite",
"method": "sessionAccept",
"sessionId": "s16-receiver",
"params": {
"acceptedTracks": [
"broadcast-out"
]
}
}S16-M19 · requestAck
{
"msgToken": "s16-s16-receiver-invite",
"method": "requestAck",
"sessionId": "s16-receiver",
"code": 200,
"data": {
"requestMethod": "sessionAccept",
"result": {
"state": "negotiating"
}
}
}S16-M20 · mediaOffer
{
"msgToken": "s16-s16-receiver-offer",
"method": "mediaOffer",
"sessionId": "s16-receiver",
"params": {
"mediaRevision": 1,
"webrtc": {
"iceMode": "complete",
"sdp": "<SDP offer>"
}
}
}S16-M21 · mediaAnswer
{
"msgToken": "s16-s16-receiver-offer",
"method": "mediaAnswer",
"sessionId": "s16-receiver",
"code": 200,
"data": {
"mediaRevision": 1,
"webrtc": {
"iceMode": "complete",
"sdp": "<SDP answer>"
}
}
}S16-M22 · mediaState
{
"msgToken": "s16-s16-receiver-connected",
"method": "mediaState",
"sessionId": "s16-receiver",
"params": {
"mediaRevision": 1,
"state": "connected"
}
}S16-M23 · requestAck
{
"msgToken": "s16-s16-receiver-connected",
"method": "requestAck",
"sessionId": "s16-receiver",
"code": 200,
"data": {
"requestMethod": "mediaState",
"result": {
"mediaRevision": 1,
"state": "connected"
}
}
}S16-M24 · sessionEstablished
{
"msgToken": "s16-e1",
"method": "sessionEstablished",
"sessionId": "s16-receiver",
"eventSeq": 2,
"data": {
"state": "established",
"mediaRevision": 1
}
}S16-M03 · focusControl
{
"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-M04 · focusState
{
"msgToken": "s16-52",
"method": "focusState",
"sessionId": "s16-music-receiver",
"data": {
"state": "suspended",
"revision": 1,
"focusId": "music-focus",
"resources": [
"speaker"
]
},
"code": 200
}S16-M05 · broadcastState
{
"msgToken": "s16-53",
"method": "broadcastState",
"sessionId": "s16-session",
"data": {
"state": "partial",
"revision": 2,
"broadcastId": "broadcast-1",
"recipients": [
{
"endpointId": "speaker-a",
"state": "connected"
},
{
"endpointId": "speaker-b",
"state": "failed",
"reason": "offline"
}
],
"requestToken": "s16-51"
},
"eventSeq": 1
}S16-M06 · broadcastControl
{
"msgToken": "s16-54",
"method": "broadcastControl",
"sessionId": "s16-session",
"params": {
"operation": "stop",
"expectedRevision": 2,
"broadcastId": "broadcast-1"
}
}S16-M07 · broadcastState
{
"msgToken": "s16-54",
"method": "broadcastState",
"sessionId": "s16-session",
"data": {
"state": "stopped",
"revision": 3,
"broadcastId": "broadcast-1",
"recipients": [
{
"endpointId": "speaker-a",
"state": "ended"
},
{
"endpointId": "speaker-b",
"state": "failed",
"reason": "offline"
}
]
},
"code": 200
}S16-M08 · focusControl
{
"msgToken": "s16-55",
"method": "focusControl",
"sessionId": "s16-music-receiver",
"params": {
"operation": "restore",
"expectedRevision": 1,
"focusId": "music-focus",
"resources": [
"speaker"
],
"priority": "background",
"resumePolicy": "ifUnchanged",
"expiresAt": 1900000000000
},
"eventSeq": 2
}S16-M09 · focusState
{
"msgToken": "s16-55",
"method": "focusState",
"sessionId": "s16-music-receiver",
"data": {
"state": "restored",
"revision": 2,
"focusId": "music-focus",
"resources": [
"speaker"
]
},
"code": 200
}S16-M10 · broadcastState
{
"msgToken": "s16-56",
"method": "broadcastState",
"sessionId": "s16-session",
"data": {
"state": "failed",
"revision": 2,
"broadcastId": "broadcast-1",
"recipients": [
{
"endpointId": "speaker-a",
"state": "failed",
"reason": "offline"
}
]
},
"eventSeq": 2
}S16-M11 · sessionEnd
{
"msgToken": "s16-57",
"method": "sessionEnd",
"sessionId": "s16-session",
"params": {
"reason": "userHangup"
}
}S16-M12 · sessionEnded
{
"msgToken": "s16-57",
"method": "sessionEnded",
"sessionId": "s16-session",
"data": {
"state": "ended",
"reason": "userHangup"
},
"code": 200
}S16-M13 · broadcastControl
{
"msgToken": "s16-extra-12",
"method": "broadcastControl",
"sessionId": "s16-recipient",
"params": {
"operation": "subscribe",
"expectedRevision": 0,
"broadcastId": "broadcast-other"
}
}S16-M14 · broadcastState
{
"msgToken": "s16-extra-12",
"method": "broadcastState",
"sessionId": "s16-recipient",
"code": 200,
"data": {
"state": "active",
"revision": 1,
"broadcastId": "broadcast-other",
"recipients": [
{
"endpointId": "speaker-c",
"state": "connected"
}
]
}
}S16-M15 · broadcastControl
{
"msgToken": "s16-extra-14",
"method": "broadcastControl",
"sessionId": "s16-recipient",
"params": {
"operation": "unsubscribe",
"expectedRevision": 1,
"broadcastId": "broadcast-other"
}
}S16-M16 · broadcastState
{
"msgToken": "s16-extra-14",
"method": "broadcastState",
"sessionId": "s16-recipient",
"code": 200,
"data": {
"state": "active",
"revision": 2,
"broadcastId": "broadcast-other",
"recipients": [
{
"endpointId": "speaker-c",
"state": "ended"
}
]
}
}媒体与本地动作
| 编号 | 路径 | 格式与约束 |
|---|---|---|
| S16-R02 | D2→P | WebRTC ICE/DTLS;独立Peer;15秒超时撤销候选腿 |
| S16-R01 | P→D2 | WebRTC广播音视频轨;无上行麦克风轨 |
异常、状态与资源释放
路由与信封见公共约定;阶段性状态不代表最终完成。操作终态时限见命令手册;编号、超时等元信息不发送。
能力不足422、无权限403、资源/修订号冲突409、超时504按S11处理,不静默开启设备能力。同token只重放原结果;事件按eventSeq去重,旧会话/端代次不可恢复。验证本页正常路径、alt分支及支持范围断言。文档通过不代表代码或硬件已实现。
订阅分支M13前要求接收端s16-recipient已按本页接收腿步骤完成媒体协商、权限与焦点确认;否则回starting/pending并等待媒体连通,不得直接回active。恢复music-focus的控制和回执属于同一接收设备的原音乐会话,不属于广播源设备。
验证入口
更新日志
2026/10/16 16:04
查看所有更新日志
fe3a7-docs(AI与音视频): 按场景整理完整接入流程与命令契约于
