im-rtc-call-engine 1.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/dist/browserSignals.d.ts +27 -0
  2. package/dist/browserSignals.d.ts.map +1 -0
  3. package/dist/browserSignals.js +34 -0
  4. package/dist/browserSignals.js.map +1 -0
  5. package/dist/callGuards.d.ts +35 -0
  6. package/dist/callGuards.d.ts.map +1 -0
  7. package/dist/callGuards.js +66 -0
  8. package/dist/callGuards.js.map +1 -0
  9. package/dist/callHistory.d.ts +50 -0
  10. package/dist/callHistory.d.ts.map +1 -0
  11. package/dist/callHistory.js +100 -0
  12. package/dist/callHistory.js.map +1 -0
  13. package/dist/callOptions.d.ts +14 -0
  14. package/dist/callOptions.d.ts.map +1 -1
  15. package/dist/callOptions.js +21 -0
  16. package/dist/callOptions.js.map +1 -1
  17. package/dist/debugToken.d.ts +29 -0
  18. package/dist/debugToken.d.ts.map +1 -0
  19. package/dist/debugToken.js +73 -0
  20. package/dist/debugToken.js.map +1 -0
  21. package/dist/engine.d.ts +88 -60
  22. package/dist/engine.d.ts.map +1 -1
  23. package/dist/engine.js +141 -178
  24. package/dist/engine.js.map +1 -1
  25. package/dist/engineBus.d.ts.map +1 -1
  26. package/dist/engineBus.js +1 -0
  27. package/dist/engineBus.js.map +1 -1
  28. package/dist/engineSession.d.ts +49 -0
  29. package/dist/engineSession.d.ts.map +1 -0
  30. package/dist/engineSession.js +97 -0
  31. package/dist/engineSession.js.map +1 -0
  32. package/dist/events.d.ts +48 -0
  33. package/dist/events.d.ts.map +1 -1
  34. package/dist/events.js +2 -0
  35. package/dist/events.js.map +1 -1
  36. package/dist/frameLoop.d.ts +48 -5
  37. package/dist/frameLoop.d.ts.map +1 -1
  38. package/dist/frameLoop.js +205 -29
  39. package/dist/frameLoop.js.map +1 -1
  40. package/dist/index.d.ts +6 -3
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +3 -2
  43. package/dist/index.js.map +1 -1
  44. package/dist/media/captureStream.d.ts +9 -0
  45. package/dist/media/captureStream.d.ts.map +1 -0
  46. package/dist/media/captureStream.js +20 -0
  47. package/dist/media/captureStream.js.map +1 -0
  48. package/dist/media/engineMediaApi.d.ts +24 -3
  49. package/dist/media/engineMediaApi.d.ts.map +1 -1
  50. package/dist/media/engineMediaApi.js +63 -27
  51. package/dist/media/engineMediaApi.js.map +1 -1
  52. package/dist/media/mediaBridge.d.ts +6 -1
  53. package/dist/media/mediaBridge.d.ts.map +1 -1
  54. package/dist/media/mediaBridge.js +18 -1
  55. package/dist/media/mediaBridge.js.map +1 -1
  56. package/dist/media/remoteAudio.d.ts +65 -0
  57. package/dist/media/remoteAudio.d.ts.map +1 -0
  58. package/dist/media/remoteAudio.js +83 -0
  59. package/dist/media/remoteAudio.js.map +1 -0
  60. package/dist/media/videoSender.d.ts +21 -0
  61. package/dist/media/videoSender.d.ts.map +1 -0
  62. package/dist/media/videoSender.js +74 -0
  63. package/dist/media/videoSender.js.map +1 -0
  64. package/dist/media/viewRegistry.d.ts +11 -3
  65. package/dist/media/viewRegistry.d.ts.map +1 -1
  66. package/dist/media/viewRegistry.js +35 -5
  67. package/dist/media/viewRegistry.js.map +1 -1
  68. package/dist/media/webrtcAdapter.d.ts +0 -31
  69. package/dist/media/webrtcAdapter.d.ts.map +1 -1
  70. package/dist/media/webrtcAdapter.js +10 -88
  71. package/dist/media/webrtcAdapter.js.map +1 -1
  72. package/dist/signaling/connection.d.ts +36 -0
  73. package/dist/signaling/connection.d.ts.map +1 -1
  74. package/dist/signaling/connection.js +89 -2
  75. package/dist/signaling/connection.js.map +1 -1
  76. package/dist/signaling/enums.d.ts +15 -0
  77. package/dist/signaling/enums.d.ts.map +1 -1
  78. package/dist/signaling/enums.js +17 -0
  79. package/dist/signaling/enums.js.map +1 -1
  80. package/dist/signaling/envelope.d.ts +13 -1
  81. package/dist/signaling/envelope.d.ts.map +1 -1
  82. package/dist/signaling/envelope.js +15 -3
  83. package/dist/signaling/envelope.js.map +1 -1
  84. package/dist/signaling/frames.call.d.ts +14 -0
  85. package/dist/signaling/frames.call.d.ts.map +1 -1
  86. package/dist/signaling/frames.call.js +8 -0
  87. package/dist/signaling/frames.call.js.map +1 -1
  88. package/dist/signaling/frames.room.d.ts +6 -4
  89. package/dist/signaling/frames.room.d.ts.map +1 -1
  90. package/dist/signaling/frames.room.js +10 -4
  91. package/dist/signaling/frames.room.js.map +1 -1
  92. package/dist/signaling/frames.sys.d.ts +5 -1
  93. package/dist/signaling/frames.sys.d.ts.map +1 -1
  94. package/dist/signaling/frames.sys.js +5 -1
  95. package/dist/signaling/frames.sys.js.map +1 -1
  96. package/dist/signaling/heartbeat.js +1 -1
  97. package/dist/signaling/heartbeat.js.map +1 -1
  98. package/dist/signaling/networkProbe.d.ts +31 -0
  99. package/dist/signaling/networkProbe.d.ts.map +1 -0
  100. package/dist/signaling/networkProbe.js +47 -0
  101. package/dist/signaling/networkProbe.js.map +1 -0
  102. package/dist/signaling/oneShotTimer.d.ts +30 -0
  103. package/dist/signaling/oneShotTimer.d.ts.map +1 -0
  104. package/dist/signaling/oneShotTimer.js +44 -0
  105. package/dist/signaling/oneShotTimer.js.map +1 -0
  106. package/dist/signaling/reconnector.d.ts +17 -1
  107. package/dist/signaling/reconnector.d.ts.map +1 -1
  108. package/dist/signaling/reconnector.js +48 -14
  109. package/dist/signaling/reconnector.js.map +1 -1
  110. package/dist/signaling/resumeDeadline.d.ts +1 -1
  111. package/dist/signaling/resumeDeadline.d.ts.map +1 -1
  112. package/dist/signaling/resumeDeadline.js +7 -10
  113. package/dist/signaling/resumeDeadline.js.map +1 -1
  114. package/dist/state/callMachine.d.ts +7 -0
  115. package/dist/state/callMachine.d.ts.map +1 -1
  116. package/dist/state/callMachine.js +16 -7
  117. package/dist/state/callMachine.js.map +1 -1
  118. package/dist/state/callRecv.d.ts.map +1 -1
  119. package/dist/state/callRecv.js +9 -1
  120. package/dist/state/callRecv.js.map +1 -1
  121. package/dist/state/engineMachine.d.ts.map +1 -1
  122. package/dist/state/engineMachine.js +26 -6
  123. package/dist/state/engineMachine.js.map +1 -1
  124. package/dist/state/roomMachine.d.ts +10 -2
  125. package/dist/state/roomMachine.d.ts.map +1 -1
  126. package/dist/state/roomMachine.js +87 -15
  127. package/dist/state/roomMachine.js.map +1 -1
  128. package/dist/state/roomPaging.d.ts +81 -0
  129. package/dist/state/roomPaging.d.ts.map +1 -0
  130. package/dist/state/roomPaging.js +202 -0
  131. package/dist/state/roomPaging.js.map +1 -0
  132. package/dist/state/roomRecv.d.ts.map +1 -1
  133. package/dist/state/roomRecv.js +17 -7
  134. package/dist/state/roomRecv.js.map +1 -1
  135. package/dist/state/types.d.ts +12 -0
  136. package/dist/state/types.d.ts.map +1 -1
  137. package/dist/state/types.js.map +1 -1
  138. package/dist/state/unsubscribeTimers.d.ts +29 -0
  139. package/dist/state/unsubscribeTimers.d.ts.map +1 -0
  140. package/dist/state/unsubscribeTimers.js +55 -0
  141. package/dist/state/unsubscribeTimers.js.map +1 -0
  142. package/dist/version.d.ts +1 -1
  143. package/dist/version.js +1 -1
  144. package/package.json +1 -1
