im-rtc-call-engine 1.0.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.
- package/LICENSE +21 -0
- package/dist/bytes.d.ts +11 -0
- package/dist/bytes.d.ts.map +1 -0
- package/dist/bytes.js +20 -0
- package/dist/bytes.js.map +1 -0
- package/dist/callOptions.d.ts +27 -0
- package/dist/callOptions.d.ts.map +1 -0
- package/dist/callOptions.js +19 -0
- package/dist/callOptions.js.map +1 -0
- package/dist/deviceId.d.ts +10 -0
- package/dist/deviceId.d.ts.map +1 -0
- package/dist/deviceId.js +55 -0
- package/dist/deviceId.js.map +1 -0
- package/dist/engine.d.ts +302 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +489 -0
- package/dist/engine.js.map +1 -0
- package/dist/engineBus.d.ts +16 -0
- package/dist/engineBus.d.ts.map +1 -0
- package/dist/engineBus.js +89 -0
- package/dist/engineBus.js.map +1 -0
- package/dist/engineWiring.d.ts +40 -0
- package/dist/engineWiring.d.ts.map +1 -0
- package/dist/engineWiring.js +57 -0
- package/dist/engineWiring.js.map +1 -0
- package/dist/errors.d.ts +185 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +253 -0
- package/dist/errors.js.map +1 -0
- package/dist/eventBus.d.ts +24 -0
- package/dist/eventBus.d.ts.map +1 -0
- package/dist/eventBus.js +50 -0
- package/dist/eventBus.js.map +1 -0
- package/dist/events.d.ts +220 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +35 -0
- package/dist/events.js.map +1 -0
- package/dist/frameLoop.d.ts +93 -0
- package/dist/frameLoop.d.ts.map +1 -0
- package/dist/frameLoop.js +346 -0
- package/dist/frameLoop.js.map +1 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +64 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +101 -0
- package/dist/logger.js.map +1 -0
- package/dist/media/engineMediaApi.d.ts +40 -0
- package/dist/media/engineMediaApi.d.ts.map +1 -0
- package/dist/media/engineMediaApi.js +71 -0
- package/dist/media/engineMediaApi.js.map +1 -0
- package/dist/media/firstFrameGate.d.ts +47 -0
- package/dist/media/firstFrameGate.d.ts.map +1 -0
- package/dist/media/firstFrameGate.js +117 -0
- package/dist/media/firstFrameGate.js.map +1 -0
- package/dist/media/mediaAdapter.d.ts +135 -0
- package/dist/media/mediaAdapter.d.ts.map +1 -0
- package/dist/media/mediaAdapter.js +2 -0
- package/dist/media/mediaAdapter.js.map +1 -0
- package/dist/media/mediaBridge.d.ts +99 -0
- package/dist/media/mediaBridge.d.ts.map +1 -0
- package/dist/media/mediaBridge.js +186 -0
- package/dist/media/mediaBridge.js.map +1 -0
- package/dist/media/mediaPlane.d.ts +58 -0
- package/dist/media/mediaPlane.d.ts.map +1 -0
- package/dist/media/mediaPlane.js +119 -0
- package/dist/media/mediaPlane.js.map +1 -0
- package/dist/media/videoProfile.d.ts +79 -0
- package/dist/media/videoProfile.d.ts.map +1 -0
- package/dist/media/videoProfile.js +46 -0
- package/dist/media/videoProfile.js.map +1 -0
- package/dist/media/videoProfile.test.d.ts +2 -0
- package/dist/media/videoProfile.test.d.ts.map +1 -0
- package/dist/media/videoProfile.test.js +26 -0
- package/dist/media/videoProfile.test.js.map +1 -0
- package/dist/media/viewRegistry.d.ts +75 -0
- package/dist/media/viewRegistry.d.ts.map +1 -0
- package/dist/media/viewRegistry.js +130 -0
- package/dist/media/viewRegistry.js.map +1 -0
- package/dist/media/webrtcAdapter.d.ts +158 -0
- package/dist/media/webrtcAdapter.d.ts.map +1 -0
- package/dist/media/webrtcAdapter.js +502 -0
- package/dist/media/webrtcAdapter.js.map +1 -0
- package/dist/protocolId.d.ts +14 -0
- package/dist/protocolId.d.ts.map +1 -0
- package/dist/protocolId.js +109 -0
- package/dist/protocolId.js.map +1 -0
- package/dist/reasons.d.ts +63 -0
- package/dist/reasons.d.ts.map +1 -0
- package/dist/reasons.js +81 -0
- package/dist/reasons.js.map +1 -0
- package/dist/redact.d.ts +19 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +50 -0
- package/dist/redact.js.map +1 -0
- package/dist/signaling/backoff.d.ts +17 -0
- package/dist/signaling/backoff.d.ts.map +1 -0
- package/dist/signaling/backoff.js +23 -0
- package/dist/signaling/backoff.js.map +1 -0
- package/dist/signaling/candidate.d.ts +19 -0
- package/dist/signaling/candidate.d.ts.map +1 -0
- package/dist/signaling/candidate.js +22 -0
- package/dist/signaling/candidate.js.map +1 -0
- package/dist/signaling/caseMapping.d.ts +19 -0
- package/dist/signaling/caseMapping.d.ts.map +1 -0
- package/dist/signaling/caseMapping.js +34 -0
- package/dist/signaling/caseMapping.js.map +1 -0
- package/dist/signaling/connection.d.ts +110 -0
- package/dist/signaling/connection.d.ts.map +1 -0
- package/dist/signaling/connection.js +365 -0
- package/dist/signaling/connection.js.map +1 -0
- package/dist/signaling/connectionFactory.d.ts +55 -0
- package/dist/signaling/connectionFactory.d.ts.map +1 -0
- package/dist/signaling/connectionFactory.js +29 -0
- package/dist/signaling/connectionFactory.js.map +1 -0
- package/dist/signaling/connectionTypes.d.ts +94 -0
- package/dist/signaling/connectionTypes.d.ts.map +1 -0
- package/dist/signaling/connectionTypes.js +2 -0
- package/dist/signaling/connectionTypes.js.map +1 -0
- package/dist/signaling/discipline.d.ts +6 -0
- package/dist/signaling/discipline.d.ts.map +1 -0
- package/dist/signaling/discipline.js +100 -0
- package/dist/signaling/discipline.js.map +1 -0
- package/dist/signaling/enums.d.ts +53 -0
- package/dist/signaling/enums.d.ts.map +1 -0
- package/dist/signaling/enums.js +52 -0
- package/dist/signaling/enums.js.map +1 -0
- package/dist/signaling/envelope.d.ts +31 -0
- package/dist/signaling/envelope.d.ts.map +1 -0
- package/dist/signaling/envelope.js +91 -0
- package/dist/signaling/envelope.js.map +1 -0
- package/dist/signaling/fieldSpec.d.ts +101 -0
- package/dist/signaling/fieldSpec.d.ts.map +1 -0
- package/dist/signaling/fieldSpec.js +130 -0
- package/dist/signaling/fieldSpec.js.map +1 -0
- package/dist/signaling/frameSender.d.ts +34 -0
- package/dist/signaling/frameSender.d.ts.map +1 -0
- package/dist/signaling/frameSender.js +57 -0
- package/dist/signaling/frameSender.js.map +1 -0
- package/dist/signaling/frames.call.d.ts +299 -0
- package/dist/signaling/frames.call.d.ts.map +1 -0
- package/dist/signaling/frames.call.js +149 -0
- package/dist/signaling/frames.call.js.map +1 -0
- package/dist/signaling/frames.room.d.ts +566 -0
- package/dist/signaling/frames.room.d.ts.map +1 -0
- package/dist/signaling/frames.room.js +165 -0
- package/dist/signaling/frames.room.js.map +1 -0
- package/dist/signaling/frames.sys.d.ts +145 -0
- package/dist/signaling/frames.sys.d.ts.map +1 -0
- package/dist/signaling/frames.sys.js +53 -0
- package/dist/signaling/frames.sys.js.map +1 -0
- package/dist/signaling/handshakeGiveUp.d.ts +36 -0
- package/dist/signaling/handshakeGiveUp.d.ts.map +1 -0
- package/dist/signaling/handshakeGiveUp.js +48 -0
- package/dist/signaling/handshakeGiveUp.js.map +1 -0
- package/dist/signaling/heartbeat.d.ts +34 -0
- package/dist/signaling/heartbeat.d.ts.map +1 -0
- package/dist/signaling/heartbeat.js +52 -0
- package/dist/signaling/heartbeat.js.map +1 -0
- package/dist/signaling/pendingRequests.d.ts +33 -0
- package/dist/signaling/pendingRequests.d.ts.map +1 -0
- package/dist/signaling/pendingRequests.js +57 -0
- package/dist/signaling/pendingRequests.js.map +1 -0
- package/dist/signaling/reconnector.d.ts +43 -0
- package/dist/signaling/reconnector.d.ts.map +1 -0
- package/dist/signaling/reconnector.js +76 -0
- package/dist/signaling/reconnector.js.map +1 -0
- package/dist/signaling/registry.d.ts +100 -0
- package/dist/signaling/registry.d.ts.map +1 -0
- package/dist/signaling/registry.js +217 -0
- package/dist/signaling/registry.js.map +1 -0
- package/dist/signaling/resumeDeadline.d.ts +48 -0
- package/dist/signaling/resumeDeadline.d.ts.map +1 -0
- package/dist/signaling/resumeDeadline.js +89 -0
- package/dist/signaling/resumeDeadline.js.map +1 -0
- package/dist/signaling/tokenExpiry.d.ts +89 -0
- package/dist/signaling/tokenExpiry.d.ts.map +1 -0
- package/dist/signaling/tokenExpiry.js +106 -0
- package/dist/signaling/tokenExpiry.js.map +1 -0
- package/dist/signaling/webSocket.d.ts +59 -0
- package/dist/signaling/webSocket.d.ts.map +1 -0
- package/dist/signaling/webSocket.js +50 -0
- package/dist/signaling/webSocket.js.map +1 -0
- package/dist/state/callMachine.d.ts +56 -0
- package/dist/state/callMachine.d.ts.map +1 -0
- package/dist/state/callMachine.js +176 -0
- package/dist/state/callMachine.js.map +1 -0
- package/dist/state/callRecv.d.ts +12 -0
- package/dist/state/callRecv.d.ts.map +1 -0
- package/dist/state/callRecv.js +255 -0
- package/dist/state/callRecv.js.map +1 -0
- package/dist/state/engineMachine.d.ts +41 -0
- package/dist/state/engineMachine.d.ts.map +1 -0
- package/dist/state/engineMachine.js +210 -0
- package/dist/state/engineMachine.js.map +1 -0
- package/dist/state/forceEnd.d.ts +44 -0
- package/dist/state/forceEnd.d.ts.map +1 -0
- package/dist/state/forceEnd.js +96 -0
- package/dist/state/forceEnd.js.map +1 -0
- package/dist/state/roomMachine.d.ts +92 -0
- package/dist/state/roomMachine.d.ts.map +1 -0
- package/dist/state/roomMachine.js +319 -0
- package/dist/state/roomMachine.js.map +1 -0
- package/dist/state/roomRecv.d.ts +7 -0
- package/dist/state/roomRecv.d.ts.map +1 -0
- package/dist/state/roomRecv.js +209 -0
- package/dist/state/roomRecv.js.map +1 -0
- package/dist/state/types.d.ts +61 -0
- package/dist/state/types.d.ts.map +1 -0
- package/dist/state/types.js +30 -0
- package/dist/state/types.js.map +1 -0
- package/dist/version.d.ts +11 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +11 -0
- package/dist/version.js.map +1 -0
- package/package.json +35 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BLiYing
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/bytes.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UTF-8 字节数。
|
|
3
|
+
*
|
|
4
|
+
* **单拎一个模块,是因为协议的上限全是「字节」不是「字符」**——§2.5 的那一列 id、
|
|
5
|
+
* §2.6 的单帧上限,都按字节判。这条规则一旦有两份实现就会各修各的,而两处判断不
|
|
6
|
+
* 一致时的症状最难查:本地按字符算放行、服务端按字节算拒掉,宿主看到的是一个
|
|
7
|
+
* 「明明校验过了却还是被拒」的 1004。
|
|
8
|
+
*/
|
|
9
|
+
/** byteLength 按 UTF-8 计算字节数——协议的上限是**字节**不是字符。 */
|
|
10
|
+
export declare function byteLength(value: string): number;
|
|
11
|
+
//# sourceMappingURL=bytes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../src/bytes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,kDAAkD;AAClD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD"}
|
package/dist/bytes.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UTF-8 字节数。
|
|
3
|
+
*
|
|
4
|
+
* **单拎一个模块,是因为协议的上限全是「字节」不是「字符」**——§2.5 的那一列 id、
|
|
5
|
+
* §2.6 的单帧上限,都按字节判。这条规则一旦有两份实现就会各修各的,而两处判断不
|
|
6
|
+
* 一致时的症状最难查:本地按字符算放行、服务端按字节算拒掉,宿主看到的是一个
|
|
7
|
+
* 「明明校验过了却还是被拒」的 1004。
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* 复用同一个编码器。
|
|
11
|
+
*
|
|
12
|
+
* `TextEncoder` 是无状态的(`encode()` 不像 `encodeInto()` 那样带游标),
|
|
13
|
+
* 复用没有线程/重入问题;而这两条调用路径都在热路上——每发一帧走一次。
|
|
14
|
+
*/
|
|
15
|
+
const encoder = new TextEncoder();
|
|
16
|
+
/** byteLength 按 UTF-8 计算字节数——协议的上限是**字节**不是字符。 */
|
|
17
|
+
export function byteLength(value) {
|
|
18
|
+
return encoder.encode(value).length;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=bytes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bytes.js","sourceRoot":"","sources":["../src/bytes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;GAKG;AACH,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,kDAAkD;AAClD,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CallOptions 是 {@link CallEngine.call} 的可选项(HOST_INTEGRATION_DESIGN §3.3)。
|
|
3
|
+
*
|
|
4
|
+
* 传布尔值等同旧的 `isGroup` 参数(三参数签名保持兼容)。
|
|
5
|
+
*
|
|
6
|
+
* 单拎一个模块(而不是留在 engine.ts 里):CONVENTIONS §2 把 engine.ts 的体量红线
|
|
7
|
+
* 卡得很紧——它是公开门面,一度正好顶到旧的 400 行阈值。校验逻辑是纯函数,
|
|
8
|
+
* 值得像 `protocolId.ts` 那样独立成模块直接单测,也让门面文件少扛一份重量。
|
|
9
|
+
*/
|
|
10
|
+
export interface CallOptions {
|
|
11
|
+
isGroup?: boolean;
|
|
12
|
+
/** 宿主自己的群号,≤64 字节、禁止空白与换行;超限本地就地拒掉,见 `CallEngine.call`。 */
|
|
13
|
+
chatGroupId?: string;
|
|
14
|
+
/** opaque 字符串,≤4096 字节,原样透传给被叫与 webhook。 */
|
|
15
|
+
userData?: string;
|
|
16
|
+
/** 振铃超时秒数,默认 30,范围 5~120(越界服务端钳到边界)。 */
|
|
17
|
+
timeoutSec?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* violatesCallOptionLimits 报告 `chatGroupId` / `userData` 是不是超了协议 §2.6 的限额。
|
|
21
|
+
*
|
|
22
|
+
* 只判断、不抛错、不记日志——那两件事各自的语境不同(`engine.ts` 的 `call()` 要
|
|
23
|
+
* 就地拒掉并抛 `error` 事件),调用方按自己的出口处理。空串永远不算违规
|
|
24
|
+
* (`''` 表示宿主没给这个可选项)。
|
|
25
|
+
*/
|
|
26
|
+
export declare function violatesCallOptionLimits(chatGroupId: string, userData: string): boolean;
|
|
27
|
+
//# sourceMappingURL=callOptions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callOptions.d.ts","sourceRoot":"","sources":["../src/callOptions.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAOD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAKvF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { byteLength } from './bytes.js';
|
|
2
|
+
/** 协议 §2.6:chat_group_id 的字节上限。 */
|
|
3
|
+
const MAX_CHAT_GROUP_ID_BYTES = 64;
|
|
4
|
+
/** 协议 §2.6:user_data 的字节上限。 */
|
|
5
|
+
const MAX_USER_DATA_BYTES = 4096;
|
|
6
|
+
/**
|
|
7
|
+
* violatesCallOptionLimits 报告 `chatGroupId` / `userData` 是不是超了协议 §2.6 的限额。
|
|
8
|
+
*
|
|
9
|
+
* 只判断、不抛错、不记日志——那两件事各自的语境不同(`engine.ts` 的 `call()` 要
|
|
10
|
+
* 就地拒掉并抛 `error` 事件),调用方按自己的出口处理。空串永远不算违规
|
|
11
|
+
* (`''` 表示宿主没给这个可选项)。
|
|
12
|
+
*/
|
|
13
|
+
export function violatesCallOptionLimits(chatGroupId, userData) {
|
|
14
|
+
if (chatGroupId !== '' && (byteLength(chatGroupId) > MAX_CHAT_GROUP_ID_BYTES || /\s/.test(chatGroupId))) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
return byteLength(userData) > MAX_USER_DATA_BYTES;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=callOptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callOptions.js","sourceRoot":"","sources":["../src/callOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAqBxC,mCAAmC;AACnC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AACnC,+BAA+B;AAC/B,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAEjC;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,WAAmB,EAAE,QAAgB;IAC5E,IAAI,WAAW,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,uBAAuB,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QACxG,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,UAAU,CAAC,QAAQ,CAAC,GAAG,mBAAmB,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* checkDeviceId 校验 `device_id`,不合规就抛 `RtcError(bad_params)`。
|
|
3
|
+
*
|
|
4
|
+
* 抛的码**和服务端拒绝时是同一个 1004**——宿主那套按 code 分支的错误处理不用为
|
|
5
|
+
* 「本地拦下的」和「服务端拒的」写两遍,具体哪里不对看 `cause`。
|
|
6
|
+
*
|
|
7
|
+
* 宿主也可以自己先调它验一遍自己生成的 id,不必等到 `login()`。
|
|
8
|
+
*/
|
|
9
|
+
export declare function checkDeviceId(deviceId: string): void;
|
|
10
|
+
//# sourceMappingURL=deviceId.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deviceId.d.ts","sourceRoot":"","sources":["../src/deviceId.ts"],"names":[],"mappings":"AA8BA;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAqBpD"}
|
package/dist/deviceId.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ErrorCode, RtcError } from './errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* `device_id` 的入参校验(协议 §2.5)。
|
|
4
|
+
*
|
|
5
|
+
* # 为什么要在端上拦一道
|
|
6
|
+
*
|
|
7
|
+
* **不拦的症状是「登录失败,没有下文」**:服务端回 1004,客户端握手失败,
|
|
8
|
+
* 而服务端那句说得很清楚的「device_id 只允许 [A-Za-z0-9_-]」**到不了宿主手里**——
|
|
9
|
+
* 宿主看到的只有一个 `bad_params`。安卓真机上踩过一次(`Build.MODEL` 是
|
|
10
|
+
* `Pixel 2 XL`,带空格),查了一轮才定位到是机型名。
|
|
11
|
+
*
|
|
12
|
+
* Web 上最常见的错法是拿浏览器信息拼 id:`navigator.platform` 是 `MacIntel` 没事,
|
|
13
|
+
* 但 `navigator.userAgent` 里到处是空格、斜杠和括号,UUID 带的连字符倒是合规的。
|
|
14
|
+
*
|
|
15
|
+
* # 只校验,不改写
|
|
16
|
+
*
|
|
17
|
+
* `device_id` 要求**跨重启稳定**,SDK 悄悄替宿主改掉,宿主自己那套设备管理
|
|
18
|
+
* (设备列表、注销设备、顶号)就跟服务端对不上账了。清洗是宿主的事。
|
|
19
|
+
*
|
|
20
|
+
* 真要清洗,**别用「删掉非法字符」那种做法**:`MI 8` 与 `MI8` 是两款不同的机器,
|
|
21
|
+
* 删完就撞成同一个 device_id,而撞号的后果是两台设备互相顶号、轮流把对方踢下线。
|
|
22
|
+
* 换成 `-` 才不会。
|
|
23
|
+
*/
|
|
24
|
+
/** 协议 §2.5:`device_id` ≤64 **字节**(不是字符)。 */
|
|
25
|
+
const MAX_DEVICE_ID_BYTES = 64;
|
|
26
|
+
const ALLOWED = /^[A-Za-z0-9_-]*$/;
|
|
27
|
+
/**
|
|
28
|
+
* checkDeviceId 校验 `device_id`,不合规就抛 `RtcError(bad_params)`。
|
|
29
|
+
*
|
|
30
|
+
* 抛的码**和服务端拒绝时是同一个 1004**——宿主那套按 code 分支的错误处理不用为
|
|
31
|
+
* 「本地拦下的」和「服务端拒的」写两遍,具体哪里不对看 `cause`。
|
|
32
|
+
*
|
|
33
|
+
* 宿主也可以自己先调它验一遍自己生成的 id,不必等到 `login()`。
|
|
34
|
+
*/
|
|
35
|
+
export function checkDeviceId(deviceId) {
|
|
36
|
+
if (deviceId === '') {
|
|
37
|
+
throw new RtcError(ErrorCode.badParams, {
|
|
38
|
+
cause: new Error('device_id 不能为空(协议 §2.5)'),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const bytes = new TextEncoder().encode(deviceId).length;
|
|
42
|
+
if (bytes > MAX_DEVICE_ID_BYTES) {
|
|
43
|
+
throw new RtcError(ErrorCode.badParams, {
|
|
44
|
+
cause: new Error(`device_id 长 ${bytes} 字节,上限 ${MAX_DEVICE_ID_BYTES}(协议 §2.5)`),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (!ALLOWED.test(deviceId)) {
|
|
48
|
+
const bad = [...deviceId].find((ch) => !ALLOWED.test(ch));
|
|
49
|
+
throw new RtcError(ErrorCode.badParams, {
|
|
50
|
+
cause: new Error(`device_id 只允许 [A-Za-z0-9_-],出现了 '${bad}'(协议 §2.5)。` +
|
|
51
|
+
'拿 userAgent 之类拼 id 的话记得先清洗——里面空格和括号是常态'),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=deviceId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deviceId.js","sourceRoot":"","sources":["../src/deviceId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,4CAA4C;AAC5C,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,MAAM,OAAO,GAAG,kBAAkB,CAAC;AAEnC;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,IAAI,QAAQ,KAAK,EAAE,EAAE,CAAC;QACpB,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE;YACtC,KAAK,EAAE,IAAI,KAAK,CAAC,yBAAyB,CAAC;SAC5C,CAAC,CAAC;IACL,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;IACxD,IAAI,KAAK,GAAG,mBAAmB,EAAE,CAAC;QAChC,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE;YACtC,KAAK,EAAE,IAAI,KAAK,CAAC,eAAe,KAAK,UAAU,mBAAmB,WAAW,CAAC;SAC/E,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1D,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE;YACtC,KAAK,EAAE,IAAI,KAAK,CACd,oCAAoC,GAAG,aAAa;gBAClD,wCAAwC,CAC3C;SACF,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
package/dist/engine.d.ts
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import type { CallOptions } from './callOptions.js';
|
|
2
|
+
import type { EngineEventHandler, EngineEventName } from './events.js';
|
|
3
|
+
import type { MediaAdapter } from './media/mediaAdapter.js';
|
|
4
|
+
import type { ViewElement } from './media/viewRegistry.js';
|
|
5
|
+
import type { VideoProfile } from './media/videoProfile.js';
|
|
6
|
+
import type { HelloOk } from './signaling/connection.js';
|
|
7
|
+
import type { Layer, MediaType } from './signaling/enums.js';
|
|
8
|
+
import type { WebSocketFactory } from './signaling/webSocket.js';
|
|
9
|
+
import type { EngineContext } from './state/engineMachine.js';
|
|
10
|
+
/**
|
|
11
|
+
* CallEngine 是门面:把信令连接、状态机、媒体适配器接在一起。
|
|
12
|
+
*
|
|
13
|
+
* # 它自己不做决策
|
|
14
|
+
*
|
|
15
|
+
* 「现在能不能 accept」「该不该抛 onCallEnd」全在状态机里(那是纯逻辑,跑一致性向量);
|
|
16
|
+
* 「SDP 长什么样」全在媒体适配器里。门面只做三件事:**路由输入、填 SDP、派发事件**。
|
|
17
|
+
*
|
|
18
|
+
* # 为什么门面要填 SDP
|
|
19
|
+
*
|
|
20
|
+
* 状态机是纯的,产不出 SDP。所以它产出的协商帧是**意图**——`sdp` 字段留空,
|
|
21
|
+
* 由门面从媒体适配器取真值填进去再发。这条边界让状态机能在 Node 里被完整测试。
|
|
22
|
+
*/
|
|
23
|
+
/** EngineOptions 是构造参数。 */
|
|
24
|
+
export interface EngineOptions {
|
|
25
|
+
/** 信令地址,如 `wss://rtc.example.com/v1/ws`。 */
|
|
26
|
+
url: string;
|
|
27
|
+
deviceId: string;
|
|
28
|
+
/** 媒体适配器。默认用浏览器 WebRTC;测试可注入假实现。 */
|
|
29
|
+
media?: MediaAdapter;
|
|
30
|
+
/** WebSocket 工厂。默认用浏览器原生;测试可注入假实现。 */
|
|
31
|
+
webSocketFactory?: WebSocketFactory;
|
|
32
|
+
/**
|
|
33
|
+
* 采集画质档位(360p / 720p / 1080p,默认 720p)。
|
|
34
|
+
*
|
|
35
|
+
* **只对默认媒体适配器生效**——自己传 `media` 的宿主在构造适配器时传它。
|
|
36
|
+
* 画质是宿主策略,不是 RTC 服务端下发的,理由见 `media/videoProfile.ts`。
|
|
37
|
+
*/
|
|
38
|
+
videoProfile?: VideoProfile;
|
|
39
|
+
}
|
|
40
|
+
export type { CallOptions } from './callOptions.js';
|
|
41
|
+
/** CallEngine 是宿主唯一需要接触的类型。 */
|
|
42
|
+
export declare class CallEngine {
|
|
43
|
+
private readonly bus;
|
|
44
|
+
private readonly bridge;
|
|
45
|
+
private readonly media;
|
|
46
|
+
private readonly options;
|
|
47
|
+
private readonly sender;
|
|
48
|
+
private connection;
|
|
49
|
+
/** 握手拿到的自己的 uid。用来挡「呼叫自己」,也供宿主读。 */
|
|
50
|
+
private myUid;
|
|
51
|
+
private readonly loop;
|
|
52
|
+
/** 最近一次 hello.ok 喂进状态机的那个 promise,`login()` 要等它。 */
|
|
53
|
+
private helloApplied;
|
|
54
|
+
/** 终态销毁标记。见 {@link destroy}。 */
|
|
55
|
+
private destroyed;
|
|
56
|
+
constructor(options: EngineOptions);
|
|
57
|
+
/** on 订阅事件,返回退订函数。事件表见 events.ts(= 设计文档 §7.5)。 */
|
|
58
|
+
on<K extends EngineEventName>(name: K, handler: EngineEventHandler<K>): () => void;
|
|
59
|
+
/** uid 是当前登录的用户。未登录时是空串。 */
|
|
60
|
+
get uid(): string;
|
|
61
|
+
/** state 返回当前的通话与房间状态,供 UI 渲染。 */
|
|
62
|
+
get state(): EngineContext;
|
|
63
|
+
/**
|
|
64
|
+
* login 建立信令连接并完成握手。
|
|
65
|
+
*
|
|
66
|
+
* # 重复调用会被拒掉
|
|
67
|
+
*
|
|
68
|
+
* **两条 WS 带着同一个 uid + device_id,服务端按顶号把先来的那条踢下线**,于是宿主收到
|
|
69
|
+
* 一个**假的 `kickedOut{takenOver}`**——「账号在别处登录」,可根本没有别处,就是这台
|
|
70
|
+
* 机器自己把自己踢了。更隐蔽的是旧那条**从不 close**:它的 `ResumeDeadline` 在第一次
|
|
71
|
+
* 断开时就已经武装好(只有 `close()` 撤得掉),约 75 秒后照样触发 `onSessionUnrecoverable`,
|
|
72
|
+
* 把**新会话**的房间清成 idle 并合成一条 `onCallEnd(network)`——用户刚换票重登、
|
|
73
|
+
* 正通着话,画面无故收场。而 `events.ts` 恰恰建议宿主在 `kickedOut{authExpired}` 之后
|
|
74
|
+
* 「取一枚新票再 login」,正好走的就是这条路。
|
|
75
|
+
*
|
|
76
|
+
* 要换账号或换一枚票,先 `logout()`。(连着的时候换票用 {@link updateToken}。)
|
|
77
|
+
* iOS 的 `login(_:)` 早就是这条规矩,本端是没跟上的那个。
|
|
78
|
+
*
|
|
79
|
+
* # 失败会把摊子收干净
|
|
80
|
+
*
|
|
81
|
+
* 握手失败时把连接关掉、`connection` 置回 null。不收的话上面那道门会把**重试**
|
|
82
|
+
* 也一起挡掉,用户从此再也登不上——比原来的毛病还糟。
|
|
83
|
+
*/
|
|
84
|
+
login(token: string): Promise<HelloOk>;
|
|
85
|
+
/**
|
|
86
|
+
* updateToken 换一枚新的接入票。**下一次重连时生效,不打断当前连接。**
|
|
87
|
+
*
|
|
88
|
+
* # 为什么是宿主推给我们,而不是我们去要
|
|
89
|
+
*
|
|
90
|
+
* 协议 §1.5 说 `4401` 的处置是「换新 token 后重连」。**换票是宿主的事**——
|
|
91
|
+
* 票从宿主的账号体系来,engine 不认识那套东西,也不该替它决定什么时候去要。
|
|
92
|
+
* 所以这里是 push 不是 pull:没有「token provider 回调」这种设计。
|
|
93
|
+
*
|
|
94
|
+
* # 宿主该怎么用
|
|
95
|
+
*
|
|
96
|
+
* 在 `disconnected` 里看到 `code === 4401` 就去取一枚新票、调这个方法。
|
|
97
|
+
* 重连是已经排好的(第一档 1 秒起),所以**只要在下一次尝试之前调到就行**;
|
|
98
|
+
* 连续 3 次鉴权失败之后 engine 会抛 `kickedOut` 收手,那时就只能重新 `login` 了。
|
|
99
|
+
*
|
|
100
|
+
* 连上着的时候调它也是安全的(比如票快过期了提前换)——当前连接不受影响。
|
|
101
|
+
*/
|
|
102
|
+
updateToken(token: string, expiresAtMs?: number): void;
|
|
103
|
+
/** logout 关掉连接与媒体。 */
|
|
104
|
+
logout(): void;
|
|
105
|
+
/**
|
|
106
|
+
* destroy 终态销毁:`logout()` + 清空全部事件订阅。**不可逆**,给宿主整个放手音视频能力时用
|
|
107
|
+
* (账号注销、SDK 卸载)。**可重复调用**——已经销毁过再调什么都不做,不会重复 logout。
|
|
108
|
+
*
|
|
109
|
+
* # 之后再调别的方法
|
|
110
|
+
*
|
|
111
|
+
* 会发起动作的方法(`login` / `call` / `accept` / … / `publishMicrophone` / `openCamera` 等,
|
|
112
|
+
* 经 {@link act} 或 {@link mediaApi} 转发的那一批)一律**抛 `2005 invalid_state`**,
|
|
113
|
+
* 不是静默空操作:事件订阅已经清空,静默的话宿主的 `hangup()` 之类调用会石沉大海——
|
|
114
|
+
* 不抛错也不会有任何事件把原因告诉它,界面只会永远停在转圈。与 `login()` 拦
|
|
115
|
+
* 「已经登录了」同一个理由:让宿主一调就知道错在哪,不用猜。
|
|
116
|
+
*
|
|
117
|
+
* `logout()` / `forceEnd()` / `on()` / `uid` / `state`,以及读或清理类的方法
|
|
118
|
+
* (`attachView` 传 `null`、`attachLocalView` 传 `null`、`localTrack`、`stopLocalPreview`、
|
|
119
|
+
* `updateToken`)**不受影响**,销毁后调用仍然安全——宿主卸载时经常无脑清理这几个,
|
|
120
|
+
* 不该因为清理顺序先后而报错。
|
|
121
|
+
*/
|
|
122
|
+
destroy(): void;
|
|
123
|
+
/**
|
|
124
|
+
* assertNotDestroyed 挡住 {@link destroy} 之后的调用。见 destroy 的文档注释。
|
|
125
|
+
*/
|
|
126
|
+
private assertNotDestroyed;
|
|
127
|
+
/**
|
|
128
|
+
* act 是「发一个业务动作、等状态机处理完」的公共外壳:`call` / `accept` / `reject` / `cancel` /
|
|
129
|
+
* `hangup` / `inviteMore` / `joinCall` / `joinRoom` / `leaveRoom` 共用,唯一的区别只是
|
|
130
|
+
* op 名与参数。抽出来顺带把 {@link assertNotDestroyed} 的检查收在一处。
|
|
131
|
+
*/
|
|
132
|
+
private act;
|
|
133
|
+
/**
|
|
134
|
+
* call 发起通话。**名单里不能有自己**,见 {@link rejectsSelf}。
|
|
135
|
+
*
|
|
136
|
+
* `options` 传布尔值等同旧的 `isGroup` 参数(三参数签名保持兼容);传 {@link CallOptions}
|
|
137
|
+
* 可以带上群号 / user_data / 振铃超时(HOST_INTEGRATION_DESIGN §3.3)。
|
|
138
|
+
*/
|
|
139
|
+
call(calleeIds: string[], mediaType: MediaType, options?: boolean | CallOptions): Promise<void>;
|
|
140
|
+
/**
|
|
141
|
+
* joinCall 是「群成员看到『进行中』主动加入」(协议 §4.1 `call.join`)。
|
|
142
|
+
*
|
|
143
|
+
* **「怎么知道有通话在进行中」不是 engine 的事**——宿主拿 webhook `call.started`
|
|
144
|
+
* 或后台 `GET /v1/calls?chat_group_id=...&active=1` 自己判断、自己摆横幅。
|
|
145
|
+
* 服务端拒绝(不存在 / 已结束 / 满员 / 本人已在通话中 / 宿主邀请鉴权回调拒绝 1409)
|
|
146
|
+
* 时与 `call()` 被拒同一个出口:`onError` + `onCallEnd(error)`。
|
|
147
|
+
*/
|
|
148
|
+
joinCall(callId: string): Promise<void>;
|
|
149
|
+
/** accept 接听。 */
|
|
150
|
+
accept(): Promise<void>;
|
|
151
|
+
/** reject 拒接。 */
|
|
152
|
+
reject(): Promise<void>;
|
|
153
|
+
/** cancel 取消呼出(**仅接通前**;接通后用 hangup)。 */
|
|
154
|
+
cancel(): Promise<void>;
|
|
155
|
+
/** hangup 挂断(接通后,主被叫都用它)。 */
|
|
156
|
+
hangup(): Promise<void>;
|
|
157
|
+
/**
|
|
158
|
+
* forceEnd 强制结束当前这一场:**结束帧立刻上线路,本地立刻收场,不等服务端**(设计文档 §7.5,五端同名)。
|
|
159
|
+
*
|
|
160
|
+
* 给「红键按下去、等不到结束事件」用——uikit 的红键看门狗 3 秒到点就调它。宿主自画 UI 时同理:
|
|
161
|
+
* `hangup()` 发出去几秒没收到 `callEnd`,就调这个。同步、不抛。
|
|
162
|
+
*
|
|
163
|
+
* 与 `hangup()` 的区别:`hangup()` 只发帧、等服务端的 `call.ended` 推进状态(§5.1),
|
|
164
|
+
* 帧没发出去或被拒了,这一场就收不掉(2026-09-13 iOS frank:界面收了,人还挂在房里四分钟)。
|
|
165
|
+
* `forceEnd()` 不等:按此刻状态挑结束帧(通话中 hangup、响铃中 reject、拨出中 cancel、
|
|
166
|
+
* 会议里 room.leave)**直接交给信令连接**,再本地收场并抛 `callEnd` / `roomLeft`;
|
|
167
|
+
* 服务端随后的 `call.ended` 会因为本地已是 idle 被静默丢弃,不会抛第二次。
|
|
168
|
+
*
|
|
169
|
+
* 收场之后才到的东西也兜住了:迟到的 `room.join.ok` 补发 `room.leave`(服务端只验房票、
|
|
170
|
+
* 不查通话成员),迟到的 `call.invite.ok` 补发 `call.cancel`、`call.connected` 补发 `call.hangup`,
|
|
171
|
+
* 迟到的候选与 SDP 不再交给媒体层。
|
|
172
|
+
*
|
|
173
|
+
* **已知限制**:没登录 / 连接断着时帧发不出去,只做本地收场;服务端那边由恢复窗口到期兜底。
|
|
174
|
+
*/
|
|
175
|
+
forceEnd(): void;
|
|
176
|
+
/**
|
|
177
|
+
* inviteMore 往进行中的群通话里再拉人(协议 §4.1 `call.invite_more`)。
|
|
178
|
+
* 名单里同样不能有自己,见 {@link rejectsSelf}。
|
|
179
|
+
*
|
|
180
|
+
* **通话里的任何人都能发**(2026-09-15 起,原先仅主叫);还在响铃 / 已离场的人发会被服务端拒成
|
|
181
|
+
* `1407 not_call_owner`(交互稿 §05)。房间满了回 `1202 room_full`;离场的发起人也能被重新邀请。
|
|
182
|
+
*/
|
|
183
|
+
inviteMore(calleeIds: string[]): Promise<void>;
|
|
184
|
+
/**
|
|
185
|
+
* probeMicrophone 在拨出 / 接听**之前**探一下麦克风权限(交互稿 §01)。
|
|
186
|
+
*
|
|
187
|
+
* 拿到就放掉,不占设备;被拒抛 `2001`、没设备抛 `2002`。
|
|
188
|
+
*/
|
|
189
|
+
probeMicrophone(): Promise<void>;
|
|
190
|
+
/**
|
|
191
|
+
* probeCamera 只探摄像头权限,**不起预览**。契约同 `probeMicrophone`。
|
|
192
|
+
*
|
|
193
|
+
* 摄像头默认关着的场合(群通话、来电页上关掉了摄像头)也可能要先问权限,
|
|
194
|
+
* 拿预览去探会把摄像头真的打开。要看见自己另调 `startLocalPreview`。
|
|
195
|
+
*/
|
|
196
|
+
probeCamera(): Promise<void>;
|
|
197
|
+
/** joinRoom 直接进一个会议房(不走振铃)。 */
|
|
198
|
+
joinRoom(roomId: string, roomToken: string, autoSubscribe?: boolean): Promise<void>;
|
|
199
|
+
/** leaveRoom 离房。 */
|
|
200
|
+
leaveRoom(): Promise<void>;
|
|
201
|
+
/** publishMicrophone 发布麦克风,返回轨道的 cid。 */
|
|
202
|
+
publishMicrophone(): Promise<string>;
|
|
203
|
+
/**
|
|
204
|
+
* openMicrophone 是麦克风开关的**按类型**便捷接口(与腾讯 TUICallEngine 同名)。
|
|
205
|
+
*
|
|
206
|
+
* 这条轨道还没发布过就发布(等价 `publishMicrophone()`);已经发布了就取消静音,
|
|
207
|
+
* **不会重新发布**——重复发布同一路麦克风会在 pub PC 上多挂一条 sender。
|
|
208
|
+
*
|
|
209
|
+
* 「发没发布过」问的是**媒体适配器自己的账**(`media.publishedMicrophoneCid()`),
|
|
210
|
+
* 不在门面另开一份:宿主先直接调 `publishMicrophone()` 发布过、再调这个方法的话,
|
|
211
|
+
* 门面自己那份账不知道已经发布过,会误判成「没发布」再发一次(2026-09-15 iOS 踩过)。
|
|
212
|
+
* `publishMicrophone()` / `setMuted(cid)` 仍然保留,给需要自己管 cid 的宿主用。
|
|
213
|
+
*/
|
|
214
|
+
openMicrophone(): Promise<void>;
|
|
215
|
+
/**
|
|
216
|
+
* closeMicrophone 关麦克风:对已发布的那条轨道 `setMuted(cid, true)`——**不 unpublish**,
|
|
217
|
+
* 协商保留。没发布过是空操作。
|
|
218
|
+
*/
|
|
219
|
+
closeMicrophone(): Promise<void>;
|
|
220
|
+
/**
|
|
221
|
+
* startLocalPreview 只起本端采集,**不发布**(设计文档 §7.5,四端同名)。
|
|
222
|
+
*
|
|
223
|
+
* 拨出中还没有房间,推流无从谈起,但界面这时就该让人看见自己(草图 §03-E)。
|
|
224
|
+
* 随后的 `publishCamera` 复用这条轨道,不会把摄像头开第二次。
|
|
225
|
+
*
|
|
226
|
+
* 返回轨道的 cid,宿主拿它调 `attachLocalView`。
|
|
227
|
+
*/
|
|
228
|
+
startLocalPreview(): Promise<string>;
|
|
229
|
+
/**
|
|
230
|
+
* stopLocalPreview 进房前关摄像头:**真的停采集**,指示灯灭(设计文档 §7.5)。
|
|
231
|
+
*
|
|
232
|
+
* 只停还没发布的预览;已发布的摄像头走 `setMuted`。再打开时重新 `startLocalPreview`,cid 会变。
|
|
233
|
+
*/
|
|
234
|
+
stopLocalPreview(): Promise<void>;
|
|
235
|
+
/** publishCamera 发布摄像头。已经在预览的话复用那条轨道。 */
|
|
236
|
+
publishCamera(simulcast?: boolean): Promise<string>;
|
|
237
|
+
/**
|
|
238
|
+
* openCamera 是摄像头开关的**按类型**便捷接口。还没发布就发布(有本端预览时复用它,
|
|
239
|
+
* 同 `publishCamera()` 现有逻辑);已发布就取消静音——通话中开关摄像头走的是
|
|
240
|
+
* `setMuted` 既有的「关停采集、开重新采集换 sender」语义,不重新协商。
|
|
241
|
+
*
|
|
242
|
+
* 「发没发布过」同样问媒体适配器自己的账(`media.publishedCameraCid()`),
|
|
243
|
+
* 理由见 {@link openMicrophone}。
|
|
244
|
+
*/
|
|
245
|
+
openCamera(): Promise<void>;
|
|
246
|
+
/** closeCamera 关摄像头:`setMuted(cid, true)`(停采集,指示灯灭;不 unpublish)。没发布过是空操作。 */
|
|
247
|
+
closeCamera(): Promise<void>;
|
|
248
|
+
/**
|
|
249
|
+
* setMuted 开关本端某条轨道。**不是 unpublish**,协商保留。
|
|
250
|
+
*
|
|
251
|
+
* 摄像头关 = 停采集(指示灯灭),开 = 重新采集换上去,cid 不变;重新采集失败时抛 RtcError。
|
|
252
|
+
*/
|
|
253
|
+
setMuted(cid: string, muted: boolean): Promise<void>;
|
|
254
|
+
/** localTrack 取本端轨道做预览。 */
|
|
255
|
+
localTrack(cid: string): MediaStreamTrack | undefined;
|
|
256
|
+
/**
|
|
257
|
+
* attachView 把某个 uid 的远端画面挂到一个 `<video>` 上;传 `null` 卸载。
|
|
258
|
+
*
|
|
259
|
+
* **这是 UI 拿到画面的唯一途径**(CONVENTIONS §1):uikit 不许自己碰
|
|
260
|
+
* `RTCPeerConnection`,也不该自己拼 `MediaStream`。
|
|
261
|
+
*/
|
|
262
|
+
attachView(uid: string, el: ViewElement | null): void;
|
|
263
|
+
/** attachLocalView 把本端某条轨道挂到元素上做预览;传 `null` 卸载。 */
|
|
264
|
+
attachLocalView(cid: string, el: ViewElement | null): void;
|
|
265
|
+
/**
|
|
266
|
+
* setRemoteLayer 报某人画面的**层上界**(协议 §3.5:上界不是命令)。
|
|
267
|
+
*
|
|
268
|
+
* 九宫格缩略图报 `l`、双击放大报 `h`。**不触发重协商**,也不保证立刻切——
|
|
269
|
+
* 服务端要等目标层的关键帧,还会再按带宽估计压一次。
|
|
270
|
+
*/
|
|
271
|
+
setRemoteLayer(uid: string, layer: Layer): Promise<void>;
|
|
272
|
+
/**
|
|
273
|
+
* rejectsSelf 挡住「名单里有自己」,就地报错并返回 true。
|
|
274
|
+
*
|
|
275
|
+
* 服务端会以 `1004 bad_params` 拒掉("callee_ids 不能含主叫自己"),但那条链路上的
|
|
276
|
+
* 失败很难看懂:界面已经乐观地进了「正在呼叫…」,而错误只是一条没头没尾的 1004。
|
|
277
|
+
* (实测撞过:Demo 的群呼默认名单里正好有登录的那个人。)
|
|
278
|
+
*
|
|
279
|
+
* **一份实现供 call 与 inviteMore 共用**——两处各写一遍的话,改了一处忘了另一处,
|
|
280
|
+
* 就又是一个「同一条规则在一处成立、另一处不成立」。
|
|
281
|
+
*/
|
|
282
|
+
private rejectsSelf;
|
|
283
|
+
/**
|
|
284
|
+
* rejectsBadCallOptions 挡住超限的 `chatGroupId` / `userData`,就地报错并返回 true。
|
|
285
|
+
*
|
|
286
|
+
* 服务端会以 `1004 bad_params` 拒掉,但那条链路上主叫已经乐观地进了「正在呼叫…」,
|
|
287
|
+
* 错误只是一条没头没尾的 1004——与 {@link rejectsSelf} 同一个理由,本地先拦,
|
|
288
|
+
* 走同一个出口(HOST_INTEGRATION_DESIGN §3.3)。判断本身在 `callOptions.ts`
|
|
289
|
+
* (纯函数,直接单测);这里只管日志与出口这两件带副作用的事。
|
|
290
|
+
*/
|
|
291
|
+
private rejectsBadCallOptions;
|
|
292
|
+
/** mediaApi 是交给 media/engineMediaApi 那几个编排函数的一把依赖。 */
|
|
293
|
+
private mediaApi;
|
|
294
|
+
/**
|
|
295
|
+
* wiring 是交给 engineWiring 那两个装配函数的一把依赖。
|
|
296
|
+
*
|
|
297
|
+
* 每次现造一个:里面的 `connection` 是闭包,读的永远是**当前**那条连接
|
|
298
|
+
* ——它会随重连换对象。
|
|
299
|
+
*/
|
|
300
|
+
private wiring;
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|