tirtc-devtools-cli 0.0.9 → 0.0.11
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/README.md +17 -11
- package/USAGE.md +72 -33
- package/bin/tirtc-devtools-cli.js +1 -1
- package/dist/cli/src/bootstrap_flows.d.ts +46 -0
- package/dist/cli/src/bootstrap_flows.js +249 -0
- package/dist/{devtools/cli → cli}/src/config.d.ts +4 -15
- package/dist/{devtools/cli → cli}/src/config.js +7 -31
- package/dist/cli/src/default_paths.d.ts +3 -0
- package/dist/cli/src/default_paths.js +23 -0
- package/dist/{devtools/cli → cli}/src/embedded_paths.d.ts +1 -0
- package/dist/{devtools/cli → cli}/src/embedded_paths.js +18 -1
- package/dist/{devtools/cli → cli}/src/facade.d.ts +41 -235
- package/dist/{devtools/cli → cli}/src/facade.js +8 -27
- package/dist/cli/src/guide.js +47 -0
- package/dist/{devtools/cli → cli}/src/index.js +55 -141
- package/dist/{devtools/cli → cli}/src/session_manager.js +9 -11
- package/dist/{devtools/cli → cli}/src/token_command.js +69 -0
- package/dist/{devtools/cli → cli}/src/token_tool.d.ts +26 -0
- package/dist/{devtools/cli → cli}/src/token_tool.js +123 -22
- package/dist/{devtools/cli → cli}/src/transport.d.ts +1 -1
- package/package.json +6 -2
- package/script/ensure_ffmpeg.sh +1 -1
- package/vendor/app-server/bin/native/linux-x64/credential_napi.node +0 -0
- package/vendor/app-server/bin/native/macos-arm64/credential_napi.node +0 -0
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/credential.h +34 -0
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/error.h +13 -0
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/foundation/build_info.h +27 -0
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/http.h +57 -0
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/logging.h +3 -1
- package/vendor/app-server/bin/runtime/linux-x64/lib/libcrypto.a +0 -0
- package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_credential.a +0 -0
- package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_foundation_http.a +0 -0
- package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_foundation_logging.a +0 -0
- package/vendor/app-server/bin/runtime/linux-x64/lib/libssl.a +0 -0
- package/vendor/app-server/bin/runtime/linux-x64/manifest.txt +2 -32
- package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/audio.h +176 -133
- package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/av.h +223 -182
- package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/error.h +2 -0
- package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/media_downlink.h +6 -0
- package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/transport.h +58 -133
- package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/trp.h +47 -224
- package/vendor/app-server/bin/runtime/macos-arm64/lib/libTGTRP.a +0 -0
- package/vendor/app-server/bin/runtime/macos-arm64/lib/libTiRTC.a +0 -0
- package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_audio.a +0 -0
- package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_credential.a +0 -0
- package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_facade.a +0 -0
- package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_foundation_http.a +0 -0
- package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_foundation_logging.a +0 -0
- package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_media.a +0 -0
- package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_transport.a +0 -0
- package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_video.a +0 -0
- package/vendor/app-server/bin/runtime/macos-arm64/manifest.txt +19 -15
- package/vendor/app-server/dist/host/HostCommandCoordinator.d.ts +19 -0
- package/vendor/app-server/dist/host/HostCommandCoordinator.js +196 -0
- package/vendor/app-server/dist/host/HostProtocol.d.ts +1 -11
- package/vendor/app-server/dist/host/HostProtocol.js +3 -37
- package/vendor/app-server/dist/host/HostServer.d.ts +1 -4
- package/vendor/app-server/dist/host/HostServer.js +16 -152
- package/vendor/app-server/dist/host/RuntimeAdapter.js +2 -2
- package/vendor/app-server/dist/host/native/RuntimeCredentialTokenIssuer.js +3 -3
- package/vendor/app-server/dist/host/native/RuntimeHostBridge.js +4 -4
- package/vendor/app-server/dist/host/runtime_backed_preflight.js +2 -2
- package/vendor/app-server/dist/host/tests/helpers/runtime_e2e_local_config.js +1 -1
- package/vendor/app-server/dist/protocol/contract.d.ts +5 -64
- package/vendor/app-server/dist/protocol/contract.js +3 -12
- package/dist/devtools/cli/src/guide.js +0 -50
- package/dist/dummy.d.ts +0 -0
- package/dist/dummy.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -48
- package/vendor/app-server/bin/native/macos-arm64/libcrypto.dylib +0 -0
- package/vendor/app-server/bin/native/macos-arm64/libssl.dylib +0 -0
- package/vendor/app-server/bin/native/macos-arm64/runtime_host_napi.node +0 -0
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_codec.h +0 -23
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_frame.h +0 -36
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_io.h +0 -56
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_io_android.h +0 -19
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_io_apple.h +0 -19
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_io_harmony.h +0 -19
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_io_windows.h +0 -19
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_processing.h +0 -56
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_sample_rate.h +0 -18
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/media_codec.h +0 -21
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/media_downlink.h +0 -89
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/media_uplink.h +0 -115
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/runtime.h +0 -236
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_codec.h +0 -57
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_frame.h +0 -55
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_io.h +0 -46
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_io_android.h +0 -32
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_io_apple.h +0 -34
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_io_harmony.h +0 -32
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_io_windows.h +0 -26
- package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_processing.h +0 -34
- package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_audio.a +0 -0
- package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_facade.a +0 -0
- package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_media.a +0 -0
- package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_video.a +0 -0
- package/vendor/app-server/bin/runtime/linux-x64/lib/libwebrtc_apm.a +0 -0
- package/vendor/app-server/dist/host/RuntimeCredentialTokenIssuer.d.ts +0 -30
- package/vendor/app-server/dist/host/RuntimeCredentialTokenIssuer.js +0 -224
- /package/dist/{devtools/cli → cli}/src/dummy.d.ts +0 -0
- /package/dist/{devtools/cli → cli}/src/dummy.js +0 -0
- /package/dist/{devtools/cli → cli}/src/ffmpeg_tool.d.ts +0 -0
- /package/dist/{devtools/cli → cli}/src/ffmpeg_tool.js +0 -0
- /package/dist/{devtools/cli → cli}/src/guide.d.ts +0 -0
- /package/dist/{devtools/cli → cli}/src/index.d.ts +0 -0
- /package/dist/{devtools/cli → cli}/src/media_assets.d.ts +0 -0
- /package/dist/{devtools/cli → cli}/src/media_assets.js +0 -0
- /package/dist/{devtools/cli → cli}/src/progress.d.ts +0 -0
- /package/dist/{devtools/cli → cli}/src/progress.js +0 -0
- /package/dist/{devtools/cli → cli}/src/session_manager.d.ts +0 -0
- /package/dist/{devtools/cli → cli}/src/token_command.d.ts +0 -0
- /package/dist/{devtools/cli → cli}/src/transport.js +0 -0
- /package/vendor/app-server/bin/{native/macos-arm64 → runtime/macos-arm64/lib}/libtgrtc.dylib +0 -0
package/README.md
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
# TiRTC DevTools CLI
|
|
2
2
|
|
|
3
|
-
`
|
|
3
|
+
`products/cli/` 承接 `TiRTC DevTools CLI`。它是当前唯一用户界面的产品门面 (command client),为用户提供了一套操作 `Matrix Host` 控制面的终端工具。
|
|
4
4
|
|
|
5
5
|
## 使用说明 (C-Lite)
|
|
6
6
|
|
|
7
7
|
关于 `tirtc-devtools-cli` 命令的详细使用方法、参数说明与示例,请参考 [USAGE.md](./USAGE.md)。
|
|
8
8
|
|
|
9
|
-
如果要先快速确认当前 binary 暴露了哪些命令面,直接运行:`node
|
|
9
|
+
如果要先快速确认当前 binary 暴露了哪些命令面,直接运行:`node products/cli/bin/tirtc-devtools-cli.js --help`。
|
|
10
|
+
|
|
11
|
+
当前正式入口补充:
|
|
12
|
+
|
|
13
|
+
- server 侧最小入口:`service start`
|
|
14
|
+
- client 本地预览正式入口:`client start --token <token>` + `[client]` TOML
|
|
10
15
|
|
|
11
16
|
## 负责什么
|
|
12
17
|
|
|
@@ -15,6 +20,7 @@
|
|
|
15
20
|
- **产品级 Observability**:将底层的运行时事件和状态翻译为结构化输出 (JSON) 或友好的终端日志输出;对长耗时命令补轻量进度提示。
|
|
16
21
|
- **调试期工具内聚**:承接调试期必要工具(如 token bootstrap、二维码与媒体预处理)的产品化入口,避免把调试流程散落在 runtime 或外部手工步骤中。
|
|
17
22
|
- **本地 token 工具**:提供直接签发 token、打印组合 JSON、单独 token 与本地二维码 PNG 路径的公开 CLI 能力,服务本地联调与体验验证。
|
|
23
|
+
- **本地 license 二维码工具**:提供 server 扫码用的 license JSON 二维码生成能力,支持可选 `service_entry`。
|
|
18
24
|
|
|
19
25
|
## 不负责什么
|
|
20
26
|
|
|
@@ -24,7 +30,7 @@
|
|
|
24
30
|
|
|
25
31
|
## 依赖方向
|
|
26
32
|
|
|
27
|
-
- **依赖 `app-server/protocol-client/`**:通过可复用的第一方协议客户端与 `Matrix Host` 进程通信。
|
|
33
|
+
- **依赖 `products/app-server/protocol-client/`**:通过可复用的第一方协议客户端与 `Matrix Host` 进程通信。
|
|
28
34
|
- **绝不依赖 `runtime/` 代码实现**:CLI 不直接链接 runtime 模块,只消费 app-server 打包好的运行时产物与 Host 协议。
|
|
29
35
|
|
|
30
36
|
## 这里应该放什么
|
|
@@ -36,7 +42,7 @@
|
|
|
36
42
|
|
|
37
43
|
## 代码规范与 lint
|
|
38
44
|
|
|
39
|
-
- TypeScript 代码规范通过 `eslint` 承接,配置文件位于 `
|
|
45
|
+
- TypeScript 代码规范通过 `eslint` 承接,配置文件位于 `products/cli/.eslintrc.cjs`。
|
|
40
46
|
- 本目录作者侧收口命令:`npm run lint`、`npm test`、`npm run build`。
|
|
41
47
|
- 仓库级 gate 会通过 `./script/lint_node_products.sh` 在 `pre-commit` 与 `./script/check.sh` 中统一执行 Node 产品 lint。
|
|
42
48
|
|
|
@@ -44,18 +50,18 @@
|
|
|
44
50
|
|
|
45
51
|
- `npm run build`:执行 TypeScript 编译。
|
|
46
52
|
- `npm test`:运行 CLI 门面与 Smoke 测试。
|
|
47
|
-
- `npm run package`:执行 `./script/package.sh`,构建 CLI 本体并同步 npm 发布所需的 app-server/runtime vendor 资产。
|
|
53
|
+
- `npm run package`:执行 `./script/package.sh`,构建 CLI 本体并同步 npm 发布所需的 products/app-server/runtime vendor 资产。
|
|
48
54
|
- 运行 `media assets prepare` 时,CLI 会优先复用系统 `ffmpeg/ffprobe`;若本机不存在,则首次使用时自动下载到用户缓存目录。
|
|
49
55
|
|
|
50
56
|
## Runtime E2E Tester Config
|
|
51
57
|
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
58
|
+
- CLI server/client E2E 本地配置路径:`products/cli/config/.local/server.local.toml` + `products/cli/config/.local/client.local.toml`。
|
|
59
|
+
- `products/cli/config/.local/` 默认整体忽略;本地 gate 直接读取这两份 TOML,不再依赖 `tests/.local/*.json`。
|
|
60
|
+
- `server.local.toml` 负责 `service start` 和 `debug.connect_bootstrap` 真相;`client.local.toml` 负责 `client start` 与 `token issue` 所需的本地 truth。`license qrcode` 为纯命令行输入,不依赖 TOML。
|
|
55
61
|
|
|
56
62
|
## Command Loop E2E Harness
|
|
57
63
|
|
|
58
|
-
- 长驻人工验收脚本:`
|
|
59
|
-
- 示例配置:`
|
|
60
|
-
- 本地配置路径:`
|
|
64
|
+
- 长驻人工验收脚本:`products/cli/script/command_loop_e2e.sh`
|
|
65
|
+
- 示例配置:`products/cli/config/command_loop_e2e.example.toml`
|
|
66
|
+
- 本地配置路径:`products/cli/config/.local/command_loop_e2e.local.toml`(已在 `.gitignore` 忽略)
|
|
61
67
|
- 该脚本会先打包最新 `runtime + app-server + cli`,再清场、`service start`、周期性发送 `stream message` / time command,并轮询 `command pending list` 后自动做 CLI 侧显式 reply;启动成功后保持常驻,等待人工去操作 Android example。
|
package/USAGE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TiRTC DevTools CLI(用户手册)
|
|
2
2
|
|
|
3
|
-
`tirtc-devtools-cli` 是基于 `app-server/host` 的命令行门面,用来控制会话、服务、连接、流、命令通道与调试工具。
|
|
3
|
+
`tirtc-devtools-cli` 是基于 `products/app-server/host` 的命令行门面,用来控制会话、服务、连接、流、命令通道与调试工具。
|
|
4
4
|
|
|
5
5
|
## 一、关系
|
|
6
6
|
|
|
@@ -11,16 +11,16 @@
|
|
|
11
11
|
## 二、开发态构建
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npm --prefix app-server ci
|
|
15
|
-
npm --prefix
|
|
16
|
-
npm --prefix app-server run build
|
|
17
|
-
npm --prefix
|
|
14
|
+
npm --prefix products/app-server ci
|
|
15
|
+
npm --prefix products/cli ci
|
|
16
|
+
npm --prefix products/app-server run build
|
|
17
|
+
npm --prefix products/cli run build
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
运行入口:
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
node
|
|
23
|
+
node products/cli/bin/tirtc-devtools-cli.js --help
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## 三、Help 菜单速览
|
|
@@ -28,7 +28,7 @@ node devtools/cli/bin/tirtc-devtools-cli.js --help
|
|
|
28
28
|
安装或构建完成后,先用 help 菜单确认当前 binary 暴露的命令面:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
node
|
|
31
|
+
node products/cli/bin/tirtc-devtools-cli.js --help
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
当前顶层 help 快照:
|
|
@@ -41,7 +41,7 @@ TiRTC DevTools CLI
|
|
|
41
41
|
Options:
|
|
42
42
|
--config <path> 配置文件路径(TOML)
|
|
43
43
|
--json 以机器可读 JSON 输出(便于脚本集成)
|
|
44
|
-
--session <sessionId> 指定会话 ID;除 service start/connect 外必须传
|
|
44
|
+
--session <sessionId> 指定会话 ID;除 service start / client start / connection connect 外必须传
|
|
45
45
|
-h, --help display help for command
|
|
46
46
|
|
|
47
47
|
Commands:
|
|
@@ -49,8 +49,10 @@ Commands:
|
|
|
49
49
|
init 新手第一步:生成 CLI 配置模板
|
|
50
50
|
media 媒体素材辅助:prepare local assets
|
|
51
51
|
service 服务端能力:启动/停止服务,等待远端接入
|
|
52
|
+
client 客户端正式入口:连接远端并自动挂载本地 web preview
|
|
52
53
|
connection 客户端能力:主动连接远端 peer
|
|
53
54
|
token Token 工具:签发 token,并输出可直接使用的 JSON 与本地二维码 PNG
|
|
55
|
+
license License 工具:生成 server 扫码 JSON 与本地二维码 PNG
|
|
54
56
|
stream 流控制:发送/接收/消息
|
|
55
57
|
output 输出挂载:文件等消费者 attach/detach
|
|
56
58
|
command 命令通道:发送命令与事件跟踪
|
|
@@ -64,10 +66,10 @@ Commands:
|
|
|
64
66
|
常用子菜单 help:
|
|
65
67
|
|
|
66
68
|
```bash
|
|
67
|
-
node
|
|
68
|
-
node
|
|
69
|
-
node
|
|
70
|
-
node
|
|
69
|
+
node products/cli/bin/tirtc-devtools-cli.js service --help
|
|
70
|
+
node products/cli/bin/tirtc-devtools-cli.js stream --help
|
|
71
|
+
node products/cli/bin/tirtc-devtools-cli.js command --help
|
|
72
|
+
node products/cli/bin/tirtc-devtools-cli.js token issue --help
|
|
71
73
|
```
|
|
72
74
|
|
|
73
75
|
当前关键子菜单快照:
|
|
@@ -104,13 +106,19 @@ Options:
|
|
|
104
106
|
--channel-ttl-seconds <seconds>
|
|
105
107
|
--qr-error-correction-level <level>
|
|
106
108
|
--ascii-max-columns <columns>
|
|
109
|
+
|
|
110
|
+
$ node ... license qrcode --help
|
|
111
|
+
Options:
|
|
112
|
+
--service-entry <entry>
|
|
113
|
+
--qr-error-correction-level <level>
|
|
114
|
+
--ascii-max-columns <columns>
|
|
107
115
|
```
|
|
108
116
|
|
|
109
117
|
## 四、全局参数
|
|
110
118
|
|
|
111
119
|
- `--config <path>`:TOML 配置文件路径。
|
|
112
120
|
- `--json`:结构化 JSON 输出。
|
|
113
|
-
- `--session <sessionId>`:除 `service start` / `connection connect` 外,其余业务命令必须显式提供。
|
|
121
|
+
- `--session <sessionId>`:除 `service start` / `client start` / `connection connect` 外,其余业务命令必须显式提供。
|
|
114
122
|
|
|
115
123
|
## 五、会话模型
|
|
116
124
|
|
|
@@ -120,13 +128,13 @@ Options:
|
|
|
120
128
|
- `host session list`:查看会话。
|
|
121
129
|
- `host session stop <sessionId>`:停止会话。
|
|
122
130
|
- `service start`:默认创建 `service` 会话;可通过 `--session` 绑定已有空闲会话。
|
|
123
|
-
- `connection connect`:总是创建新的 `client` 会话,不允许复用 `--session`。
|
|
131
|
+
- `client start` / `connection connect`:总是创建新的 `client` 会话,不允许复用 `--session`。
|
|
124
132
|
|
|
125
133
|
## 六、server-only 正式入口
|
|
126
134
|
|
|
127
135
|
### 1. 配置真相
|
|
128
136
|
|
|
129
|
-
server-only 正式路径只认 `[server]
|
|
137
|
+
server-only 正式路径只认 `[server]`:
|
|
130
138
|
|
|
131
139
|
```toml
|
|
132
140
|
[server]
|
|
@@ -136,10 +144,6 @@ mp4_path = "/Users/allenfeng/Development/Repositories/tirtc-nexus/tirtc-matrix/.
|
|
|
136
144
|
video_stream_id = 11
|
|
137
145
|
audio_stream_id = 10
|
|
138
146
|
|
|
139
|
-
[logging]
|
|
140
|
-
root_dir = "./.tmp/tirtc-devtools-cli/logging"
|
|
141
|
-
console_mirror = true
|
|
142
|
-
level = "info"
|
|
143
147
|
```
|
|
144
148
|
|
|
145
149
|
说明:
|
|
@@ -147,11 +151,12 @@ level = "info"
|
|
|
147
151
|
- `license`、`mp4_path`、`video_stream_id`、`audio_stream_id` 必填。
|
|
148
152
|
- `service_entry` 可留空,回退到底层默认值。
|
|
149
153
|
- 旧 `[service]`、`[stream.request_policy]`、`[streams.send]` 不再属于正式合同。
|
|
154
|
+
- 正式命令默认开启 console mirror,并把日志固定落到 `~/.tirtc-devtools-cli/logging/`。
|
|
150
155
|
|
|
151
156
|
### 2. 启动命令
|
|
152
157
|
|
|
153
158
|
```bash
|
|
154
|
-
node
|
|
159
|
+
node products/cli/bin/tirtc-devtools-cli.js --config ./server.toml --json service start
|
|
155
160
|
```
|
|
156
161
|
|
|
157
162
|
`service start` 固定流程:
|
|
@@ -170,18 +175,49 @@ node devtools/cli/bin/tirtc-devtools-cli.js --config ./server.toml --json servic
|
|
|
170
175
|
- CLI 不再暴露 request-policy 配置或命令。
|
|
171
176
|
- 一旦远端请求对应 media,已绑定的发送流会自动转为 `active`。
|
|
172
177
|
|
|
173
|
-
## 七、
|
|
178
|
+
## 七、client start
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
node products/cli/bin/tirtc-devtools-cli.js --config ./client.toml --json client start --token <TOKEN>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
client 正式路径只认 `[client]`:
|
|
185
|
+
|
|
186
|
+
```toml
|
|
187
|
+
[client]
|
|
188
|
+
service_entry = ""
|
|
189
|
+
peer_id = "peer-123"
|
|
190
|
+
audio_stream_id = 10
|
|
191
|
+
video_stream_id = 11
|
|
192
|
+
consumer = "web_preview"
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
说明:
|
|
196
|
+
|
|
197
|
+
- `peer_id`、`audio_stream_id`、`video_stream_id`、`consumer` 必填。
|
|
198
|
+
- `consumer` 当前固定为 `web_preview`。
|
|
199
|
+
- token 必须通过命令行 `--token` 显式提供,不进入配置文件。
|
|
200
|
+
|
|
201
|
+
`client start` 固定流程:
|
|
202
|
+
|
|
203
|
+
1. 读取并校验 `[client]`。
|
|
204
|
+
2. 调用 `connection/connect`。
|
|
205
|
+
3. 自动调用两次 `stream/receiveStart`:一次音频、一次视频。
|
|
206
|
+
4. 自动调用两次 `output/attach`,consumer 固定为 `web_preview`。
|
|
207
|
+
5. 返回 `autoApplied` 摘要,其中 `preview.url` 是正式浏览器入口。
|
|
208
|
+
|
|
209
|
+
## 八、connection connect
|
|
174
210
|
|
|
175
211
|
```bash
|
|
176
|
-
node
|
|
212
|
+
node products/cli/bin/tirtc-devtools-cli.js --config ./client.toml --json connection connect <serviceEntry> <peerId> <token>
|
|
177
213
|
```
|
|
178
214
|
|
|
179
215
|
说明:
|
|
180
216
|
|
|
181
|
-
-
|
|
182
|
-
-
|
|
217
|
+
- 该命令保留为 expert/atomic 路径。
|
|
218
|
+
- token 必须显式提供;CLI 不再提供 auto token 回退。
|
|
183
219
|
|
|
184
|
-
##
|
|
220
|
+
## 九、stream / output / command
|
|
185
221
|
|
|
186
222
|
### Stream
|
|
187
223
|
|
|
@@ -214,18 +250,21 @@ CLI 仍会在本地收紧最小组合矩阵:
|
|
|
214
250
|
|
|
215
251
|
`command request` 是 canonical 主语,`command send` 只保留为兼容别名。若要发 JSON,请把 JSON 文本作为 `payload` 传入。`command pending list` 用于恢复或轮询当前积压,`command reply` 基于 `remoteRequestId` 显式回复待处理请求。
|
|
216
252
|
|
|
217
|
-
##
|
|
253
|
+
## 十、token / debug / report
|
|
218
254
|
|
|
219
255
|
- `token issue <peerId>`:本地签发 token。
|
|
256
|
+
- `license qrcode <license>`:本地生成 server 扫码二维码。
|
|
220
257
|
- `debug bootstrap qrcode ...` / `debug bootstrap qrcode-from-config`:生成联调用二维码。
|
|
221
258
|
- `events tail`:实时查看事件流。
|
|
222
259
|
- `logs export <outputPath>`:导出日志。
|
|
223
260
|
- `report show` / `report export <outputPath>`:查看或导出报告。
|
|
224
261
|
|
|
225
|
-
##
|
|
262
|
+
## 十一、本地 E2E 配置
|
|
226
263
|
|
|
227
|
-
- CLI server/client E2E 本地配置文件:`
|
|
228
|
-
-
|
|
264
|
+
- CLI server/client E2E 本地配置文件:`products/cli/config/.local/server.local.toml` + `products/cli/config/.local/client.local.toml`
|
|
265
|
+
- `products/cli/config/.local/` 默认整体忽略,由本地联调环境自行维护
|
|
266
|
+
- `server.local.toml` 字段:`[server]` + `[debug.connect_bootstrap]`
|
|
267
|
+
- `client.local.toml` 字段:`[client]` + `[debug.token_issue]`
|
|
229
268
|
- CLI server-only E2E 不再要求先手工 `media assets prepare` 再回填 `assetsDir`
|
|
230
269
|
|
|
231
270
|
## 十一、Android 人工闭环脚本
|
|
@@ -233,16 +272,16 @@ CLI 仍会在本地收紧最小组合矩阵:
|
|
|
233
272
|
如果需要把 CLI 侧闭环常驻起来,再手工去操作 Android example,使用:
|
|
234
273
|
|
|
235
274
|
```bash
|
|
236
|
-
./
|
|
275
|
+
./products/cli/script/command_loop_e2e.sh
|
|
237
276
|
```
|
|
238
277
|
|
|
239
|
-
默认读取:`
|
|
278
|
+
默认读取:`products/cli/config/.local/command_loop_e2e.local.toml`
|
|
240
279
|
|
|
241
280
|
建议先从模板复制:
|
|
242
281
|
|
|
243
282
|
```bash
|
|
244
|
-
mkdir -p
|
|
245
|
-
cp
|
|
283
|
+
mkdir -p products/cli/config/.local
|
|
284
|
+
cp products/cli/config/command_loop_e2e.example.toml products/cli/config/.local/command_loop_e2e.local.toml
|
|
246
285
|
```
|
|
247
286
|
|
|
248
287
|
该脚本会:
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
require('../dist/
|
|
2
|
+
require('../dist/cli/src/index.js');
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { AppServerClient } from '../../app-server/protocol-client';
|
|
2
|
+
import type { CliConfig } from './config';
|
|
3
|
+
import { ProgressIndicator } from './progress';
|
|
4
|
+
type ClientPreview = {
|
|
5
|
+
url: string;
|
|
6
|
+
token?: string;
|
|
7
|
+
endpoint?: string;
|
|
8
|
+
};
|
|
9
|
+
export type ServerBootstrapConfig = {
|
|
10
|
+
serviceEntry?: string;
|
|
11
|
+
license: string;
|
|
12
|
+
mp4Path: string;
|
|
13
|
+
audioStreamId: number;
|
|
14
|
+
videoStreamId: number;
|
|
15
|
+
};
|
|
16
|
+
export type ClientBootstrapConfig = {
|
|
17
|
+
serviceEntry?: string;
|
|
18
|
+
peerId: string;
|
|
19
|
+
audioStreamId: number;
|
|
20
|
+
videoStreamId: number;
|
|
21
|
+
consumer: 'web_preview';
|
|
22
|
+
};
|
|
23
|
+
export declare class BootstrapStepError extends Error {
|
|
24
|
+
readonly reasonCode: string;
|
|
25
|
+
readonly data: Record<string, unknown>;
|
|
26
|
+
constructor(reasonCode: string, message: string, data: Record<string, unknown>);
|
|
27
|
+
}
|
|
28
|
+
export declare function validateServerConfig(config: CliConfig): ServerBootstrapConfig;
|
|
29
|
+
export declare function validateClientConfig(config: CliConfig): ClientBootstrapConfig;
|
|
30
|
+
export declare function applyConfiguredServerBootstrap(client: AppServerClient, config: CliConfig, progress?: ProgressIndicator): Promise<{
|
|
31
|
+
preparedAssetsDir: string;
|
|
32
|
+
mediaSendPolicy: 'AUTO_ON_CONNECTED';
|
|
33
|
+
bootstrapSendStreams: Array<Record<string, unknown>>;
|
|
34
|
+
}>;
|
|
35
|
+
export declare function applyClientStartBootstrap(client: AppServerClient, config: CliConfig, token: string, progress?: ProgressIndicator): Promise<{
|
|
36
|
+
connection: unknown;
|
|
37
|
+
autoApplied: {
|
|
38
|
+
consumer: 'web_preview';
|
|
39
|
+
audioStream: unknown;
|
|
40
|
+
videoStream: unknown;
|
|
41
|
+
audioOutput: unknown;
|
|
42
|
+
videoOutput: unknown;
|
|
43
|
+
preview: ClientPreview;
|
|
44
|
+
};
|
|
45
|
+
}>;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.BootstrapStepError = void 0;
|
|
7
|
+
exports.validateServerConfig = validateServerConfig;
|
|
8
|
+
exports.validateClientConfig = validateClientConfig;
|
|
9
|
+
exports.applyConfiguredServerBootstrap = applyConfiguredServerBootstrap;
|
|
10
|
+
exports.applyClientStartBootstrap = applyClientStartBootstrap;
|
|
11
|
+
const fs_1 = __importDefault(require("fs"));
|
|
12
|
+
const os_1 = __importDefault(require("os"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const default_paths_1 = require("./default_paths");
|
|
15
|
+
const media_assets_1 = require("./media_assets");
|
|
16
|
+
class BootstrapStepError extends Error {
|
|
17
|
+
reasonCode;
|
|
18
|
+
data;
|
|
19
|
+
constructor(reasonCode, message, data) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = 'BootstrapStepError';
|
|
22
|
+
this.reasonCode = reasonCode;
|
|
23
|
+
this.data = data;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.BootstrapStepError = BootstrapStepError;
|
|
27
|
+
function resolveProtocolError(error) {
|
|
28
|
+
if (typeof error === 'object' && error !== null) {
|
|
29
|
+
const typed = error;
|
|
30
|
+
if (typed.data?.reasonCode && typed.data.reasonCode.trim().length > 0) {
|
|
31
|
+
return {
|
|
32
|
+
reasonCode: typed.data.reasonCode,
|
|
33
|
+
message: typed.data.message ?? typed.message ?? 'Request failed',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
if (typed.message && typed.message.trim().length > 0) {
|
|
37
|
+
return {
|
|
38
|
+
reasonCode: 'internal_error',
|
|
39
|
+
message: typed.message,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (error instanceof Error) {
|
|
44
|
+
return {
|
|
45
|
+
reasonCode: 'internal_error',
|
|
46
|
+
message: error.message,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
reasonCode: 'internal_error',
|
|
51
|
+
message: 'Request failed',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function ensureNonNegativeInteger(value, field) {
|
|
55
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {
|
|
56
|
+
throw new Error(field + ' must be a non-negative integer');
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
function ensureNonEmptyString(value, field) {
|
|
61
|
+
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
62
|
+
throw new Error(field + ' must be a non-empty string');
|
|
63
|
+
}
|
|
64
|
+
return value.trim();
|
|
65
|
+
}
|
|
66
|
+
function extractPreview(result, step) {
|
|
67
|
+
if (typeof result !== 'object' || result === null) {
|
|
68
|
+
throw new Error(step + ' did not return an object result');
|
|
69
|
+
}
|
|
70
|
+
const previewRaw = result.preview;
|
|
71
|
+
if (typeof previewRaw !== 'object' || previewRaw === null) {
|
|
72
|
+
throw new Error(step + ' did not return preview metadata');
|
|
73
|
+
}
|
|
74
|
+
const preview = previewRaw;
|
|
75
|
+
const url = ensureNonEmptyString(preview.url, step + ' preview.url');
|
|
76
|
+
return {
|
|
77
|
+
url,
|
|
78
|
+
token: typeof preview.token === 'string' && preview.token.trim().length > 0 ? preview.token.trim() : undefined,
|
|
79
|
+
endpoint: typeof preview.endpoint === 'string' && preview.endpoint.trim().length > 0 ? preview.endpoint.trim() : undefined,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async function runBootstrapStep(client, method, params, step, completed) {
|
|
83
|
+
try {
|
|
84
|
+
return await client.sendRequest(method, params);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
const resolved = resolveProtocolError(error);
|
|
88
|
+
throw new BootstrapStepError(resolved.reasonCode, resolved.message, {
|
|
89
|
+
failedStep: step,
|
|
90
|
+
completedSteps: completed,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function validateServerConfig(config) {
|
|
95
|
+
const server = config.server;
|
|
96
|
+
const license = server?.license?.trim() ?? '';
|
|
97
|
+
const mp4Path = server?.mp4_path?.trim() ?? '';
|
|
98
|
+
const audioStreamId = ensureNonNegativeInteger(server?.audio_stream_id, '[server].audio_stream_id');
|
|
99
|
+
const videoStreamId = ensureNonNegativeInteger(server?.video_stream_id, '[server].video_stream_id');
|
|
100
|
+
if (license.length === 0) {
|
|
101
|
+
throw new Error('server-only config requires [server].license');
|
|
102
|
+
}
|
|
103
|
+
if (mp4Path.length === 0) {
|
|
104
|
+
throw new Error('server-only config requires [server].mp4_path');
|
|
105
|
+
}
|
|
106
|
+
if (audioStreamId === videoStreamId) {
|
|
107
|
+
throw new Error('server-only config requires distinct audio_stream_id and video_stream_id');
|
|
108
|
+
}
|
|
109
|
+
const resolvedMp4Path = path_1.default.resolve(mp4Path);
|
|
110
|
+
let stats;
|
|
111
|
+
try {
|
|
112
|
+
stats = fs_1.default.statSync(resolvedMp4Path);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
throw new Error('server-only config mp4_path does not exist: ' + resolvedMp4Path);
|
|
116
|
+
}
|
|
117
|
+
if (!stats.isFile()) {
|
|
118
|
+
throw new Error('server-only config mp4_path must be a readable file: ' + resolvedMp4Path);
|
|
119
|
+
}
|
|
120
|
+
const serviceEntry = server?.service_entry?.trim();
|
|
121
|
+
return {
|
|
122
|
+
serviceEntry: serviceEntry && serviceEntry.length > 0 ? serviceEntry : undefined,
|
|
123
|
+
license,
|
|
124
|
+
mp4Path: resolvedMp4Path,
|
|
125
|
+
audioStreamId,
|
|
126
|
+
videoStreamId,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function validateClientConfig(config) {
|
|
130
|
+
const client = config.client;
|
|
131
|
+
if (!client) {
|
|
132
|
+
throw new Error('client start requires [client] config');
|
|
133
|
+
}
|
|
134
|
+
const peerId = ensureNonEmptyString(client.peer_id, '[client].peer_id');
|
|
135
|
+
const audioStreamId = ensureNonNegativeInteger(client.audio_stream_id, '[client].audio_stream_id');
|
|
136
|
+
const videoStreamId = ensureNonNegativeInteger(client.video_stream_id, '[client].video_stream_id');
|
|
137
|
+
if (audioStreamId === videoStreamId) {
|
|
138
|
+
throw new Error('client config requires distinct audio_stream_id and video_stream_id');
|
|
139
|
+
}
|
|
140
|
+
if (client.consumer !== 'web_preview') {
|
|
141
|
+
throw new Error('client config requires [client].consumer = "web_preview"');
|
|
142
|
+
}
|
|
143
|
+
const serviceEntry = client.service_entry?.trim();
|
|
144
|
+
return {
|
|
145
|
+
serviceEntry: serviceEntry && serviceEntry.length > 0 ? serviceEntry : undefined,
|
|
146
|
+
peerId,
|
|
147
|
+
audioStreamId,
|
|
148
|
+
videoStreamId,
|
|
149
|
+
consumer: 'web_preview',
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
async function applyConfiguredServerBootstrap(client, config, progress) {
|
|
153
|
+
const server = validateServerConfig(config);
|
|
154
|
+
progress?.start('Preparing MP4 assets');
|
|
155
|
+
const prepared = await (0, media_assets_1.prepareMediaAssets)({
|
|
156
|
+
source: server.mp4Path,
|
|
157
|
+
outputRoot: (0, default_paths_1.resolveCliPreparedAssetsRoot)(),
|
|
158
|
+
});
|
|
159
|
+
progress?.update('Prepared MP4 assets');
|
|
160
|
+
const bootstrapSendStreams = [
|
|
161
|
+
{ streamId: server.audioStreamId, media: 'audio' },
|
|
162
|
+
{ streamId: server.videoStreamId, media: 'video' },
|
|
163
|
+
].map(({ streamId, media }) => ({
|
|
164
|
+
streamId,
|
|
165
|
+
media,
|
|
166
|
+
source: {
|
|
167
|
+
mode: 'local_assets',
|
|
168
|
+
local_assets: {
|
|
169
|
+
assets_dir: prepared.assets_dir,
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
}));
|
|
173
|
+
return {
|
|
174
|
+
preparedAssetsDir: prepared.assets_dir,
|
|
175
|
+
mediaSendPolicy: 'AUTO_ON_CONNECTED',
|
|
176
|
+
bootstrapSendStreams,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
async function applyClientStartBootstrap(client, config, token, progress) {
|
|
180
|
+
const normalizedToken = ensureNonEmptyString(token, '--token');
|
|
181
|
+
const clientConfig = validateClientConfig(config);
|
|
182
|
+
const audioArtifactPath = path_1.default.join(os_1.default.tmpdir(), `tirtc-client-preview-audio-${Date.now()}-${process.pid}.pcm`);
|
|
183
|
+
const videoArtifactPath = path_1.default.join(os_1.default.tmpdir(), `tirtc-client-preview-video-${Date.now()}-${process.pid}.jpeg`);
|
|
184
|
+
const completed = {
|
|
185
|
+
consumer: clientConfig.consumer,
|
|
186
|
+
};
|
|
187
|
+
progress?.start('Connecting client session');
|
|
188
|
+
const connection = await runBootstrapStep(client, 'connection/connect', {
|
|
189
|
+
serviceEntry: clientConfig.serviceEntry,
|
|
190
|
+
peerId: clientConfig.peerId,
|
|
191
|
+
token: normalizedToken,
|
|
192
|
+
timeoutMs: 5000,
|
|
193
|
+
}, 'connect', completed);
|
|
194
|
+
completed.connection = connection;
|
|
195
|
+
progress?.update('Connected client session');
|
|
196
|
+
const audioStream = await runBootstrapStep(client, 'stream/receiveStart', {
|
|
197
|
+
streamId: clientConfig.audioStreamId,
|
|
198
|
+
media: 'audio',
|
|
199
|
+
}, 'receive audio', completed);
|
|
200
|
+
completed.audioStream = audioStream;
|
|
201
|
+
progress?.update('Attached audio receive stream');
|
|
202
|
+
const videoStream = await runBootstrapStep(client, 'stream/receiveStart', {
|
|
203
|
+
streamId: clientConfig.videoStreamId,
|
|
204
|
+
media: 'video',
|
|
205
|
+
}, 'receive video', completed);
|
|
206
|
+
completed.videoStream = videoStream;
|
|
207
|
+
progress?.update('Attached video receive stream');
|
|
208
|
+
const audioOutput = await runBootstrapStep(client, 'output/attach', {
|
|
209
|
+
streamId: clientConfig.audioStreamId,
|
|
210
|
+
consumer: clientConfig.consumer,
|
|
211
|
+
mediaView: 'encoded_packet',
|
|
212
|
+
format: 'pcm',
|
|
213
|
+
delivery: 'artifact_path',
|
|
214
|
+
targetPath: audioArtifactPath,
|
|
215
|
+
}, 'attach audio preview', completed);
|
|
216
|
+
completed.audioOutput = audioOutput;
|
|
217
|
+
progress?.update('Attached audio preview output');
|
|
218
|
+
const videoOutput = await runBootstrapStep(client, 'output/attach', {
|
|
219
|
+
streamId: clientConfig.videoStreamId,
|
|
220
|
+
consumer: clientConfig.consumer,
|
|
221
|
+
mediaView: 'encoded_packet',
|
|
222
|
+
format: 'jpeg',
|
|
223
|
+
delivery: 'artifact_path',
|
|
224
|
+
targetPath: videoArtifactPath,
|
|
225
|
+
}, 'attach video preview', completed);
|
|
226
|
+
completed.videoOutput = videoOutput;
|
|
227
|
+
progress?.succeed('Client preview session is ready');
|
|
228
|
+
const audioPreview = extractPreview(audioOutput, 'attach audio preview');
|
|
229
|
+
const videoPreview = extractPreview(videoOutput, 'attach video preview');
|
|
230
|
+
if (audioPreview.url !== videoPreview.url) {
|
|
231
|
+
throw new BootstrapStepError('internal_error', 'web_preview outputs returned different preview URLs', {
|
|
232
|
+
failedStep: 'preview aggregation',
|
|
233
|
+
completedSteps: completed,
|
|
234
|
+
audioPreview,
|
|
235
|
+
videoPreview,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
connection,
|
|
240
|
+
autoApplied: {
|
|
241
|
+
consumer: clientConfig.consumer,
|
|
242
|
+
audioStream,
|
|
243
|
+
videoStream,
|
|
244
|
+
audioOutput,
|
|
245
|
+
videoOutput,
|
|
246
|
+
preview: audioPreview,
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
}
|
|
@@ -6,23 +6,12 @@ export type CliConfig = {
|
|
|
6
6
|
video_stream_id?: number;
|
|
7
7
|
audio_stream_id?: number;
|
|
8
8
|
};
|
|
9
|
-
|
|
9
|
+
client?: {
|
|
10
10
|
service_entry?: string;
|
|
11
11
|
peer_id?: string;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
access_id?: string;
|
|
16
|
-
secret_key?: string;
|
|
17
|
-
local_id?: string;
|
|
18
|
-
user_ttl_seconds?: number;
|
|
19
|
-
channel_ttl_seconds?: number;
|
|
20
|
-
};
|
|
21
|
-
};
|
|
22
|
-
logging?: {
|
|
23
|
-
root_dir?: string;
|
|
24
|
-
console_mirror?: boolean;
|
|
25
|
-
level?: 'verbose' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
|
12
|
+
audio_stream_id?: number;
|
|
13
|
+
video_stream_id?: number;
|
|
14
|
+
consumer?: 'web_preview';
|
|
26
15
|
};
|
|
27
16
|
debug?: {
|
|
28
17
|
connect_bootstrap?: {
|