@@ -1,5 +1,7 @@
1
1
  import { ErrorCode, errorName } from '../errors.js';
2
+ import { AUTO_SUBSCRIBE_MODES } from '../signaling/enums.js';
2
3
  import { FrameType } from '../signaling/registry.js';
4
+ import { flushHysteresis, pagedUpdateLayer, usesPagedVideo } from './roomPaging.js';
3
5
  import { reduceRoomRecv } from './roomRecv.js';
4
6
  import { bool, str } from './types.js';
5
7
  /** initialRoomContext 是 idle 态的初值。 */
@@ -8,13 +10,14 @@ export const initialRoomContext = {
8
10
  roomId: '',
9
11
  roomToken: '',
10
12
  participantId: '',
11
- autoSubscribe: true,
13
+ autoSubscribe: 'all',
12
14
  publish: {},
13
15
  publishTrackIds: {},
14
16
  subscribe: {},
15
17
  remoteTracks: {},
16
18
  layers: {},
17
19
  buffered: [],
20
+ pendingUnsubscribe: [],
18
21
  didJoin: false,
19
22
  };
20
23
  /** roomOut 构造一次状态转移的产物。roomRecv.ts 也用它。 */
@@ -70,14 +73,21 @@ function reduceRoomInternal(ctx, name, args) {
70
73
  : roomOut(ctx);
71
74
  case 'publish_failed':
72
75
  return dropFailedPublish(ctx, str(args, 'cid'));
76
+ case 'publish_deferred':
77
+ return deferPublish(ctx, args);
73
78
  case 'subscribe_failed':
74
79
  return dropFailedSubscribe(ctx, str(args, 'track_id'));
80
+ case 'unsubscribe_hysteresis_elapsed':
81
+ // 翻页退订的五秒到了。带 track_id 就只退那一条(帧循环按 track 排定时器),
82
+ // 不带就把排着的一次清掉(一致性向量用的是这一种)。
83
+ return flushHysteresis(ctx, optionalStr(args, 'track_id'));
75
84
  default:
76
85
  return roomOut(ctx);
77
86
  }
78
87
  }
