@tencent-rtc/mcp 1.7.2 → 1.7.4

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 (49) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +25 -17
  3. package/knowledge/bm25.js +20 -11
  4. package/knowledge/path-meta.js +23 -1
  5. package/knowledge/search/generic-rerank.js +123 -0
  6. package/knowledge/search/search-pass.js +8 -1
  7. package/package.json +1 -1
  8. package/resource/index/manifest.json +1 -1
  9. package/resource/knowledge/callkit/best-practice/android/video-chat-dating.md +497 -0
  10. package/resource/knowledge/callkit/best-practice/flutter/android-keep-call-alive-background.md +79 -0
  11. package/resource/knowledge/callkit/best-practice/flutter/background-incoming-call-no-notification.md +99 -0
  12. package/resource/knowledge/callkit/best-practice/flutter/ios-keep-call-alive-background.md +93 -0
  13. package/resource/knowledge/callkit/best-practice/flutter/ios-startup-crash-version-voip.md +68 -0
  14. package/resource/knowledge/callkit/core-sdk/miniprogram/call-engine.md +386 -0
  15. package/resource/knowledge/callkit/core-sdk/miniprogram/call-event.md +315 -0
  16. package/resource/knowledge/callkit/faq/uniapp-miniprogram.md +204 -0
  17. package/resource/knowledge/callkit/preset/harmonyos/api.md +362 -0
  18. package/resource/knowledge/callkit/preset/harmonyos/integration.md +318 -0
  19. package/resource/knowledge/callkit/preset/miniprogram/api-uniapp.md +430 -0
  20. package/resource/knowledge/callkit/preset/miniprogram/api.md +293 -0
  21. package/resource/knowledge/callkit/preset/miniprogram/integration.md +294 -0
  22. package/resource/knowledge/callkit/preset/miniprogram/uniapp-integration.md +224 -0
  23. package/resource/knowledge/callkit/preset/uni-app/api.md +339 -0
  24. package/resource/knowledge/callkit/preset/uni-app/integration.md +243 -0
  25. package/resource/knowledge/chat/best-practice/common/web-sdk-log-level.md +76 -0
  26. package/resource/knowledge/chat/best-practice/miniprogram/desktop-wechat-miniprogram-error.md +79 -0
  27. package/resource/knowledge/chat/preset/react/h5/integration.md +964 -0
  28. package/resource/knowledge/chat/preset/vue/h5/integration.md +717 -0
  29. package/resource/knowledge/roomkit/best-practice/vue/screen-share-auto-stop-on-leave.md +62 -0
  30. package/resource/knowledge/roomkit/core-sdk/react/network-proxy.md +83 -0
  31. package/resource/knowledge/roomkit/core-sdk/vue/network-proxy.md +83 -0
  32. package/resource/knowledge/roomkit/core-sdk/vue/recording.md +245 -0
  33. package/resource/knowledge/roomkit/core-sdk/vue/whiteboard-annotation.md +196 -0
  34. package/resource/knowledge/roomkit/faq/error-code.md +103 -0
  35. package/resource/knowledge/roomkit/preset/harmonyos/integration.md +461 -0
  36. package/resource/knowledge/roomkit/preset/react/features/network-proxy.md +79 -0
  37. package/resource/knowledge/roomkit/preset/uniapp-app/integration.md +580 -0
  38. package/resource/knowledge/roomkit/preset/vue/features/ai-caption-translation.md +69 -0
  39. package/resource/knowledge/roomkit/preset/vue/features/ai-denoiser.md +67 -0
  40. package/resource/knowledge/roomkit/preset/vue/features/network-proxy.md +79 -0
  41. package/resource/knowledge/roomkit/preset/vue/features/recording.md +85 -0
  42. package/resource/knowledge/roomkit/preset/vue/features/whiteboard-annotation.md +86 -0
  43. package/resource/knowledge/rtcengine/web/plugin/23-advanced-support-detection.md +6 -6
  44. package/resource/knowledge/rtcengine/web/plugin/31-advanced-plugins-overview.md +8 -6
  45. package/resource/knowledge/rtcengine/web/plugin/42-advanced-realtime-transcriber.md +30 -10
  46. package/server.js +1 -1
  47. package/utils/preflight-route.js +18 -6
  48. package/utils/report-cls-client.js +1 -1
  49. package/utils/report-es-client.js +1 -1