79
88
  /**
80
- * dropFailedPublish:`room.publish` 被拒(或没送到)时把那条 `publishing` 摘掉(静默失败审计 §A)。
89
+ * dropFailedPublish:`room.publish` **被服务端拒绝**时把那条 `publishing` 摘掉(静默失败审计 §A)。
90
+ * 没送到(超时 / 断线)不走这里,走 {@link deferPublish}。
81
91
  *
82
92
  * 不摘的话它永远停在 `publishing`:`publish.ok` 不会来,pub offer 永远不产出。
83
93
  * **通话里走不到这里**——帧循环直接把整通强制收场(reason=error),因为推不上去的那一端
@@ -91,12 +101,46 @@ function dropFailedPublish(ctx, cid) {
91
101
  delete publish[cid];
92
102
  return roomOut({ ...ctx, publish });
93
103
  }
104
+ /**
105
+ * deferPublish:`room.publish` **没等到应答**(2003/2004/2007)时把这一路挂起来等重连,而不是丢掉。
106
+ *
107
+ * 与 `dropFailedPublish` 的分别只有一条,但这条是根本的:**服务端拒了**是个答复,重试救不回来
108
+ * (房间没了、重复发布),该收场;**超时/断线**根本不是答复,它只说明「这一问没能送到」,
109
+ * 而连接回来之后同一问多半就成了。
110
+ *
111
+ * 2026-09-18 真机撞的正是后者:18:18:39 `room.publish` 超时 → 整通电话被本端收成
112
+ * `reason=error`,而**9 秒后连接就回来了、会话也在恢复窗口内 resume 成功**
113
+ * (服务端 18:18:48「在恢复窗口内重连,取消离房」)。本来能接着打的一通被我们自己判了死刑;
114
+ * 更糟的是那时挂断帧也发不出去,服务端与对端完全不知道,对面对着一个幽灵坐了 3 分钟。
115
+ *
116
+ * 摘掉 `publishing` 之后把同一个意图塞回 `buffered`:`resumeRoom` 回到 `joined` 时
117
+ * `replayBuffered` 会原路重走一遍(**走 `reduceRoomAct`,不是补发旧帧**,所以状态与帧永远一致)。
118
+ * 重连一直不成功的话,`resumeDeadline.ts` 那条给恢复窗口上限的倒计时照样会把通话收场,
119
+ * 这里只是不再抢在它前面下手。
120
+ *
121
+ * **只认 `publishing`**:已经 `published` 的迟到超时、或压根没有这条记账的 cid,
122
+ * 都不碰——不然一条迟到的超时能把已经成功的发布摘掉,恢复后还会重复发布,
123
+ * 换回服务端一个「重复发布」的拒绝(见一致性向量 `publish_deferred_ignored_unless_publishing`)。
124
+ */
125
+ function deferPublish(ctx, args) {
126
+ const cid = str(args, 'cid');
127
+ if (ctx.publish[cid] !== 'publishing')
128
+ return roomOut(ctx);
129
+ const publish = { ...ctx.publish };
130
+ delete publish[cid];
131
+ return roomOut({ ...ctx, publish, buffered: [...ctx.buffered, { op: 'publish', args }] });
132
+ }
94
133
  /**
95
134
  * dropFailedSubscribe:`room.subscribe` 被拒时把那条 `subscribing` 连同层记账摘掉。
96
135
  *
97
136
  * 不摘的话不变量 R3 会把之后的每次重订都当成「已经订过、只换层」,
98
137
  * 只发 `room.update_layer`,**再也发不出 `room.subscribe`**。最常见的来路是 1301:
99
138
  * 订阅与对方的 `track_unpublished` 赛跑输了,此时摘掉正是实情。
139
+ *
140
+ * **待退订队列要一起摘**:会议房里「订上 → 翻走排退订 → 订阅这时才被拒」是能排到的顺序
141
+ * (订阅与翻页各走各的),队列里留着一个已经没有订阅记账的 track,
142
+ * 五秒后会发一条打在空处的 `room.unsubscribe`;要是这中间那个人又翻回来了,
143
+ * 那一条会把**刚重新订上的**那一路退掉,表现成「翻回来看了五秒,画面自己没了」。
100
144
  */
101
145
  function dropFailedSubscribe(ctx, trackId) {
102
146
  if (ctx.subscribe[trackId] !== 'subscribing')
@@ -105,7 +149,12 @@ function dropFailedSubscribe(ctx, trackId) {
105
149
  const layers = { ...ctx.layers };
106
150
  delete subscribe[trackId];
107
151
  delete layers[trackId];
108
- return roomOut({ ...ctx, subscribe, layers });
152
+ return roomOut({
153
+ ...ctx,
154
+ subscribe,
155
+ layers,
156
+ pendingUnsubscribe: ctx.pendingUnsubscribe.filter((id) => id !== trackId),
157
+ });
109
158
  }
110
159
  /**
111
160
  * resumeRoom 在重连成功后恢复房间:重放缓存的用户意图。
@@ -217,9 +266,9 @@ function reduceRoomAct(ctx, op, args) {
217
266
  function joinRoom(ctx, args) {
218
267
  if (ctx.state !== 'idle')
219
268
  return localReject(ctx);
220
- // auto_subscribe 默认 true——直接读 args 会把「没写」当成 false,
221
- // 那正是协议 §2.4 点名的发送侧陷阱。
222
- const autoSubscribe = args['auto_subscribe'] === undefined ? true : bool(args, 'auto_subscribe');
269
+ // auto_subscribe 默认 'all'——直接读 args 会把「没写」当成空串,
270
+ // 那正是协议 §2.4 点名的发送侧陷阱。集合外的值按 §2.4 规则 6 兜底成 'all'。
271
+ const autoSubscribe = coerceAutoSubscribe(args['auto_subscribe']);
223
272
  const roomId = str(args, 'room_id');
224
273
  const roomToken = str(args, 'room_token');
225
274
  return roomOut({ ...ctx, state: 'joining', roomId, roomToken, autoSubscribe }, [
@@ -274,17 +323,42 @@ function subscribeTrack(ctx, args) {
274
323
  }
275
324
  function unsubscribeTrack(ctx, args) {
276
325
  const trackId = str(args, 'track_id');
277
- return roomOut({ ...ctx, subscribe: { ...ctx.subscribe, [trackId]: 'unsubscribing' } }, [
278
- { type: FrameType.roomUnsubscribe, data: { track_id: trackId } },
279
- ]);
326
+ // 已经手动退了,排着的那次迟滞退订就不必再来一遍。
327
+ return roomOut({
328
+ ...ctx,
329
+ subscribe: { ...ctx.subscribe, [trackId]: 'unsubscribing' },
330
+ pendingUnsubscribe: ctx.pendingUnsubscribe.filter((id) => id !== trackId),
331
+ }, [{ type: FrameType.roomUnsubscribe, data: { track_id: trackId } }]);
280
332
  }
333
+ /**
334
+ * updateLayer 报某条流的层上界。
335
+ *
336
+ * **会议房里它同时是订阅意图**:视频不由服务端自动订,所以「看得见」= 订阅、
337
+ * 「看不见」= 五秒后退订(`roomPaging.ts`)。通话房照旧只换层。
338
+ */
281
339
  function updateLayer(ctx, args) {
282
340
  const trackId = str(args, 'track_id');
283
341
  const maxLayer = (str(args, 'max_layer') || 'm');
342
+ if (usesPagedVideo(ctx) && ctx.remoteTracks[trackId]?.kind === 'video') {
343
+ return pagedUpdateLayer(ctx, trackId, maxLayer);
344
+ }
284
345
  return roomOut({ ...ctx, layers: { ...ctx.layers, [trackId]: maxLayer } }, [
285
346
  { type: FrameType.roomUpdateLayer, data: { track_id: trackId, max_layer: maxLayer } },
286
347
  ]);
287
348
  }
349
+ /** coerceAutoSubscribe 把线路上的档位归一化,认不出的一律按 'all'(§2.4 规则 6)。 */
350
+ function coerceAutoSubscribe(value) {
351
+ if (typeof value !== 'string')
352
+ return 'all';
353
+ return AUTO_SUBSCRIBE_MODES.includes(value)
354
+ ? value
355
+ : 'all';
356
+ }
357
+ /** optionalStr 取一个可以缺席的字符串参数。 */
358
+ function optionalStr(args, key) {
359
+ const value = args[key];
360
+ return typeof value === 'string' && value !== '' ? value : undefined;
361
+ }
288
362
  /** BUFFERABLE_OPS 是值得攒下来重放的操作——正好是 R1 管的那一组。 */
289
363
  const BUFFERABLE_OPS = new Set([
290
364
  'publish',
@@ -309,11 +383,9 @@ function cidOfTrack(ctx, trackId) {
309
383
  }
310
384
  /** localReject 是不变量 R1 的落点:错误状态下的调用**本地拒绝**,不发上去。 */
311
385
  function localReject(ctx) {
312
- return roomOut(ctx, [], [
313
- {
314
- cb: 'onError',
315
- args: { code: ErrorCode.invalidState, name: errorName(ErrorCode.invalidState) },
316
- },
317
- ]);
386
+ return {
387
+ ...roomOut(ctx),
388
+ reject: { code: ErrorCode.invalidState, name: errorName(ErrorCode.invalidState) },
389
+ };
318
390
  }
319
391
  //# sourceMappingURL=roomMachine.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"roomMachine.js","sourceRoot":"","sources":["../../src/state/roomMachine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"roomMachine.js","sourceRoot":"","sources":["../../src/state/roomMachine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import type { Layer } from '../signaling/enums.js';
2
+ import type { RoomContext } from './roomMachine.js';
3
+ import type { MachineOutput } from './types.js';
4
+ /**
5
+ * 会议房的**按页订阅**:把「这个人现在看得见吗」翻译成订阅与退订。
6
+ *
7
+ * 见 `im-rtc-server/docs/design/MEETING_ROOM_DESIGN.md` §4.3。
8
+ *
9
+ * # 为什么挂在 setRemoteLayer 上,而不是新开一个 API
10
+ *
11
+ * **Engine 的公开 API 一个都不新增。** Kit 与自画 UI 的宿主本来就得按可视尺寸调
12
+ * `setRemoteLayer(uid, layer)`(九宫格报 `l`、放大报 `h`、看不见报 `none`),
13
+ * 这套调用已经**完整地表达了「谁在当前页」**。会议房要的只是把同一组调用
14
+ * 翻译成另一套帧:`l/m/h` = 订阅或换层,`none` = 五秒后退订。
15
+ * 新开一个 `subscribePage()` 的话,宿主要为「会议」写第二套界面代码,
16
+ * 而两套之间的差别只有引擎自己知道。
17
+ *
18
+ * # 只在 auto_subscribe='audio' 的房间里生效
19
+ *
20
+ * 通话房是 `all`:服务端全自动订好,`none` 的语义只是**暂停下发**(协议 §3.5),
21
+ * 退订会让那个人永远消失。这条分支写错的后果就是通话房里有人的画面再也回不来,
22
+ * 所以向量里给通话房单列了一组护栏用例(`room_fsm.json` 的
23
+ * `call_room_auto_subscribe_all_layer_only`)。
24
+ */
25
+ /**
26
+ * UNSUBSCRIBE_HYSTERESIS_MS 是翻页离开之后**等多久才真的退订**。
27
+ *
28
+ * 退订要重协商(sub PC 少一条 m-line),而翻页是来回的动作:左滑一页看一眼再滑回来
29
+ * 是最常见的操作。立刻退订的话这一来一回要两次协商,回来那一下还得重新等关键帧,
30
+ * 画面黑一下。等五秒,来回翻的那一种就一次协商都不用。
31
+ *
32
+ * 定时器不在状态机里(状态机是纯的,I4:禁止由定时器改状态):
33
+ * 由帧循环按 {@link RoomContext.pendingUnsubscribe} 排,到点喂一个内部事件回来。
34
+ */
35
+ export declare const UNSUBSCRIBE_HYSTERESIS_MS = 5000;
36
+ /**
37
+ * MAX_SUBSCRIBED_VIDEO 是同时订阅的视频路数上限(手机:本页 8 + 迟滞 8)。
38
+ *
39
+ * **这个数是 SDP 墙定的,不是算力定的**:sub offer 每订一路多一条 m-line,
40
+ * 整帧超过 64 KiB 就发不出去,而发不出去的后果是这个人的下行**永久冻结**
41
+ * (设计 §1.3)。所以它是硬上限,不是一个可以「先超一点看看」的建议值。
42
+ */
43
+ export declare const MAX_SUBSCRIBED_VIDEO = 16;
44
+ /** usesPagedVideo 报告这个房间的视频是不是由客户端按页订阅的。 */
45
+ export declare function usesPagedVideo(ctx: RoomContext): boolean;
46
+ /**
47
+ * pagedUpdateLayer 把一次 `setRemoteLayer` 翻译成订阅动作。
48
+ *
49
+ * - `none`:**先发 `room.update_layer{none}` 立刻停包**,再排五秒的退订。
50
+ * 两件事都要:停包省的是带宽(这一下就生效),退订省的是 m-line(五秒后才值得付那次协商)。
51
+ * - `l/m/h`:撤掉还没到点的退订;订过就只换层(**不重协商**,这正是迟滞想省下的那一次),
52
+ * 没订过就订。
53
+ */
54
+ export declare function pagedUpdateLayer(ctx: RoomContext, trackId: string, maxLayer: Layer): MachineOutput<RoomContext>;
55
+ /**
56
+ * flushHysteresis 让迟滞到点:把排着的退订真的发出去。
57
+ *
58
+ * `trackId` 省略时把**全部**排着的一次清掉(一致性向量用的就是这一种)。
59
+ * 帧循环按 track 排定时器,所以线上走的是带 `trackId` 的那一路。
60
+ *
61
+ * **通话房什么都不做**:它的 `none` 只是暂停,退订会让那个人的画面再也回不来。
62
+ *
63
+ * # 不在 joined 就按兵不动
64
+ *
65
+ * 断网重连期间这只定时器照样会到点。此时把 `room.unsubscribe` 发出去等于扔进一条死连接:
66
+ * 它没有 reject 可回(退订帧没有回滚路径),那条 track 会**永远卡在 `unsubscribing`**——
67
+ * 16 路的账从此少算一路,攒够几次翻页就再也订不上新的人;
68
+ * 更糟的是它仍占着 sub PC 的 m-line,offer 还在往 64 KiB 上顶。
69
+ *
70
+ * 留在 `pendingUnsubscribe` 里不动即可:{@link UnsubscribeTimers} 每轮按清单对账,
71
+ * 这一条还在清单上,定时器会**重新排一只**,等房间回到 joined 再退。
72
+ */
73
+ export declare function flushHysteresis(ctx: RoomContext, trackId?: string): MachineOutput<RoomContext>;
74
+ /**
75
+ * dropPending 把已经不存在的 track 从待退订队列里摘掉。
76
+ *
77
+ * 人走了、对方 unpublish 了,那条订阅本来就没了。不摘的话定时器到点会发一条
78
+ * 打在空处的 `room.unsubscribe`(服务端幂等,但帧循环会为它多排一轮)。
79
+ */
80
+ export declare function dropPending(pending: readonly string[], gone: ReadonlySet<string>): string[];
81
+ //# sourceMappingURL=roomPaging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roomPaging.d.ts","sourceRoot":"","sources":["../../src/state/roomPaging.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,OAAQ,CAAC;AAE/C;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,4CAA4C;AAC5C,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAExD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,KAAK,GACd,aAAa,CAAC,WAAW,CAAC,CAE5B;AAgED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,WAAW,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,aAAa,CAAC,WAAW,CAAC,CAkB5B;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAE3F"}
@@ -0,0 +1,202 @@
1
+ import { ErrorCode, errorName } from '../errors.js';
2
+ import { FrameType } from '../signaling/registry.js';
3
+ import { roomOut } from './roomMachine.js';
4
+ /**
5
+ * 会议房的**按页订阅**:把「这个人现在看得见吗」翻译成订阅与退订。
6
+ *
7
+ * 见 `im-rtc-server/docs/design/MEETING_ROOM_DESIGN.md` §4.3。
8
+ *
9
+ * # 为什么挂在 setRemoteLayer 上,而不是新开一个 API
10
+ *
11
+ * **Engine 的公开 API 一个都不新增。** Kit 与自画 UI 的宿主本来就得按可视尺寸调
12
+ * `setRemoteLayer(uid, layer)`(九宫格报 `l`、放大报 `h`、看不见报 `none`),
13
+ * 这套调用已经**完整地表达了「谁在当前页」**。会议房要的只是把同一组调用
14
+ * 翻译成另一套帧:`l/m/h` = 订阅或换层,`none` = 五秒后退订。
15
+ * 新开一个 `subscribePage()` 的话,宿主要为「会议」写第二套界面代码,
16
+ * 而两套之间的差别只有引擎自己知道。
17
+ *
18
+ * # 只在 auto_subscribe='audio' 的房间里生效
19
+ *
20
+ * 通话房是 `all`:服务端全自动订好,`none` 的语义只是**暂停下发**(协议 §3.5),
21
+ * 退订会让那个人永远消失。这条分支写错的后果就是通话房里有人的画面再也回不来,
22
+ * 所以向量里给通话房单列了一组护栏用例(`room_fsm.json` 的
23
+ * `call_room_auto_subscribe_all_layer_only`)。
24
+ */
25
+ /**
26
+ * UNSUBSCRIBE_HYSTERESIS_MS 是翻页离开之后**等多久才真的退订**。
27
+ *
28
+ * 退订要重协商(sub PC 少一条 m-line),而翻页是来回的动作:左滑一页看一眼再滑回来
29
+ * 是最常见的操作。立刻退订的话这一来一回要两次协商,回来那一下还得重新等关键帧,
30
+ * 画面黑一下。等五秒,来回翻的那一种就一次协商都不用。
31
+ *
32
+ * 定时器不在状态机里(状态机是纯的,I4:禁止由定时器改状态):
33
+ * 由帧循环按 {@link RoomContext.pendingUnsubscribe} 排,到点喂一个内部事件回来。
34
+ */
35
+ export const UNSUBSCRIBE_HYSTERESIS_MS = 5_000;
36
+ /**
37
+ * MAX_SUBSCRIBED_VIDEO 是同时订阅的视频路数上限(手机:本页 8 + 迟滞 8)。
38
+ *
39
+ * **这个数是 SDP 墙定的,不是算力定的**:sub offer 每订一路多一条 m-line,
40
+ * 整帧超过 64 KiB 就发不出去,而发不出去的后果是这个人的下行**永久冻结**
41
+ * (设计 §1.3)。所以它是硬上限,不是一个可以「先超一点看看」的建议值。
42
+ */
43
+ export const MAX_SUBSCRIBED_VIDEO = 16;
44
+ /** usesPagedVideo 报告这个房间的视频是不是由客户端按页订阅的。 */
45
+ export function usesPagedVideo(ctx) {
46
+ return ctx.autoSubscribe === 'audio';
47
+ }
48
+ /**
49
+ * pagedUpdateLayer 把一次 `setRemoteLayer` 翻译成订阅动作。
50
+ *
51
+ * - `none`:**先发 `room.update_layer{none}` 立刻停包**,再排五秒的退订。
52
+ * 两件事都要:停包省的是带宽(这一下就生效),退订省的是 m-line(五秒后才值得付那次协商)。
53
+ * - `l/m/h`:撤掉还没到点的退订;订过就只换层(**不重协商**,这正是迟滞想省下的那一次),
54
+ * 没订过就订。
55
+ */
56
+ export function pagedUpdateLayer(ctx, trackId, maxLayer) {
57
+ return maxLayer === 'none' ? pageOut(ctx, trackId) : pageIn(ctx, trackId, maxLayer);
58
+ }
59
+ function pageOut(ctx, trackId) {
60
+ // 没订过的不用退;**正在退的也不用**——那条 `room.unsubscribe` 已经在路上,
61
+ // 再排一次迟滞,五秒后会往一条已经不存在的订阅上再打一发,
62
+ // 而它回来的 1301 会被 dropFailedSubscribe 当成「订阅失败」处理。
63
+ const state = ctx.subscribe[trackId];
64
+ if (state === undefined || state === 'unsubscribing')
65
+ return roomOut(ctx);
66
+ // 已经排着退订的也不用再报一次 none——它早就不出包了,
67
+ // 再报一次只会把五秒的计时重新拉长。
68
+ if (ctx.pendingUnsubscribe.includes(trackId))
69
+ return roomOut(ctx);
70
+ return roomOut({
71
+ ...ctx,
72
+ layers: { ...ctx.layers, [trackId]: 'none' },
73
+ pendingUnsubscribe: [...ctx.pendingUnsubscribe, trackId],
74
+ }, [{ type: FrameType.roomUpdateLayer, data: { track_id: trackId, max_layer: 'none' } }]);
75
+ }
76
+ function pageIn(ctx, trackId, maxLayer) {
77
+ const kept = { ...ctx, pendingUnsubscribe: without(ctx.pendingUnsubscribe, trackId) };
78
+ const state = kept.subscribe[trackId];
79
+ if (state === 'subscribing' || state === 'subscribed') {
80
+ return roomOut({ ...kept, layers: { ...kept.layers, [trackId]: maxLayer } }, [
81
+ { type: FrameType.roomUpdateLayer, data: { track_id: trackId, max_layer: maxLayer } },
82
+ ]);
83
+ }
84
+ /*
85
+ **先问腾不腾得出位置,再动手**:本地拒绝要求不发帧、状态不变,
86
+ 所以不能先把强制退订发出去再反悔。
87
+
88
+ 排着迟滞的那些都还占着 m-line,它们是唯一能腾出来的位置。全退了还满,
89
+ 就**只可能是调用方一次要看超过 16 路视频**——翻页翻不出这种局面(一页 8 路),
90
+ 那是界面那边的 bug,不该由引擎悄悄吞掉。
91
+
92
+ **不排队**:排队要有一个「什么时候轮到你」的触发点,而这里没有——
93
+ 订阅位是靠翻页腾出来的,队列只会安静地越积越长,
94
+ 表现成「第 17 个人的画面永远不出来,也没有任何报错」。
95
+ */
96
+ if (countLiveVideo(kept) - kept.pendingUnsubscribe.length >= MAX_SUBSCRIBED_VIDEO) {
97
+ return {
98
+ ...roomOut(ctx),
99
+ reject: { code: ErrorCode.invalidState, name: errorName(ErrorCode.invalidState) },
100
+ };
101
+ }
102
+ const room = freeSlot(kept);
103
+ return roomOut({
104
+ ...room.ctx,
105
+ subscribe: { ...room.ctx.subscribe, [trackId]: 'subscribing' },
106
+ layers: { ...room.ctx.layers, [trackId]: maxLayer },
107
+ }, [
108
+ ...room.send,
109
+ { type: FrameType.roomSubscribe, data: { track_id: trackId, max_layer: maxLayer } },
110
+ ]);
111
+ }
112
+ /**
113
+ * flushHysteresis 让迟滞到点:把排着的退订真的发出去。
114
+ *
115
+ * `trackId` 省略时把**全部**排着的一次清掉(一致性向量用的就是这一种)。
116
+ * 帧循环按 track 排定时器,所以线上走的是带 `trackId` 的那一路。
117
+ *
118
+ * **通话房什么都不做**:它的 `none` 只是暂停,退订会让那个人的画面再也回不来。
119
+ *
120
+ * # 不在 joined 就按兵不动
121
+ *
122
+ * 断网重连期间这只定时器照样会到点。此时把 `room.unsubscribe` 发出去等于扔进一条死连接:
123
+ * 它没有 reject 可回(退订帧没有回滚路径),那条 track 会**永远卡在 `unsubscribing`**——
124
+ * 16 路的账从此少算一路,攒够几次翻页就再也订不上新的人;
125
+ * 更糟的是它仍占着 sub PC 的 m-line,offer 还在往 64 KiB 上顶。
126
+ *
127
+ * 留在 `pendingUnsubscribe` 里不动即可:{@link UnsubscribeTimers} 每轮按清单对账,
128
+ * 这一条还在清单上,定时器会**重新排一只**,等房间回到 joined 再退。
129
+ */
130
+ export function flushHysteresis(ctx, trackId) {
131
+ if (!usesPagedVideo(ctx))
132
+ return roomOut(ctx);
133
+ if (ctx.state !== 'joined')
134
+ return roomOut(ctx);
135
+ const targets = trackId === undefined ? ctx.pendingUnsubscribe : ctx.pendingUnsubscribe.filter((id) => id === trackId);
136
+ if (targets.length === 0)
137
+ return roomOut(ctx);
138
+ let next = {
139
+ ...ctx,
140
+ pendingUnsubscribe: ctx.pendingUnsubscribe.filter((id) => !targets.includes(id)),
141
+ };
142
+ const send = [];
143
+ for (const id of targets) {
144
+ const one = unsubscribeNow(next, id);
145
+ next = one.ctx;
146
+ send.push(...one.send);
147
+ }
148
+ return roomOut(next, send);
149
+ }
150
+ /**
151
+ * dropPending 把已经不存在的 track 从待退订队列里摘掉。
152
+ *
153
+ * 人走了、对方 unpublish 了,那条订阅本来就没了。不摘的话定时器到点会发一条
154
+ * 打在空处的 `room.unsubscribe`(服务端幂等,但帧循环会为它多排一轮)。
155
+ */
156
+ export function dropPending(pending, gone) {
157
+ return pending.filter((id) => !gone.has(id));
158
+ }
159
+ function unsubscribeNow(ctx, trackId) {
160
+ const state = ctx.subscribe[trackId];
161
+ if (state === undefined || state === 'unsubscribing')
162
+ return { ctx, send: [] };
163
+ const layers = { ...ctx.layers };
164
+ delete layers[trackId];
165
+ return {
166
+ ctx: { ...ctx, subscribe: { ...ctx.subscribe, [trackId]: 'unsubscribing' }, layers },
167
+ send: [{ type: FrameType.roomUnsubscribe, data: { track_id: trackId } }],
168
+ };
169
+ }
170
+ /**
171
+ * freeSlot 在订满 16 路时**提前**把排着的退订执行掉,腾出位置。
172
+ *
173
+ * 快速连翻几页就会踩到:第一页还在五秒迟滞里,第二页也翻走了,第三页要订新的。
174
+ * 迟滞是一种便利,不是承诺——位置不够时先退最早翻走的那一页,正是想退的顺序。
175
+ */
176
+ function freeSlot(ctx) {
177
+ let next = ctx;
178
+ const send = [];
179
+ while (countLiveVideo(next) >= MAX_SUBSCRIBED_VIDEO && next.pendingUnsubscribe.length > 0) {
180
+ const [oldest, ...rest] = next.pendingUnsubscribe;
181
+ const one = unsubscribeNow(next, oldest);
182
+ next = { ...one.ctx, pendingUnsubscribe: rest };
183
+ send.push(...one.send);
184
+ }
185
+ return { ctx: next, send };
186
+ }
187
+ /** countLiveVideo 数此刻**占着 m-line** 的视频路数:订上的与正在订的都算,正在退的不算。 */
188
+ function countLiveVideo(ctx) {
189
+ let count = 0;
190
+ for (const [trackId, state] of Object.entries(ctx.subscribe)) {
191
+ if (state === 'unsubscribing')
192
+ continue;
193
+ if (ctx.remoteTracks[trackId]?.kind !== 'video')
194
+ continue;
195
+ count += 1;
196
+ }
197
+ return count;
198
+ }
199
+ function without(list, value) {
200
+ return list.filter((item) => item !== value);
201
+ }
202
+ //# sourceMappingURL=roomPaging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roomPaging.js","sourceRoot":"","sources":["../../src/state/roomPaging.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"roomRecv.d.ts","sourceRoot":"","sources":["../../src/state/roomRecv.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAe,WAAW,EAAkB,MAAM,kBAAkB,CAAC;AAE/F,OAAO,KAAK,EAAgB,aAAa,EAAiB,MAAM,YAAY,CAAC;AAgB7E,gCAAgC;AAChC,wBAAgB,cAAc,CAC5B,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACtC,aAAa,CAAC,WAAW,CAAC,CA6C5B;AA0MD,2CAA2C;AAC3C,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAEtF"}
1
+ {"version":3,"file":"roomRecv.d.ts","sourceRoot":"","sources":["../../src/state/roomRecv.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAe,WAAW,EAAkB,MAAM,kBAAkB,CAAC;AAG/F,OAAO,KAAK,EAAgB,aAAa,EAAiB,MAAM,YAAY,CAAC;AAgB7E,gCAAgC;AAChC,wBAAgB,cAAc,CAC5B,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACtC,aAAa,CAAC,WAAW,CAAC,CA6C5B;AA0ND,2CAA2C;AAC3C,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAEtF"}
@@ -1,5 +1,7 @@
1
+ import { autoSubscribeCovers } from '../signaling/enums.js';
1
2
  import { FrameType } from '../signaling/registry.js';
2
3
  import { clearedRoom, replayBuffered, roomOut } from './roomMachine.js';
4
+ import { dropPending } from './roomPaging.js';
3
5
  import { bool, str } from './types.js';
4
6
  /**
5
7
  * 房间状态机的**下行帧**分支。
@@ -78,7 +80,9 @@ function handleLateFrame(ctx, type, data) {
78
80
  }
79
81
  /** handleJoinOk 用快照把房间一次性搭起来:先成员,再他们的 Track。 */
80
82
  function handleJoinOk(ctx, data) {
81
- const emit = [{ cb: 'onRoomJoined', args: { room_id: str(data, 'room_id') } }];
83
+ // uids = 进房这一刻房里已有的人(快照)。界面靠它对账:响铃阶段不在房里的人,中途离场收不到 userLeave。
84
+ const present = asArray(data['participants']).map((p) => str(p, 'uid'));
85
+ const emit = [{ cb: 'onRoomJoined', args: { room_id: str(data, 'room_id'), uids: present } }];
82
86
  const remoteTracks = { ...ctx.remoteTracks };
83
87
  const subscribe = { ...ctx.subscribe };
84
88
  for (const participant of asArray(data['participants'])) {
@@ -94,7 +98,8 @@ function handleJoinOk(ctx, data) {
94
98
  };
95
99
  emit.push(availabilityEvent(kind, str(track, 'uid'), !bool(track, 'muted')));
96
100
  // 自动订阅是**服务端**做的,客户端这边只记账,等 sub offer 来把它们坐实。
97
- if (ctx.autoSubscribe)
101
+ // 会议房只有音频落这一路,视频等界面报「看得见」时再按页订(roomPaging.ts)。
102
+ if (autoSubscribeCovers(ctx.autoSubscribe, kind))
98
103
  subscribe[trackId] = 'subscribing';
99
104
  }
100
105
  // 进房成功之后**立刻重放 joining 期间攒下的意图**(不变量 R2):
@@ -132,24 +137,24 @@ function handleParticipantLeft(ctx, data) {
132
137
  const participantId = str(data, 'participant_id');
133
138
  const remoteTracks = {};
134
139
  const subscribe = { ...ctx.subscribe };
140
+ const gone = new Set();
135
141
  for (const [trackId, track] of Object.entries(ctx.remoteTracks)) {
136
142
  if (track.participantId === participantId) {
137
143
  // 人走了,他的 Track 与我们对它的订阅一起清掉——不清的话重连时会重放一个死订阅。
138
144
  delete subscribe[trackId];
145
+ gone.add(trackId);
139
146
  continue;
140
147
  }
141
148
  remoteTracks[trackId] = track;
142
149
  }
143
- return roomOut({ ...ctx, remoteTracks, subscribe }, [], [
144
- { cb: 'onUserLeave', args: { uid: str(data, 'uid') } },
145
- ]);
150
+ return roomOut({ ...ctx, remoteTracks, subscribe, pendingUnsubscribe: dropPending(ctx.pendingUnsubscribe, gone) }, [], [{ cb: 'onUserLeave', args: { uid: str(data, 'uid') } }]);
146
151
  }
147
152
  function handleTrackPublished(ctx, data) {
148
153
  const trackId = str(data, 'track_id');
149
154
  const kind = str(data, 'kind') === 'video' ? 'video' : 'audio';
150
155
  const uid = str(data, 'uid');
151
156
  const subscribe = { ...ctx.subscribe };
152
- if (ctx.autoSubscribe)
157
+ if (autoSubscribeCovers(ctx.autoSubscribe, kind))
153
158
  subscribe[trackId] = 'subscribing';
154
159
  return roomOut({
155
160
  ...ctx,
@@ -169,7 +174,12 @@ function handleTrackUnpublished(ctx, data) {
169
174
  delete remoteTracks[trackId];
170
175
  delete subscribe[trackId];
171
176
  const emit = known === undefined ? [] : [availabilityEvent(known.kind, known.uid, false)];
172
- return roomOut({ ...ctx, remoteTracks, subscribe }, [], emit);
177
+ return roomOut({
178
+ ...ctx,
179
+ remoteTracks,
180
+ subscribe,
181
+ pendingUnsubscribe: dropPending(ctx.pendingUnsubscribe, new Set([trackId])),
182
+ }, [], emit);
173
183
  }
174
184
  function handleTrackMuted(ctx, data) {
175
185
  const kind = str(data, 'kind') === 'video' ? 'video' : 'audio';