@@ -0,0 +1,62 @@
1
+ ---
2
+ title: Whether Screen Sharing Stops Automatically When Leaving the Room/Ending the Meeting in TUIRoomKit Vue3
3
+ product: room
4
+ frameworks: [vue, web]
5
+ scope: platform_specific
6
+ tags: [TUIRoomKit, screen share, stopScreenShare, startScreenShare, leaveRoom, endRoom, leave room, end meeting, close browser, useDeviceState, useRoomState, screenStatus, vue3, Atomicx]
7
+ version_range: ">=2.0.0"
8
+ ---
9
+
10
+ # Whether Screen Sharing Stops Automatically When Leaving the Room/Ending the Meeting in TUIRoomKit Vue3
11
+
12
+ ## 1. Key Conclusions
13
+
14
+ - Leaving the room (`leaveRoom`), ending the meeting (`endRoom`), and exit actions such as closing the browser or closing the web page all automatically end the current screen share. The business side does not need to manually call `stopScreenShare` again.
15
+ - Screen sharing is part of the room session: leaving the room releases the user's sharing channel, and screen sharing stops accordingly.
16
+ - No extra cleanup code is needed to "stop screen sharing when leaving the room." You only need to explicitly call `stopScreenShare` when **actively stopping** screen sharing during the meeting (without leaving the room).
17
+ - This behavior is consistent between UI-less integration (`tuikit-atomicx-vue3`) and integration with UI (`@tencentcloud/roomkit-web-vue3`).
18
+
19
+ ## 2. Field/Capability Reference
20
+
21
+ | Field/Capability | Purpose | Notes |
22
+ |---|---|---|
23
+ | `startScreenShare` | Starts screen sharing | Provided by `useDeviceState()`; once started, the share is visible to other room members |
24
+ | `stopScreenShare` | Stops screen sharing | Only needs to be called explicitly when **actively stopping during the meeting without leaving the room** |
25
+ | `screenStatus` | Screen share status | Provided by `useDeviceState()`; `DeviceStatus.On` indicates sharing is active |
26
+ | `leaveRoom` | Leave the room | A member exits the room; the member's screen share ends automatically |
27
+ | `endRoom` | End the meeting | The host dismisses the room; screen sharing ends automatically |
28
+ | Close browser/web page | Abnormal/normal exit | Disconnects the room session; screen sharing ends accordingly |
29
+
30
+ ## 3. Mechanism/Sequence
31
+
32
+ The user starts screen sharing during the meeting (`startScreenShare`, `screenStatus = On`) -> an exit action is triggered (`leaveRoom` / `endRoom` / closing the browser or web page) -> the room session disconnects and the user's sharing channel is released -> screen sharing stops automatically, and other room members no longer see the shared content.
33
+
34
+ ## 4. Standard Usage
35
+
36
+ 1. Start screen sharing during the meeting: call `startScreenShare` from `useDeviceState()`.
37
+ 2. To stop sharing **without leaving the room**: explicitly call `stopScreenShare`.
38
+ 3. When the user leaves the room: just call `leaveRoom` (or the host calls `endRoom`); screen sharing ends automatically, and there is no need to call `stopScreenShare` first.
39
+ 4. Exit scenarios such as closing the browser / closing the web page: no extra handling is needed; screen sharing ends automatically as the room session disconnects.
40
+
41
+ ## 5. Result Verification
42
+
43
+ - After calling `leaveRoom` / `endRoom`, the user's screen share stops and the shared content disappears for other room members.
44
+ - After closing the browser or web page, other room members no longer receive the user's screen-sharing stream.
45
+ - When staying in the room and calling only `stopScreenShare`, screen sharing stops while the user remains in the room.
46
+
47
+ ## 6. Common Pitfalls
48
+
49
+ - Pitfall 1: Assuming you must manually call `stopScreenShare` before leaving, otherwise the screen share lingers (leaving the room ends the share automatically).
50
+ - Pitfall 2: Assuming screen sharing continues after closing the browser/web page (the share ends once the room session disconnects).
51
+ - Pitfall 3: Conflating the responsibilities of `leaveRoom`/`endRoom` with `stopScreenShare` (the former leaves the room and cleans up automatically; the latter only stops sharing without leaving the room).
52
+
53
+ ## 7. Problem Definition (Retrieval Aid, Minimal)
54
+
55
+ In TUIRoomKit Vue3, whether screen sharing stops automatically when the user calls `leaveRoom`/`endRoom` or closes the browser/web page.
56
+
57
+ ## 8. Synonymous Phrasing Coverage (Retrieval Recall, Minimal)
58
+
59
+ - Does `leaveRoom` / `endRoom` automatically `stopScreenShare`?
60
+ - Does screen sharing continue after leaving the room?
61
+ - Does screen sharing end automatically after closing the browser/web page?
62
+ - Do I need to manually stop screen sharing before leaving the room?
@@ -0,0 +1,83 @@
1
+ The Conference SDK is built on Tencent Cloud Chat (IM) and Tencent Real-Time Communication (TRTC). It supports configuring the IM and TRTC proxies together in intranet / firewall environments, which is suitable for scenarios such as private deployment and enterprise intranet isolation where a direct connection to Tencent Cloud services is not available.
2
+
3
+ ## Proxy architecture
4
+
5
+ |Proxy server|Proxy link|
6
+ |---------|---------|
7
+ |IM proxy|Proxies the signaling channels for IM login, message sending/receiving, etc. (WebSocket), as well as the upload and download of resources such as chat images and files.|
8
+ |TRTC WebSocket proxy (e.g. Nginx)|Proxies the signaling channels for TRTC room entry, control, etc. (WebSocket), and is responsible for room management and user state synchronization.|
9
+ |TRTC TURN Server|Relays TRTC audio and video media streams.|
10
+
11
+ > **Note:**
12
+ > The proxy servers (IM proxy, Nginx, TURN) need to be deployed by yourself. For how to set them up, see [TRTC Web SDK handling firewall restrictions](https://web.sdk.qcloud.com/trtc/webrtc/v5/doc/zh-cn/tutorial-34-advanced-proxy.html).
13
+ >
14
+
15
+ ## API and parameters
16
+
17
+ The Conference SDK allows you to configure the intranet proxy uniformly through the `callExperimentalAPI` interface before calling `login()`:
18
+ ``` typescript
19
+ callExperimentalAPI({
20
+ api: 'setNetworkProxy',
21
+ params: {
22
+ im?: { /* IM proxy parameters */ },
23
+ rtc?: { /* TRTC proxy parameters */ },
24
+ },
25
+ });
26
+ ```
27
+
28
+ ### IM proxy parameters
29
+
30
+ |Parameter|Type|Description|
31
+ |---------|---------|---------|
32
+ |`proxyServer`|String|IM signaling WebSocket proxy address.|
33
+ |`fileUploadProxy`|String|IM file upload proxy address.|
34
+ |`fileDownloadProxy`|String|IM file download proxy address.|
35
+
36
+ ### TRTC proxy parameters
37
+
38
+ |Parameter|Type|Description|
39
+ |---------|---------|---------|
40
+ |`websocketProxy`|String|TRTC signaling WebSocket proxy address, e.g. `wss://proxy.example.com/ws/`.|
41
+ |`turnServer`|Array|List of TURN servers. Each item contains `url` / `username` / `credential`.|
42
+ |`iceTransportPolicy`|`'relay' \| 'all'`|Client-side ICE transport policy. In an intranet environment, it is recommended to set it to `'relay'` to force a connection to the TURN server.|
43
+
44
+ ## Sample code
45
+
46
+ ``` typescript
47
+ import { callExperimentalAPI } from 'tuikit-atomicx-react';
48
+ import { useLoginState, useRoomState } from 'tuikit-atomicx-react/room';
49
+
50
+ callExperimentalAPI({
51
+ api: 'setNetworkProxy',
52
+ params: {
53
+ im: {
54
+ proxyServer: 'wss://proxy.example.com:8080',
55
+ fileUploadProxy: 'https://proxy.example.com:8080',
56
+ fileDownloadProxy: 'https://proxy.example.com:8080',
57
+ },
58
+ rtc: {
59
+ websocketProxy: 'wss://proxy.example.com/ws/',
60
+ turnServer: [
61
+ { url: '14.3.3.3:3478', username: 'turn', credential: 'turn' },
62
+ ],
63
+ iceTransportPolicy: 'relay',
64
+ },
65
+ },
66
+ });
67
+
68
+ const { login } = useLoginState();
69
+ await login({ sdkAppId, userId, userSig });
70
+
71
+ const { createAndJoinRoom } = useRoomState();
72
+ await createAndJoinRoom({ roomId });
73
+ ```
74
+
75
+ ## FAQs
76
+
77
+ ### A user can join the conference normally on the public network, but cannot join it on the intranet?
78
+
79
+ Check whether `setNetworkProxy` was called before `login()`. If it is already configured but still fails, check the TURN port and the outbound allowlist of the proxy server.
80
+
81
+ ### A user can join the conference but cannot see the remote video or hear the remote audio?
82
+
83
+ Confirm that `turnServer` is reachable, and set `iceTransportPolicy` to `'relay'` in an intranet environment.
@@ -0,0 +1,83 @@
1
+ The Conference SDK is built on Tencent Cloud Chat (IM) and Tencent Real-Time Communication (TRTC). It supports configuring the IM and TRTC proxies together in intranet / firewall environments, which is suitable for scenarios such as private deployment and enterprise intranet isolation where a direct connection to Tencent Cloud services is not available.
2
+
3
+ ## Proxy architecture
4
+
5
+ |Proxy server|Proxy link|
6
+ |---------|---------|
7
+ |IM proxy|Proxies the signaling channels for IM login, message sending/receiving, etc. (WebSocket), as well as the upload and download of resources such as chat images and files.|
8
+ |TRTC WebSocket proxy (e.g. Nginx)|Proxies the signaling channels for TRTC room entry, control, etc. (WebSocket), and is responsible for room management and user state synchronization.|
9
+ |TRTC TURN Server|Relays TRTC audio and video media streams.|
10
+
11
+ > **Note:**
12
+ > The proxy servers (IM proxy, Nginx, TURN) need to be deployed by yourself. For how to set them up, see [TRTC Web SDK handling firewall restrictions](https://web.sdk.qcloud.com/trtc/webrtc/v5/doc/zh-cn/tutorial-34-advanced-proxy.html).
13
+ >
14
+
15
+ ## API and parameters
16
+
17
+ The Conference SDK allows you to configure the intranet proxy uniformly through the `callExperimentalAPI` interface before calling `login()`:
18
+ ``` typescript
19
+ callExperimentalAPI({
20
+ api: 'setNetworkProxy',
21
+ params: {
22
+ im?: { /* IM proxy parameters */ },
23
+ rtc?: { /* TRTC proxy parameters */ },
24
+ },
25
+ });
26
+ ```
27
+
28
+ ### IM proxy parameters
29
+
30
+ |Parameter|Type|Description|
31
+ |---------|---------|---------|
32
+ |`proxyServer`|String|IM signaling WebSocket proxy address.|
33
+ |`fileUploadProxy`|String|IM file upload proxy address.|
34
+ |`fileDownloadProxy`|String|IM file download proxy address.|
35
+
36
+ ### TRTC proxy parameters
37
+
38
+ |Parameter|Type|Description|
39
+ |---------|---------|---------|
40
+ |`websocketProxy`|String|TRTC signaling WebSocket proxy address, e.g. `wss://proxy.example.com/ws/`.|
41
+ |`turnServer`|Array|List of TURN servers. Each item contains `url` / `username` / `credential`.|
42
+ |`iceTransportPolicy`|`'relay' \| 'all'`|Client-side ICE transport policy. In an intranet environment, it is recommended to set it to `'relay'` to force a connection to the TURN server.|
43
+
44
+ ## Sample code
45
+
46
+ ``` typescript
47
+ import { callExperimentalAPI } from 'tuikit-atomicx-vue3';
48
+ import { useLoginState, useRoomState } from 'tuikit-atomicx-vue3/room';
49
+
50
+ callExperimentalAPI({
51
+ api: 'setNetworkProxy',
52
+ params: {
53
+ im: {
54
+ proxyServer: 'wss://proxy.example.com:8080',
55
+ fileUploadProxy: 'https://proxy.example.com:8080',
56
+ fileDownloadProxy: 'https://proxy.example.com:8080',
57
+ },
58
+ rtc: {
59
+ websocketProxy: 'wss://proxy.example.com/ws/',
60
+ turnServer: [
61
+ { url: '14.3.3.3:3478', username: 'turn', credential: 'turn' },
62
+ ],
63
+ iceTransportPolicy: 'relay',
64
+ },
65
+ },
66
+ });
67
+
68
+ const { login } = useLoginState();
69
+ await login({ sdkAppId, userId, userSig });
70
+
71
+ const { createAndJoinRoom } = useRoomState();
72
+ await createAndJoinRoom({ roomId });
73
+ ```
74
+
75
+ ## FAQs
76
+
77
+ ### A user can join the conference normally on the public network, but cannot join it on the intranet?
78
+
79
+ Check whether `setNetworkProxy` was called before `login()`. If it is already configured but still fails, check the TURN port and the outbound allowlist of the proxy server.
80
+
81
+ ### A user can join the conference but cannot see the remote video or hear the remote audio?
82
+
83
+ Confirm that `turnServer` is reachable, and set `iceTransportPolicy` to `'relay'` in an intranet environment.
@@ -0,0 +1,245 @@
1
+ This document guides developers in implementing cloud recording in the no-UI integration solution for standard meetings. You can control the start and stop of recording through `startRecording()` / `stopRecording()` provided by `useRoomState()`, and monitor recording state changes in real time through `currentRoom.recordingInfo` and `RoomEvent`.
2
+
3
+ > **Version note:**
4
+ >
5
+ > The cloud recording interfaces (`startRecording` / `stopRecording`) are supported since **tuikit-atomicx-vue3 6.4.0** and **tuikit-atomicx-react 6.2.0**. Make sure the version you use meets the requirement.
6
+ >
7
+
8
+ ## Prerequisites
9
+ - The user has completed login authentication through `useLoginState`.
10
+
11
+ - The user has entered a standard meeting room through `useRoomState`.
12
+
13
+ - Cloud recording package activation and storage configuration have been completed:
14
+
15
+ - Purchase a Conference SDK package that includes cloud recording capability.
16
+
17
+ - Enable the recording file storage service: Recording files can be stored in [Cloud VOD (VOD)](https://console.cloud.tencent.com/vod) or [Cloud Object Storage (COS)](https://console.cloud.tencent.com/cos). Complete the activation in the corresponding console and record the storage information.
18
+
19
+ - [Submit a ticket](https://console.cloud.tencent.com/workorder/category), select the **Real-Time Communication** product, and apply to configure the cloud recording storage information for your SDKAppID.
20
+
21
+ ## Recording effect
22
+
23
+ The Conference SDK uses **mixed-stream recording** mode by default, mixing the audio and video streams published in the room into one complete recording file. The recording layout **switches automatically** with the in-meeting state, and the recording task is not restarted during the switch:
24
+
25
+ |**In-meeting state**|**Mixed-stream layout**|**Maximum number of views**|
26
+ |---------|---------|---------|
27
+ |No screen sharing / whiteboard|Grid layout|Up to **25** video views|
28
+ |With screen sharing / whiteboard|Screen sharing layout (sharing as the main view)|Up to **1** screen sharing + **16** video views|
29
+ |Audio only|-|—|
30
+
31
+ ## Interface description
32
+
33
+ Conference SDK no-UI integration provides recording control and state subscription capabilities through `useRoomState()`. The recording task is fully managed by the server, and the client is only responsible for starting and stopping it.
34
+
35
+ |**Type**|**Name**|**Description**|
36
+ |---------|---------|---------|
37
+ |Method|`startRecording(): Promise<void>`|Starts cloud recording. Only the **room owner or administrator** can call it, and it must be called after successfully entering the room.|
38
+ |Method|`stopRecording(): Promise<void>`|Stops cloud recording. Only the **room owner or administrator** can call it.|
39
+ |State|`currentRoom.recordingInfo`|The recording information of the current room, including the `status` field (`RecordingStatus.Recording` indicates recording in progress).|
40
+ |Event|`RoomEvent.onRecordingStarted`|Triggered when the recording task starts successfully. The callback parameter is `{ roomInfo, operator }`.|
41
+ |Event|`RoomEvent.onRecordingStopped`|Triggered when the recording task stops. The callback parameter is `{ roomInfo, operator, reason }`. `reason` can distinguish between active stop and abnormal interruption.|
42
+
43
+ ## Step 1: Start cloud recording
44
+
45
+ ### Permission requirements
46
+
47
+ Only the **room owner or administrator** can call `startRecording()`; other roles calling it will throw a permission error. Only one recording task can exist in the same room at a time, and repeated calls will also return an error.
48
+
49
+ ### Sample code
50
+
51
+ 【Vue3】
52
+ ``` typescript
53
+ import { useRoomState } from 'tuikit-atomicx-vue3/room';
54
+
55
+ const { startRecording } = useRoomState();
56
+
57
+ await startRecording();
58
+ ```
59
+
60
+ 【React】
61
+ ``` typescript
62
+ import { useRoomState } from 'tuikit-atomicx-react/room';
63
+
64
+ const { startRecording } = useRoomState();
65
+
66
+ await startRecording();
67
+ ```
68
+
69
+ ### Error handling
70
+
71
+ `startRecording()` throws an error when it fails. Common error cases are as follows:
72
+
73
+ |**Error code**|**Meaning**|**Suggested handling**|
74
+ |---------|---------|---------|
75
+ |`100001`|Backend system error.|Retry later; if it persists, submit a ticket for investigation.|
76
+ |`100004`|The room does not exist.|Confirm that you have successfully entered the room through `createAndJoinRoom()` or `joinRoom()` before calling the recording interface.|
77
+ |`100006`|No permission; must be the room owner or administrator.|Check the current user role; only the room owner or administrator can start recording.|
78
+ |`101072`|The recording configuration does not exist or is not enabled.|Confirm that you have completed the console package activation, ticket configuration, and value-added feature switch. .|
79
+
80
+ 【Vue3】
81
+ ``` typescript
82
+ import { useRoomState } from 'tuikit-atomicx-vue3/room';
83
+
84
+ const { startRecording } = useRoomState();
85
+
86
+ try {
87
+ await startRecording();
88
+ } catch (error: any) {
89
+ switch (error?.code) {
90
+ case 100001:
91
+ console.error('Backend system error, please retry later.');
92
+ break;
93
+ case 100004:
94
+ console.error('The room does not exist, please confirm you have entered the room before starting recording.');
95
+ break;
96
+ case 100006:
97
+ console.error('Insufficient permission, only the room owner or administrator can start recording.');
98
+ break;
99
+ case 101072:
100
+ console.error('The recording configuration does not exist or is not enabled, please check the console activation configuration.');
101
+ break;
102
+ default:
103
+ console.error('Failed to start recording:', error);
104
+ }
105
+ }
106
+ ```
107
+
108
+ 【React】
109
+ ``` typescript
110
+ import { useRoomState } from 'tuikit-atomicx-react/room';
111
+
112
+ const { startRecording } = useRoomState();
113
+
114
+ try {
115
+ await startRecording();
116
+ } catch (error: any) {
117
+ switch (error?.code) {
118
+ case 100001:
119
+ console.error('Backend system error, please retry later.');
120
+ break;
121
+ case 100002:
122
+ console.error('Parameter error, please check the passed parameters.');
123
+ break;
124
+ case 100004:
125
+ console.error('The room does not exist, please confirm you have entered the room before starting recording.');
126
+ break;
127
+ case 100006:
128
+ console.error('Insufficient permission, only the room owner or administrator can start recording.');
129
+ break;
130
+ case 101072:
131
+ console.error('The recording configuration does not exist or is not enabled, please check the console activation configuration.');
132
+ break;
133
+ default:
134
+ console.error('Failed to start recording:', error);
135
+ }
136
+ }
137
+ ```
138
+
139
+ ## Step 2: Stop cloud recording
140
+
141
+ ### Preconditions
142
+
143
+ There is a recording task in progress (`RecordingStatus.Recording`) in the current room.
144
+
145
+ ### Permission requirements
146
+
147
+ Only the **room owner or administrator** can call `stopRecording()`.
148
+
149
+ ### Sample code
150
+
151
+ 【Vue3】
152
+ ``` typescript
153
+ import { useRoomState } from 'tuikit-atomicx-vue3/room';
154
+
155
+ const { stopRecording } = useRoomState();
156
+
157
+ try {
158
+ await stopRecording();
159
+ } catch (error: any) {
160
+ console.error('Failed to stop recording:', error);
161
+ }
162
+ ```
163
+
164
+ 【React】
165
+ ``` typescript
166
+ import { useRoomState } from 'tuikit-atomicx-react/room';
167
+
168
+ const { stopRecording } = useRoomState();
169
+
170
+ try {
171
+ await stopRecording();
172
+ } catch (error: any) {
173
+ console.error('Failed to stop recording:', error);
174
+ }
175
+ ```
176
+
177
+ ## Step 3: Monitor recording state changes
178
+
179
+ ### Preconditions
180
+ - You have successfully entered the room.
181
+
182
+ - It is recommended to subscribe to events **immediately** after entering the room to avoid missing recording notifications initiated by other ends (such as a mobile room owner).
183
+
184
+ ### Sample code
185
+
186
+ 【Vue3】
187
+ ``` typescript
188
+ import { useRoomState, RecordingStatus, RecordingStopReason, RoomEvent } from 'tuikit-atomicx-vue3/room';
189
+
190
+ const { currentRoom, subscribeEvent } = useRoomState();
191
+
192
+ // Actively query the current recording state
193
+ const isRecording = currentRoom.value?.recordingInfo?.status === RecordingStatus.Recording;
194
+
195
+ // Listen for recording start
196
+ subscribeEvent(RoomEvent.onRecordingStarted, ({ operator }) => {
197
+ console.log('Recording started, operator:', operator.userId);
198
+ });
199
+
200
+ // Listen for recording stop
201
+ subscribeEvent(RoomEvent.onRecordingStopped, ({ operator, reason }) => {
202
+ if (reason === RecordingStopReason.StoppedByUser) {
203
+ console.log('Recording stopped, operator:', operator.userId);
204
+ } else if (reason === RecordingStopReason.RecorderLeftRoom) {
205
+ console.warn('Recording interrupted abnormally, the recording robot has left the room. Restart recording if needed.');
206
+ }
207
+ });
208
+ ```
209
+
210
+ 【React】
211
+ ``` typescript
212
+ import { useRoomState, RecordingStatus, RecordingStopReason, RoomEvent } from 'tuikit-atomicx-react/room';
213
+
214
+ const { currentRoom, subscribeEvent } = useRoomState();
215
+
216
+ // Actively query the current recording state
217
+ const isRecording = currentRoom?.recordingInfo?.status === RecordingStatus.Recording;
218
+
219
+ // Listen for recording start
220
+ subscribeEvent(RoomEvent.onRecordingStarted, ({ operator }) => {
221
+ console.log('Recording started, operator:', operator.userId);
222
+ });
223
+
224
+ // Listen for recording stop
225
+ subscribeEvent(RoomEvent.onRecordingStopped, ({ operator, reason }) => {
226
+ if (reason === RecordingStopReason.StoppedByUser) {
227
+ console.log('Recording stopped, operator:', operator.userId);
228
+ } else if (reason === RecordingStopReason.RecorderLeftRoom) {
229
+ console.warn('Recording interrupted abnormally, the recording robot has left the room. Restart recording if needed.');
230
+ }
231
+ });
232
+ ```
233
+
234
+ ### Error cases
235
+
236
+ The `reason` field of the `onRecordingStopped` event identifies the reason the recording stopped:
237
+
238
+ |**Enum value**|**Value**|**Description**|
239
+ |---------|---------|---------|
240
+ |`RecordingStopReason.StoppedByUser`|`0`|The room owner or administrator actively called `stopRecording()` for a normal stop.|
241
+ |`RecordingStopReason.RecorderLeftRoom`|`1`|The recording robot left the room abnormally and the recording was interrupted. It is recommended to prompt the user and decide whether to restart recording based on business needs.|
242
+
243
+ > **Note:**
244
+ > - The cloud recording feature requires completing package purchase, storage service activation, and ticket configuration in advance. Confirm that you have completed all steps in the **Prerequisites** of this document.
245
+ > - Recording files are stored in the Cloud VOD (VOD) or Cloud Object Storage (COS) you configured. Go to the corresponding console to view and manage them.
@@ -0,0 +1,196 @@
1
+ This document introduces how to use the Atomicx API to integrate whiteboard or screen sharing annotation into your own meeting UI.
2
+
3
+ First, choose the feature you want to implement:
4
+
5
+ |Goal|Do you need to start screen sharing first|Integration order|
6
+ |---------|---------|---------|
7
+ |Whiteboard: Write on a blank canvas|No|Once the display area is ready, call `startWhiteboard`|
8
+ |Screen sharing annotation: Annotate on the screen sharing view|Yes|Call `startScreenShare` first, then call `startWhiteboard`|
9
+
10
+ > **Note:**
11
+ > **To integrate screen sharing annotation, you do not need to integrate the standalone whiteboard first.** Both features use `startWhiteboard` to create the drawing layer, but their integration flows are independent of each other. Choose one according to your business goal.
12
+ >
13
+
14
+ ## Preparation
15
+
16
+ Before you start, please confirm:
17
+ - User state: The user has completed login authentication through `useLoginState` (see Integration overview) and is already in a room as the owner or a member of that room (see Room management).
18
+
19
+ - Environment dependency: The project has correctly installed and imported `tuikit-atomicx-vue3` (Vue 3), version `6.1.0` or later.
20
+
21
+ - Use the latest stable versions of Chrome and Edge on Windows or macOS desktops.
22
+
23
+ The "display area" in the code in this document is a `<div>` on the page used to display the whiteboard or shared view. After setting its `id`, pass that `id` to the API. It determines both where the content is displayed and the display size, and you do not need to understand the internal implementation of the whiteboard.
24
+
25
+ ## Integrating the whiteboard
26
+
27
+ The whiteboard does not depend on screen sharing. Prepare a display area, and when the user clicks "Open whiteboard", pass its `id` to `startWhiteboard`:
28
+ ``` typescript
29
+ <template>
30
+ <button @click="openWhiteboard">Open whiteboard</button>
31
+ <div id="whiteboard-view" class="content-view" />
32
+ </template>
33
+
34
+ <script setup lang="ts">
35
+ import { useWhiteboardState } from 'tuikit-atomicx-vue3/room';
36
+
37
+ const { startWhiteboard } = useWhiteboardState();
38
+
39
+ async function openWhiteboard() {
40
+ await startWhiteboard({
41
+ view: 'whiteboard-view',
42
+ canvasColor: '#FFFFFF',
43
+ });
44
+ }
45
+ </script>
46
+
47
+ <style scoped>
48
+ .content-view {
49
+ position: relative;
50
+ width: 100%;
51
+ height: 600px;
52
+ background: #fff;
53
+ }
54
+ </style>
55
+ ```
56
+
57
+ After the call succeeds, the current user can draw in that area, and other members in the room will see the whiteboard view in real time.
58
+
59
+ ## Integrating screen sharing annotation
60
+
61
+ Screen sharing annotation adds a transparent drawing layer on top of the shared view. The whole flow has only two steps:
62
+ 1. Display the screen sharing view in a `<div>` on the page.
63
+
64
+ 2. Pass the `id` of the same `<div>` to `startWhiteboard` so that the strokes overlay the shared view.
65
+
66
+ The following example provides two buttons, "Start sharing" and "Start annotation":
67
+
68
+ ``` typescript
69
+ <template>
70
+ <button @click="shareScreen">Start sharing</button>
71
+ <button @click="openAnnotation">Start annotation</button>
72
+ <div id="screen-share-view" class="content-view" />
73
+ </template>
74
+
75
+ <script setup lang="ts">
76
+ import {
77
+ DeviceStatus,
78
+ useDeviceState,
79
+ useWhiteboardState,
80
+ } from 'tuikit-atomicx-vue3/room';
81
+
82
+ const { screenStatus, startScreenShare } = useDeviceState();
83
+ const { startWhiteboard } = useWhiteboardState();
84
+
85
+ async function shareScreen() {
86
+ await startScreenShare({
87
+ screenAudio: true,
88
+ view: 'screen-share-view',
89
+ });
90
+ }
91
+
92
+ async function openAnnotation() {
93
+ if (screenStatus.value !== DeviceStatus.On) {
94
+ throw new Error('Please start screen sharing first');
95
+ }
96
+
97
+ await startWhiteboard({
98
+ view: 'screen-share-view',
99
+ });
100
+ }
101
+ </script>
102
+
103
+ <style scoped>
104
+ .content-view {
105
+ position: relative;
106
+ width: 100%;
107
+ height: 600px;
108
+ }
109
+ </style>
110
+ ```
111
+
112
+ ## Adding drawing tools
113
+
114
+ The whiteboard and screen sharing annotation use the same set of tool APIs. Just connect the methods below to your toolbar buttons:
115
+ ``` typescript
116
+ import {
117
+ useWhiteboardState,
118
+ WhiteboardTool,
119
+ } from 'tuikit-atomicx-vue3/room';
120
+
121
+ const {
122
+ setToolConfig,
123
+ undo,
124
+ redo,
125
+ clear,
126
+ snapshot,
127
+ } = useWhiteboardState();
128
+
129
+ // Pen
130
+ setToolConfig({
131
+ tool: WhiteboardTool.Pen,
132
+ color: '#006EFF',
133
+ lineWidth: 4,
134
+ });
135
+
136
+ // Rectangle
137
+ setToolConfig({
138
+ tool: WhiteboardTool.Shape,
139
+ shapeType: 'rect',
140
+ color: '#006EFF',
141
+ lineWidth: 4,
142
+ });
143
+
144
+ await undo(); // Undo
145
+ await redo(); // Redo
146
+ await clear(); // Clear
147
+ const image = await snapshot();
148
+ ```
149
+
150
+ The available tools include:
151
+
152
+ |Tool|Enum value|Purpose|
153
+ |---------|---------|---------|
154
+ |Select|`WhiteboardTool.None`|Stop drawing.|
155
+ |Pen|`WhiteboardTool.Pen`|Free-form writing.|
156
+ |Laser pointer|`WhiteboardTool.Laser`|Disappears automatically after a short stay.|
157
+ |Shape|`WhiteboardTool.Shape`|Draw a rectangle or ellipse through `shapeType`.|
158
+ |Arrow|`WhiteboardTool.Arrow`|Mark a direction or key point.|
159
+ |Eraser|`WhiteboardTool.EraserObject`|Erase graphic objects.|
160
+
161
+ When drawing a shape, set `shapeType` in the same configuration object: `rect` for a rectangle and `ellipse` for an ellipse.
162
+
163
+ ## Hiding the whiteboard and annotation entries
164
+
165
+ When closing the whiteboard or annotation, call `stopWhiteboard`:
166
+ ``` typescript
167
+ const { stopWhiteboard } = useWhiteboardState();
168
+
169
+ stopWhiteboard();
170
+ ```
171
+
172
+ ## Updating the whiteboard display area
173
+
174
+ When you need to switch the whiteboard to another display area, you can call `updateWhiteboard` and pass in the new element id.
175
+ ``` typescript
176
+ const { updateWhiteboard } = useWhiteboardState();
177
+
178
+ updateWhiteboard({ view: 'whiteboard-new-view' });
179
+ ```
180
+
181
+ ## Scope of use
182
+ - Does not yet support mobile browsers and webinar (Webinar) rooms.
183
+
184
+ - Currently, the initiator draws while other members watch in real time; simultaneous drawing by multiple people is not yet supported.
185
+
186
+ - The whiteboard and regular screen sharing use the same sharing channel and cannot be enabled at the same time.
187
+
188
+ ## FAQs
189
+
190
+ ### Why is no content displayed on the page after calling `startWhiteboard`?
191
+
192
+ Please confirm that when calling it you passed the `id` of the display area through `view`, and that the corresponding `<div>` exists on the page. If the element is mounted later, call `updateWhiteboard({ view })` after the whiteboard is started.
193
+
194
+ ### Can the whiteboard and regular screen sharing be enabled at the same time?
195
+
196
+ No. The whiteboard and regular screen sharing use the same sharing channel; screen sharing annotation, on the other hand, overlays a drawing layer on top of the screen sharing view, which is a supported combination.