@tencent-rtc/mcp 1.3.4 → 1.3.5

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 (102) hide show
  1. package/package.json +1 -1
  2. package/resource/doc/chatuikit/android/features/theme.md +363 -0
  3. package/resource/doc/chatuikit/{android/client_api_Android.md → faq/android_sdk/client-api.md} +0 -2
  4. package/resource/doc/chatuikit/faq/common/product.md +8 -0
  5. package/resource/doc/chatuikit/faq/flutter_sdk/faq.md +53 -0
  6. package/resource/doc/chatuikit/{iOS/client_api_iOS.md → faq/ios_sdk/client-api.md} +0 -2
  7. package/resource/doc/chatuikit/flutter/features/theme.md +379 -0
  8. package/resource/doc/chatuikit/flutter/integration.md +413 -0
  9. package/resource/doc/chatuikit/flutter/workflow.md +941 -0
  10. package/resource/doc/chatuikit/iOS/features/theme.md +416 -0
  11. package/resource/doc/chatuikit/iOS/workflow.md +0 -0
  12. package/resource/doc/chatuikit/react/components/chat-setting.md +86 -0
  13. package/resource/doc/chatuikit/react/components/contact-list.md +1093 -0
  14. package/resource/doc/chatuikit/react/components/search.md +745 -0
  15. package/resource/doc/chatuikit/vue/components/chat-setting.md +64 -0
  16. package/resource/doc/chatuikit/vue/components/contact-list.md +679 -0
  17. package/resource/doc/chatuikit/vue/components/search.md +1384 -0
  18. package/resource/doc/livekit/live/android/workflow.md +137 -6
  19. package/resource/doc/livekit/live/ios/live-audience-list.md +339 -0
  20. package/resource/doc/livekit/live/ios/live-audio-effect.md +370 -0
  21. package/resource/doc/livekit/live/ios/live-barrage.md +517 -0
  22. package/resource/doc/livekit/live/ios/live-base-beauty.md +247 -0
  23. package/resource/doc/livekit/live/ios/live-co-guest-interaction.md +518 -0
  24. package/resource/doc/livekit/live/ios/live-gift.md +783 -0
  25. package/resource/doc/livekit/live/ios/live-host-interaction.md +815 -0
  26. package/resource/doc/livekit/live/ios/live-integration.md +931 -0
  27. package/resource/doc/livekit/live/ios/live-live-list.md +485 -0
  28. package/resource/doc/livekit/live/ios/workflow.md +454 -0
  29. package/resource/doc/rtcengine/web/plugin/20-advanced-customized-capture-rendering.md +87 -0
  30. package/resource/doc/rtcengine/web/plugin/21-advanced-auto-play-policy.md +87 -0
  31. package/resource/doc/rtcengine/web/plugin/22-advanced-audio-mixer.md +175 -0
  32. package/resource/doc/rtcengine/web/plugin/23-advanced-support-detection.md +221 -0
  33. package/resource/doc/rtcengine/web/plugin/24-advanced-network-quality.md +140 -0
  34. package/resource/doc/rtcengine/web/plugin/25-advanced-device-change.md +99 -0
  35. package/resource/doc/rtcengine/web/plugin/26-advanced-publish-cdn-stream.md +451 -0
  36. package/resource/doc/rtcengine/web/plugin/27-advanced-small-stream.md +151 -0
  37. package/resource/doc/rtcengine/web/plugin/28-advanced-beauty.md +322 -0
  38. package/resource/doc/rtcengine/web/plugin/29-advanced-water-mark.md +149 -0
  39. package/resource/doc/rtcengine/web/plugin/30-advanced-cross-room-link.md +96 -0
  40. package/resource/doc/rtcengine/web/plugin/31-advanced-plugins-overview.md +330 -0
  41. package/resource/doc/rtcengine/web/plugin/34-advanced-proxy.md +248 -0
  42. package/resource/doc/rtcengine/web/plugin/35-advanced-ai-denoiser.md +81 -0
  43. package/resource/doc/rtcengine/web/plugin/36-advanced-virtual-background.md +242 -0
  44. package/resource/doc/rtcengine/web/plugin/37-advanced-voice-changer.md +99 -0
  45. package/resource/doc/rtcengine/web/plugin/39-advanced-video-decoder.md +33 -0
  46. package/resource/doc/rtcengine/web/plugin/40-advanced-video-mixer.md +379 -0
  47. package/resource/doc/rtcengine/web/plugin/41-advanced-small-stream-auto-switcher.md +91 -0
  48. package/resource/doc/rtcengine/web/plugin/42-advanced-realtime-transcriber.md +315 -0
  49. package/resource/doc/rtcengine/web/plugin/43-advanced-face-detection.md +180 -0
  50. package/tools/chat/get-native-chat-feature-detail.js +30 -0
  51. package/tools/chat/get-native-chat-feature-detail.js.map +1 -0
  52. package/tools/chat/get-native-chat-integration.js +30 -12
  53. package/tools/chat/get-native-chat-integration.js.map +1 -1
  54. package/tools/common/get-faq.js +2 -4
  55. package/tools/common/get-faq.js.map +1 -1
  56. package/tools/definitions/get_native_chat_feature_detail_def.js +32 -0
  57. package/tools/definitions/get_native_chat_feature_detail_def.js.map +1 -0
  58. package/tools/definitions/get_native_chat_uikit_integration_def.js +19 -7
  59. package/tools/definitions/get_native_chat_uikit_integration_def.js.map +1 -1
  60. package/tools/definitions/{get_native_live_extra_features_def.js → get_native_live_uikit_extra_features_def.js} +3 -3
  61. package/tools/definitions/get_native_live_uikit_extra_features_def.js.map +1 -0
  62. package/tools/definitions/{get_native_live_interaction_def.js → get_native_live_uikit_interaction_def.js} +3 -3
  63. package/tools/definitions/get_native_live_uikit_interaction_def.js.map +1 -0
  64. package/tools/definitions/get_web_chat_uikit_component_detail_def.js +49 -10
  65. package/tools/definitions/get_web_chat_uikit_component_detail_def.js.map +1 -1
  66. package/tools/index.js +6 -4
  67. package/tools/index.js.map +1 -1
  68. package/tools/live/{get_native_live_extra_features.js → get_native_live_uikit_extra_features.js} +4 -4
  69. package/tools/live/get_native_live_uikit_extra_features.js.map +1 -0
  70. package/tools/live/{get_native_live_interaction.js → get_native_live_uikit_interaction.js} +4 -4
  71. package/tools/live/get_native_live_uikit_interaction.js.map +1 -0
  72. package/tools/rtcengine/get-rtcengine-web-sdk-integration.js.map +1 -1
  73. package/tools/rtcengine/get-trtc-sdk-faq.js +32 -0
  74. package/tools/rtcengine/get-trtc-sdk-faq.js.map +1 -0
  75. package/tools/rtcengine/get-trtc-web-sdk-faq.js +1 -1
  76. package/tools/rtcengine/get-trtc-web-sdk-integration.js.map +1 -1
  77. package/tools/rtcengine/get-trtc-web-sdk-plugin.js +45 -0
  78. package/tools/rtcengine/get-trtc-web-sdk-plugin.js.map +1 -0
  79. package/utils/handle-component-name.js +0 -16
  80. package/utils/handle-component-name.js.map +1 -1
  81. package/utils/report-cls-client.js +1 -1
  82. package/utils/report-es-client.js +1 -1
  83. package/resource/doc/chatuikit/android/generate_UserSig.md +0 -306
  84. package/resource/doc/chatuikit/android/integrarte_only_tuichat_Android.md +0 -290
  85. package/resource/doc/chatuikit/android/quick_start_Android.md +0 -138
  86. package/resource/doc/chatuikit/android/show_typing_Android.md +0 -43
  87. package/resource/doc/chatuikit/flutter/generate_UserSig.md +0 -306
  88. package/resource/doc/chatuikit/flutter/integrate_tuikit_Flutter.md +0 -133
  89. package/resource/doc/chatuikit/iOS/generate_UserSig.md +0 -306
  90. package/resource/doc/chatuikit/iOS/integrate_only_tuichat_iOS.md +0 -748
  91. package/resource/doc/chatuikit/iOS/quick_start_iOS.md +0 -163
  92. package/resource/doc/chatuikit/iOS/show_typing_iOS.md +0 -52
  93. package/tools/definitions/get_native_live_extra_features_def.js.map +0 -1
  94. package/tools/definitions/get_native_live_interaction_def.js.map +0 -1
  95. package/tools/live/get_native_live_extra_features.js.map +0 -1
  96. package/tools/live/get_native_live_interaction.js.map +0 -1
  97. /package/resource/doc/chatuikit/android/{integrate_tuikit_Android.md → integration.md} +0 -0
  98. /package/resource/doc/chatuikit/{faq/native_sdk/faq.md → android/workflow.md} +0 -0
  99. /package/resource/doc/chatuikit/{flutter/client_api_Flutter.md → faq/flutter_sdk/client-api.md} +0 -0
  100. /package/resource/doc/chatuikit/iOS/{integrate_tuikit_iOS.md → integration.md} +0 -0
  101. /package/resource/doc/chatuikit/react/components/{chatheader.md → chat-header.md} +0 -0
  102. /package/resource/doc/chatuikit/vue/components/{chatheader.md → chat-header.md} +0 -0
@@ -0,0 +1,931 @@
1
+ This document guides you through building a basic live streaming app with host broadcasting and audience viewing capabilities using the core component [LiveCoreView](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.view/-live-core-view/index.html) from the **AtomicXCore SDK**.
2
+
3
+ ### Core Features
4
+
5
+ **LiveCoreView** is a lightweight `View` component purpose-built for live streaming scenarios. It serves as the foundation of your live streaming implementation, encapsulating all complex streaming technologies—including stream publishing and playback, co-hosting, and audio/video rendering. Use LiveCoreView as the "canvas" for your live video, enabling you to focus on developing your custom UI and interactions.
6
+
7
+ The following view hierarchy diagram illustrates the position and role of **LiveCoreView** within the live streaming interface:
8
+
9
+ ![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100043650599/96041acccc0711f093295254001c06ec.png)
10
+
11
+
12
+ ## Core Concepts
13
+ <table>
14
+ <tr>
15
+ <td rowspan="1" colSpan="1" >**Core Concept**</td>
16
+
17
+ <td rowspan="1" colSpan="1" >**Core Responsibility**</td>
18
+
19
+ <td rowspan="1" colSpan="1" >**Key API / Property**</td>
20
+ </tr>
21
+
22
+ <tr>
23
+ <td rowspan="1" colSpan="1" >LiveCoreView</td>
24
+
25
+ <td rowspan="1" colSpan="1" >Handles publishing, playing, and rendering audio/video streams. Provides adapter interfaces for integrating custom UI components (e.g., user info, PK progress bar).</td>
26
+
27
+ <td rowspan="1" colSpan="1" >- `viewType`:<br> - `.pushView` (host publishing view)<br> - `.playView` (audience playback view)<br>- `setLiveId()`: Binds the live room ID for this view.<br>- `videoViewDelegate`: Adapter for custom video display UI slots.</td>
28
+ </tr>
29
+
30
+ <tr>
31
+ <td rowspan="1" colSpan="1" >LiveListStore</td>
32
+
33
+ <td rowspan="1" colSpan="1" >Manages the complete live room lifecycle (create, join, leave), synchronizes state, and listens for passive events (e.g., live ended, kicked out).</td>
34
+
35
+ <td rowspan="1" colSpan="1" >- `createLive()`: Start live stream as host.<br>- `endLive()`: End live stream as host.<br>- `joinLive()`: Audience joins live room.<br>- `leaveLive()`: Leave live room.</td>
36
+ </tr>
37
+
38
+ <tr>
39
+ <td rowspan="1" colSpan="1" >LiveInfo</td>
40
+
41
+ <td rowspan="1" colSpan="1" >Defines room parameters before going live, such as room ID, seat layout mode, max co-hosts, etc.</td>
42
+
43
+ <td rowspan="1" colSpan="1" >- `liveID`: Unique room identifier.<br>- `seatLayoutTemplateID`: Layout template ID (e.g., 600 for dynamic grid).</td>
44
+ </tr>
45
+ </table>
46
+
47
+
48
+ ## Preparation
49
+
50
+ ### Step 1: Activate the Service
51
+
52
+ See [Activate Service](https://write.woa.com/document/141936672617742336) to obtain either the trial or paid version of the SDK.Then, go to [the Console](https://console.trtc.io/app) for application management, and get the following:
53
+ - `SDKAppID`: Application identifier (required). Tencent Cloud uses `SDKAppID` for billing and details.
54
+
55
+ - `SDKSecretKey`: Application secret key, used to initialize the configuration file with secret information.
56
+
57
+ ![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100043650599/a926d228cc0711f093295254001c06ec.png)
58
+
59
+
60
+ ### Step 2: Import AtomicXCore into Your Project
61
+ 1. **Install the Component**: Add `pod 'AtomicXCore'` to your `Podfile`, then run `pod install`.
62
+
63
+ ``` ruby
64
+ target 'xxxx' do
65
+ pod 'AtomicXCore'
66
+ end
67
+ ```
68
+ 2. **Configure App Permissions**: Add camera and microphone usage descriptions to your app's `Info.plist` file.
69
+
70
+ ``` xml
71
+ <key>NSCameraUsageDescription</key>
72
+ <string>TUILiveKit needs camera access to enable video recording with picture</string>
73
+ <key>NSMicrophoneUsageDescription</key>
74
+ <string>TUILiveKit needs microphone permission to enable sound in recorded videos</string>
75
+ ```
76
+ ![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100043650599/b47f58e0cc0711f0afdc52540044a08e.png)
77
+
78
+
79
+ ### Step 3: Implement Login Logic
80
+
81
+ Call `LoginStore.shared.login` in your project to complete authentication. **This is required before using any functionality of AtomicXCore**.
82
+
83
+ > **Note:**
84
+ >
85
+
86
+ > We recommend calling LoginStore.shared.login only after your app's own user authentication is successful, to ensure clear and consistent login logic.
87
+ >
88
+
89
+ ``` swift
90
+ import AtomicXCore
91
+
92
+ // AppDelegate.swift
93
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
94
+ LoginStore.shared.login(sdkAppID: 1400000001, // Replace with your SDKAppID
95
+ userID: "test_001", // Replace with your UserID
96
+ userSig: "xxxxxxxxxxx") { result in // Replace with your UserSig
97
+ switch result {
98
+ case .success(let info):
99
+ debugPrint("login success")
100
+ case .failure(let error):
101
+ debugPrint("login failed code:\(error.code), message:\(error.message)")
102
+ }
103
+ }
104
+ return true
105
+ }
106
+ ```
107
+
108
+ **Login API Parameter Description**
109
+ <table>
110
+ <tr>
111
+ <td rowspan="1" colSpan="1" >**Parameter**</td>
112
+
113
+ <td rowspan="1" colSpan="1" >**Type**</td>
114
+
115
+ <td rowspan="1" colSpan="1" >**Description**</td>
116
+ </tr>
117
+
118
+ <tr>
119
+ <td rowspan="1" colSpan="1" >`SDKAppID`</td>
120
+
121
+ <td rowspan="1" colSpan="1" >`Int`</td>
122
+
123
+ <td rowspan="1" colSpan="1" >Get this from [TRTC console](https://console.trtc.io/app).</td>
124
+ </tr>
125
+
126
+ <tr>
127
+ <td rowspan="1" colSpan="1" >`UserID`</td>
128
+
129
+ <td rowspan="1" colSpan="1" >`String`</td>
130
+
131
+ <td rowspan="1" colSpan="1" >The unique ID for the current user. Must contain only English letters, numbers, hyphens, and underscores.</td>
132
+ </tr>
133
+
134
+ <tr>
135
+ <td rowspan="1" colSpan="1" >`userSig`</td>
136
+
137
+ <td rowspan="1" colSpan="1" >`String`</td>
138
+
139
+ <td rowspan="1" colSpan="1" >A ticket for Tencent Cloud authentication. Please note:<br>- Development Environment: You can use the local `GenerateTestUserSig.genTestSig` function to generate a `UserSig` or generate a temporary UserSig via the [UserSig Generation Tool](https://console.trtc.io/usersig).<br>- Production Environment: To prevent key leakage, you must use a server-side method to generate `UserSig`. For details, see [Generating UserSig on the Server](https://write.woa.com/document/89644530319802368).</td>
140
+ </tr>
141
+ </table>
142
+
143
+
144
+ ## Building a Basic Live Room
145
+
146
+ ### Step 1: Implement Broadcaster Video Streaming
147
+
148
+ Follow these steps to quickly set up broadcaster video streaming:
149
+
150
+ ![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100043650599/bf07f34bcc0711f0ae4f52540099c741.png)
151
+
152
+
153
+ > **Note:**
154
+ >
155
+
156
+ > For a complete broadcaster streaming implementation, refer to [TUILiveRoomAnchorViewController.swift](https://github.com/Tencent-RTC/TUIKit_iOS/blob/main/live/Sources/LiveStream/TUILiveRoomAnchorViewController.swift) in the TUILiveKit open source project.
157
+ >
158
+
159
+ 1. **Initialize the Broadcaster Streaming View**
160
+
161
+
162
+ In your broadcaster view controller, create a `LiveCoreView` instance and set `viewType` to `.pushView`.
163
+
164
+ ``` swift
165
+ import AtomicXCore
166
+
167
+ // YourAnchorViewController represents your broadcaster streaming view controller
168
+ class YourAnchorViewController: UIViewController {
169
+
170
+ private let liveId: String
171
+ // 1. Add LiveCoreView as a property of your view controller
172
+ private let coreView = LiveCoreView(viewType: .pushView, frame: UIScreen.main.bounds)
173
+
174
+ // 2. Add a convenience initializer for instance initialization
175
+ // - liveId: The ID of the live room to start streaming
176
+ public init(liveId: String) {
177
+ self.liveId = liveId
178
+ super.init(nibName: nil, bundle: nil)
179
+ self.coreView.setLiveID(liveId)
180
+ }
181
+
182
+ required init?(coder: NSCoder) {
183
+ fatalError("init(coder:) has not been implemented")
184
+ }
185
+
186
+ public override func viewDidLoad() {
187
+ super.viewDidLoad()
188
+ // 3. Add the broadcaster streaming view to your view
189
+ view.addSubview(coreView)
190
+ }
191
+ }
192
+ ```
193
+ 2. **Open Camera and Microphone**
194
+
195
+
196
+ Call `DeviceStore.shared.openLocalCamera` and `DeviceStore.shared.openLocalMicrophone` to open the camera and microphone. **No further action is required—LiveCoreView automatically previews the current camera video stream**.
197
+
198
+ ``` swift
199
+ import AtomicXCore
200
+
201
+ class YourAnchorViewController: UIViewController {
202
+ // ... other code ...
203
+ public override func viewDidLoad() {
204
+ super.viewDidLoad()
205
+ // Enable devices
206
+ openDevices()
207
+ }
208
+
209
+ private func openDevices() {
210
+ // 1. Enable front camera
211
+ DeviceStore.shared.openLocalCamera(isFront: true, completion: nil)
212
+ // 2. Enable microphone
213
+ DeviceStore.shared.openLocalMicrophone(completion: nil)
214
+ }
215
+ }
216
+ ```
217
+ 3. **Start Live Streaming**
218
+
219
+
220
+ Call `LiveListStore.shared.createLive` to start streaming.
221
+
222
+ ``` swift
223
+ import AtomicXCore
224
+
225
+ class YourAnchorViewController: UIViewController {
226
+
227
+ // ... other code ...
228
+
229
+ // Call the start streaming interface to begin live streaming
230
+ private func startLive() {
231
+ var liveInfo = LiveInfo()
232
+ // 1. Set the live room ID
233
+ liveInfo.liveID = self.liveId
234
+ // 2. Set the live room name
235
+ liveInfo.liveName = "test live"
236
+ // 3. Configure layout template, default: 600 dynamic grid layout
237
+ liveInfo.seatLayoutTemplateID = 600
238
+ // 4. Keep the broadcaster always on the seat
239
+ liveInfo.keepOwnerOnSeat = true
240
+ // 5. Call LiveListStore.shared.createLive to start streaming
241
+ LiveListStore.shared.createLive(liveInfo) { [weak self] result in
242
+ guard let self = self else { return }
243
+ switch result {
244
+ case .success(let info):
245
+ debugPrint("startLive success")
246
+ case .failure(let error):
247
+ debugPrint("startLive error:\(error.message)")
248
+ }
249
+ }
250
+ }
251
+ }
252
+ ```
253
+
254
+ `LiveInfo` Parameter Descriptions:
255
+
256
+ <table>
257
+ <tr>
258
+ <td rowspan="1" colSpan="1" >**Parameter Name**</td>
259
+
260
+ <td rowspan="1" colSpan="1" >**Type**</td>
261
+
262
+ <td rowspan="1" colSpan="1" >**Attribute**</td>
263
+
264
+ <td rowspan="1" colSpan="1" >**Description**</td>
265
+ </tr>
266
+
267
+ <tr>
268
+ <td rowspan="1" colSpan="1" >`liveID`</td>
269
+
270
+ <td rowspan="1" colSpan="1" >`String`</td>
271
+
272
+ <td rowspan="1" colSpan="1" >Required</td>
273
+
274
+ <td rowspan="1" colSpan="1" >Unique identifier for the live room.</td>
275
+ </tr>
276
+
277
+ <tr>
278
+ <td rowspan="1" colSpan="1" >`liveName`</td>
279
+
280
+ <td rowspan="1" colSpan="1" >`String`</td>
281
+
282
+ <td rowspan="1" colSpan="1" >Optional</td>
283
+
284
+ <td rowspan="1" colSpan="1" >Title of the live room.</td>
285
+ </tr>
286
+
287
+ <tr>
288
+ <td rowspan="1" colSpan="1" >`notice`</td>
289
+
290
+ <td rowspan="1" colSpan="1" >`String`</td>
291
+
292
+ <td rowspan="1" colSpan="1" >Optional</td>
293
+
294
+ <td rowspan="1" colSpan="1" >Announcement for the live room.</td>
295
+ </tr>
296
+
297
+ <tr>
298
+ <td rowspan="1" colSpan="1" >`isMessageDisable`</td>
299
+
300
+ <td rowspan="1" colSpan="1" >`Bool`</td>
301
+
302
+ <td rowspan="1" colSpan="1" >Optional</td>
303
+
304
+ <td rowspan="1" colSpan="1" >Whether to mute chat (true: yes, false: no).</td>
305
+ </tr>
306
+
307
+ <tr>
308
+ <td rowspan="1" colSpan="1" >`isPublicVisible`</td>
309
+
310
+ <td rowspan="1" colSpan="1" >`Bool`</td>
311
+
312
+ <td rowspan="1" colSpan="1" >Optional</td>
313
+
314
+ <td rowspan="1" colSpan="1" >Whether the room is publicly visible (true: yes, false: no).</td>
315
+ </tr>
316
+
317
+ <tr>
318
+ <td rowspan="1" colSpan="1" >`isSeatEnabled`</td>
319
+
320
+ <td rowspan="1" colSpan="1" >`Bool`</td>
321
+
322
+ <td rowspan="1" colSpan="1" >Optional</td>
323
+
324
+ <td rowspan="1" colSpan="1" >Whether to enable seat functionality (true: yes, false: no).</td>
325
+ </tr>
326
+
327
+ <tr>
328
+ <td rowspan="1" colSpan="1" >`keepOwnerOnSeat`</td>
329
+
330
+ <td rowspan="1" colSpan="1" >`Bool`</td>
331
+
332
+ <td rowspan="1" colSpan="1" >Optional</td>
333
+
334
+ <td rowspan="1" colSpan="1" >Whether to keep the owner on the seat.</td>
335
+ </tr>
336
+
337
+ <tr>
338
+ <td rowspan="1" colSpan="1" >`maxSeatCount`</td>
339
+
340
+ <td rowspan="1" colSpan="1" >`Int`</td>
341
+
342
+ <td rowspan="1" colSpan="1" >Required</td>
343
+
344
+ <td rowspan="1" colSpan="1" >Maximum number of seats.</td>
345
+ </tr>
346
+
347
+ <tr>
348
+ <td rowspan="1" colSpan="1" >`seatMode`</td>
349
+
350
+ <td rowspan="1" colSpan="1" >`TakeSeatMode`</td>
351
+
352
+ <td rowspan="1" colSpan="1" >Optional</td>
353
+
354
+ <td rowspan="1" colSpan="1" >Seat mode (.free: free to take seat, .apply: apply to take seat).</td>
355
+ </tr>
356
+
357
+ <tr>
358
+ <td rowspan="1" colSpan="1" >`seatLayoutTemplateID`</td>
359
+
360
+ <td rowspan="1" colSpan="1" >`UInt`</td>
361
+
362
+ <td rowspan="1" colSpan="1" >Required</td>
363
+
364
+ <td rowspan="1" colSpan="1" >Seat layout template ID.</td>
365
+ </tr>
366
+
367
+ <tr>
368
+ <td rowspan="1" colSpan="1" >`coverURL`</td>
369
+
370
+ <td rowspan="1" colSpan="1" >`String`</td>
371
+
372
+ <td rowspan="1" colSpan="1" >Optional</td>
373
+
374
+ <td rowspan="1" colSpan="1" >Cover image URL for the live room.</td>
375
+ </tr>
376
+
377
+ <tr>
378
+ <td rowspan="1" colSpan="1" >`backgroundURL`</td>
379
+
380
+ <td rowspan="1" colSpan="1" >`String`</td>
381
+
382
+ <td rowspan="1" colSpan="1" >Optional</td>
383
+
384
+ <td rowspan="1" colSpan="1" >Background image URL for the live room.</td>
385
+ </tr>
386
+
387
+ <tr>
388
+ <td rowspan="1" colSpan="1" >`categoryList`</td>
389
+
390
+ <td rowspan="1" colSpan="1" >`NSNumber`</td>
391
+
392
+ <td rowspan="1" colSpan="1" >Optional</td>
393
+
394
+ <td rowspan="1" colSpan="1" >Category tag list for the live room.</td>
395
+ </tr>
396
+
397
+ <tr>
398
+ <td rowspan="1" colSpan="1" >`activityStatus`</td>
399
+
400
+ <td rowspan="1" colSpan="1" >`Int`</td>
401
+
402
+ <td rowspan="1" colSpan="1" >Optional</td>
403
+
404
+ <td rowspan="1" colSpan="1" >Live activity status.</td>
405
+ </tr>
406
+
407
+ <tr>
408
+ <td rowspan="1" colSpan="1" >`isGiftEnabled`</td>
409
+
410
+ <td rowspan="1" colSpan="1" >`Bool`</td>
411
+
412
+ <td rowspan="1" colSpan="1" >Optional</td>
413
+
414
+ <td rowspan="1" colSpan="1" >Whether to enable gift functionality (true: yes, false: no).</td>
415
+ </tr>
416
+ </table>
417
+
418
+ 4. **End Live Streaming**
419
+
420
+
421
+ After the live stream ends, call `LiveListStore.shared.endLive `to stop streaming and destroy the room. The SDK handles cleanup automatically.
422
+
423
+ ``` swift
424
+ import AtomicXCore
425
+
426
+ class YourAnchorViewController: UIViewController {
427
+
428
+ // ... other code ...
429
+
430
+ // End live streaming
431
+ private func stopLive() {
432
+ LiveListStore.shared.endLive { [weak self] result in
433
+ guard let self = self else { return }
434
+ switch result {
435
+ case .success(let data):
436
+ debugPrint("endLive success")
437
+ case .failure(let error):
438
+ debugPrint("endLive error: \(error.message)")
439
+ }
440
+ }
441
+ }
442
+ }
443
+ ```
444
+
445
+ ### Step 2: Implement Audience Join and Watch
446
+
447
+ Enable audience viewing with the following steps:
448
+
449
+ ![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100043650599/d1169383cc0711f084a45254005ef0f7.png)
450
+
451
+
452
+ > **Note:**
453
+ >
454
+
455
+ > For a complete audience playback implementation, refer to [TUILiveRoomAudienceViewController.swift](https://github.com/Tencent-RTC/TUIKit_iOS/blob/main/live/Sources/LiveStream/TUILiveRoomAudienceViewController.swift) in the TUILiveKit open source project.
456
+ >
457
+
458
+ 1. **Implement the Audience Playback Page**
459
+
460
+
461
+ In your audience view controller, create a `LiveCoreView` instance and set `viewType` to `.playView`.
462
+
463
+ ``` swift
464
+ import AtomicXCore
465
+
466
+ class YourAudienceViewController: UIViewController {
467
+
468
+ // 1. Initialize the audience playback page
469
+ private let coreView = LiveCoreView(viewType: .playView, frame: UIScreen.main.bounds)
470
+ private let liveId: String
471
+
472
+ public init(liveId: String) {
473
+ self.liveId = liveId
474
+ super.init(nibName: nil, bundle: nil)
475
+ // 2. Bind the live ID
476
+ self.coreView.setLiveID(liveId)
477
+ }
478
+
479
+ required init?(coder: NSCoder) {
480
+ fatalError("init(coder:) has not been implemented")
481
+ }
482
+
483
+ public override func viewDidLoad() {
484
+ super.viewDidLoad()
485
+ // 3. Add the playback view to your view
486
+ view.addSubview(coreView)
487
+ }
488
+ }
489
+ ```
490
+ 2. **Join the Live Room to Watch**
491
+
492
+
493
+ Call `LiveListStore.shared.joinLive` to join the live stream. **No further action is required—LiveCoreView will automatically play the current room's video stream**.
494
+
495
+ ``` swift
496
+ import AtomicXCore
497
+
498
+ class YourAudienceViewController: UIViewController {
499
+ // ... other code ...
500
+
501
+ public override func viewDidLoad() {
502
+ super.viewDidLoad()
503
+ view.addSubview(coreView)
504
+ // 4. Join the live room
505
+ joinLive()
506
+ }
507
+
508
+ private func joinLive() {
509
+ // Call LiveListStore.shared.joinLive to enter the live room
510
+ // - liveId: Same liveId as the broadcaster
511
+ LiveListStore.shared.joinLive(liveID: liveId) { [weak self] result in
512
+ guard let self = self else { return }
513
+ switch result {
514
+ case .success(let info):
515
+ debugPrint("joinLive success")
516
+ case .failure(let error):
517
+ debugPrint("joinLive error \(error.message)")
518
+ // If joining fails, exit the page
519
+ // self.dismiss(animated: true)
520
+ }
521
+ }
522
+ }
523
+ }
524
+ ```
525
+ 3. **Leave the Live Room**
526
+
527
+
528
+ When the audience leaves, call `LiveListStore.shared.leaveLive` to exit. The SDK will automatically stop playback and leave the room.
529
+
530
+ ``` swift
531
+ import AtomicXCore
532
+
533
+ class YourAudienceViewController: UIViewController {
534
+
535
+ // ... other code ...
536
+
537
+ // Leave the live room
538
+ private func leaveLive() {
539
+ LiveListStore.shared.leaveLive { [weak self] result in
540
+ guard let self = self else { return }
541
+ switch result {
542
+ case .success:
543
+ debugPrint("leaveLive success")
544
+ case .failure(let error):
545
+ debugPrint("leaveLive error \(error.message)")
546
+ }
547
+ }
548
+ }
549
+ }
550
+ ```
551
+
552
+ ### Step 3: Listen for Live Events
553
+
554
+ After joining a live room, handle "passive" events such as the broadcaster ending the stream or the audience being removed. If you do not listen for these events, the audience UI may remain on a black screen, impacting user experience.
555
+
556
+ Subscribe to `liveListEventPublisher` from `LiveListStore` to listen for events:
557
+ ``` swift
558
+ import AtomicXCore
559
+ import Combine // 1. Import the Combine framework
560
+
561
+ class YourAudienceViewController: UIViewController {
562
+
563
+ // ... other code (coreView, liveId, init, deinit, joinLive, leaveLive, etc.) ...
564
+
565
+ // 2. Define cancellableSet to manage subscription lifecycle
566
+ private var cancellableSet: Set<AnyCancellable> = []
567
+
568
+ public override func viewDidLoad() {
569
+ super.viewDidLoad()
570
+ view.addSubview(coreView)
571
+ // 3. Listen for live events
572
+ setupLiveEventListener()
573
+ // 4. Join the live room
574
+ joinLive()
575
+ }
576
+
577
+ // 5. Add a method to set up event listeners
578
+ private func setupLiveEventListener() {
579
+ LiveListStore.shared.liveListEventPublisher
580
+ .receive(on: RunLoop.main) // Ensure UI updates are handled on the main thread
581
+ .sink { [weak self] event in
582
+ guard let self = self else { return }
583
+ switch event {
584
+ case .onLiveEnded(let liveID, let reason, let message):
585
+ // Live stream ended
586
+ debugPrint("Live ended. liveID: \(liveID), reason: \(reason.rawValue), message: \(message)")
587
+ // Handle logic to exit the live room, e.g., close the current page
588
+ // self.dismiss(animated: true)
589
+ case .onKickedOutOfLive(let liveID, let reason, let message):
590
+ // Kicked out of live stream
591
+ debugPrint("Kicked out of live. liveID: \(liveID), reason: \(reason.rawValue), message: \(message)")
592
+ // Handle logic to exit the live room
593
+ // self.dismiss(animated: true)
594
+ }
595
+ }
596
+ .store(in: &cancellableSet) // Manage subscription
597
+ }
598
+
599
+ // ... joinLive() and leaveLive() methods ...
600
+ }
601
+ ```
602
+
603
+ ### Run and Test
604
+
605
+ After integrating `LiveCoreView`, you will have a pure video rendering view with full live streaming capabilities, but without any interactive UI. To add interactive features, see [Enriching the Live Streaming Scene](https://write.woa.com/#enriching-the-live-streaming-scene).
606
+ <table>
607
+ <tr>
608
+ <td rowspan="1" colSpan="1" ></td>
609
+
610
+ <td rowspan="1" colSpan="1" >**Dynamic Grid Layout**</td>
611
+
612
+ <td rowspan="1" colSpan="1" >**Floating Window Layout**</td>
613
+
614
+ <td rowspan="1" colSpan="1" >**Fixed Grid Layout**</td>
615
+
616
+ <td rowspan="1" colSpan="1" >**Fixed Window Layout**</td>
617
+ </tr>
618
+
619
+ <tr>
620
+ <td rowspan="1" colSpan="1" >Template ID</td>
621
+
622
+ <td rowspan="1" colSpan="1" >600</td>
623
+
624
+ <td rowspan="1" colSpan="1" >601</td>
625
+
626
+ <td rowspan="1" colSpan="1" >800</td>
627
+
628
+ <td rowspan="1" colSpan="1" >801</td>
629
+ </tr>
630
+
631
+ <tr>
632
+ <td rowspan="1" colSpan="1" >Description</td>
633
+
634
+ <td rowspan="1" colSpan="1" >Default layout; grid size adjusts dynamically based on number of co-hosts.</td>
635
+
636
+ <td rowspan="1" colSpan="1" >Co-hosts are displayed as floating windows.</td>
637
+
638
+ <td rowspan="1" colSpan="1" >Fixed number of co-hosts; each occupies a fixed grid.</td>
639
+
640
+ <td rowspan="1" colSpan="1" >Fixed number of co-hosts; guests are displayed as fixed windows.</td>
641
+ </tr>
642
+
643
+ <tr>
644
+ <td rowspan="1" colSpan="1" >Example</td>
645
+
646
+ <td rowspan="1" colSpan="1" ><br>![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100043650599/6a730a2ecc0d11f084a45254005ef0f7.png)</td>
647
+
648
+ <td rowspan="1" colSpan="1" ><br>![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100043650599/71c322e9cc0d11f084a45254005ef0f7.png)</td>
649
+
650
+ <td rowspan="1" colSpan="1" ><br>![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100043650599/a1855792cc0d11f0ae4f52540099c741.png)</td>
651
+
652
+ <td rowspan="1" colSpan="1" ><br>![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100043650599/8885e3ffcc0d11f0afdc52540044a08e.png)</td>
653
+ </tr>
654
+ </table>
655
+
656
+
657
+ ## Advanced Features
658
+
659
+ ### Synchronizing Custom Status in Live Streaming Room
660
+
661
+ In live streaming room, the host may need to synchronize custom information to all audience members, such as "current room topic" or "background music info". Use the `metaData` feature of LiveListStore to achieve this.
662
+
663
+ #### Implementation
664
+ 1. On the host side, set custom information (recommended as JSON) to one or more keys using the `updateLiveMetaData` API. AtomicXCore will synchronize these changes in real time to all audience members.
665
+
666
+ 2. On the audience side, subscribe to `LiveListState.currentLive` and listen for changes in `metaData`. When a relevant key is updated, parse its value and update your business state.
667
+
668
+
669
+ #### Code Example
670
+ ``` swift
671
+ import AtomicXCore
672
+ import Combine
673
+
674
+ // 1. Define a background music model (recommended: Codable)
675
+ struct MusicModel: Codable {
676
+ let musicId: String
677
+ let musicName: String
678
+ }
679
+
680
+ // 2. Host side: Push background music info
681
+ func updateBackgroundMusic(music: MusicModel) {
682
+ guard let jsonData = try? JSONEncoder().encode(music),
683
+ let jsonString = String(data: jsonData, encoding: .utf8) else { return }
684
+
685
+ let metaData = ["music_info": jsonString]
686
+
687
+ LiveListStore.shared.updateLiveMetaData(metaData) { result in
688
+ if case .success = result {
689
+ print("Background music \(music.musicName) pushed successfully")
690
+ } else if case .failure(let error) = result {
691
+ print("Background music push failed: \(error.message)")
692
+ }
693
+ }
694
+ }
695
+
696
+ // 3. Audience side: Subscribe and update business logic
697
+ private func subscribeToDataUpdates() {
698
+ LiveListStore.shared.state
699
+ // Listen for metaData changes in the current room
700
+ .subscribe(StatePublisherSelector(keyPath: \LiveListState.currentLive))
701
+ .map { $0.metaData["music_info"] }
702
+ .removeDuplicates()
703
+ .receive(on: DispatchQueue.main)
704
+ .sink { jsonString in
705
+ guard let jsonString = jsonString,
706
+ let data = jsonString.data(using: .utf8),
707
+ let music = try? JSONDecoder().decode(MusicModel.self, from: data) else {
708
+ return
709
+ }
710
+ // Update business state, play new music
711
+ // ... (e.g.: playMusic(music))
712
+ }
713
+ .store(in: &cancellables)
714
+ }
715
+ ```
716
+
717
+ ## Enriching the Live Streaming Scene
718
+
719
+ Once the basic live streaming functionality is in place, refer to the following guides to add interactive features to your live stream:
720
+ <table>
721
+ <tr>
722
+ <td rowspan="1" colSpan="1" >**Feature**</td>
723
+
724
+ <td rowspan="1" colSpan="1" >**Description**</td>
725
+
726
+ <td rowspan="1" colSpan="1" >**Store**</td>
727
+
728
+ <td rowspan="1" colSpan="1" >**Implementation Guide**</td>
729
+ </tr>
730
+
731
+ <tr>
732
+ <td rowspan="1" colSpan="1" >Enable Audience Audio/Video Co-hosting</td>
733
+
734
+ <td rowspan="1" colSpan="1" >Audience can apply to join the host and interact via real-time video.</td>
735
+
736
+ <td rowspan="1" colSpan="1" >[CoGuestStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/cogueststore)</td>
737
+
738
+ <td rowspan="1" colSpan="1" >[Implementation Guide](https://write.woa.com/document/194571607036174336)</td>
739
+ </tr>
740
+
741
+ <tr>
742
+ <td rowspan="1" colSpan="1" >Enable Host Cross-room PK</td>
743
+
744
+ <td rowspan="1" colSpan="1" >Hosts from different rooms can connect for interaction or PK.</td>
745
+
746
+ <td rowspan="1" colSpan="1" >[CoHostStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/cohoststore)</td>
747
+
748
+ <td rowspan="1" colSpan="1" >[Implementation Guide](https://write.woa.com/document/194571607415758848)</td>
749
+ </tr>
750
+
751
+ <tr>
752
+ <td rowspan="1" colSpan="1" >Add Bullet Chat Feature</td>
753
+
754
+ <td rowspan="1" colSpan="1" >Audience can send and receive real-time text messages in the live room.</td>
755
+
756
+ <td rowspan="1" colSpan="1" >[BarrageStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/barragestore)</td>
757
+
758
+ <td rowspan="1" colSpan="1" >[Implementation Guide](https://write.woa.com/document/194571607781711872)</td>
759
+ </tr>
760
+
761
+ <tr>
762
+ <td rowspan="1" colSpan="1" >Build a Gift Giving System</td>
763
+
764
+ <td rowspan="1" colSpan="1" >Audience can send virtual gifts to the host, increasing engagement and fun.</td>
765
+
766
+ <td rowspan="1" colSpan="1" >[GiftStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/giftstore)</td>
767
+
768
+ <td rowspan="1" colSpan="1" >[Implementation Guide](https://write.woa.com/document/194571602052481024)</td>
769
+ </tr>
770
+ </table>
771
+
772
+
773
+ ## API Documentation
774
+ <table>
775
+ <tr>
776
+ <td rowspan="1" colSpan="1" >**Store/Component**</td>
777
+
778
+ <td rowspan="1" colSpan="1" >**Description**</td>
779
+
780
+ <td rowspan="1" colSpan="1" >**API Reference**</td>
781
+ </tr>
782
+
783
+ <tr>
784
+ <td rowspan="1" colSpan="1" >LiveCoreView</td>
785
+
786
+ <td rowspan="1" colSpan="1" >Core view component for displaying and interacting with live video streams. Handles video rendering and view widgets, supports host streaming, audience co-hosting, host connections, and more.</td>
787
+
788
+ <td rowspan="1" colSpan="1" >[LiveCoreView](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/livecoreview/)</td>
789
+ </tr>
790
+
791
+ <tr>
792
+ <td rowspan="1" colSpan="1" >LiveListStore</td>
793
+
794
+ <td rowspan="1" colSpan="1" >Manages the full lifecycle of live rooms: create/join/leave/destroy rooms, query room list, modify live info (name, announcement, etc.), and listen to live status events (e.g., kicked out, ended).</td>
795
+
796
+ <td rowspan="1" colSpan="1" >[LiveListStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/liveliststore)</td>
797
+ </tr>
798
+
799
+ <tr>
800
+ <td rowspan="1" colSpan="1" >DeviceStore</td>
801
+
802
+ <td rowspan="1" colSpan="1" >Controls audio/video devices: microphone (on/off, volume), camera (on/off, switch, quality), screen sharing, and real-time device status monitoring.</td>
803
+
804
+ <td rowspan="1" colSpan="1" >[DeviceStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/devicestore)</td>
805
+ </tr>
806
+
807
+ <tr>
808
+ <td rowspan="1" colSpan="1" >CoGuestStore</td>
809
+
810
+ <td rowspan="1" colSpan="1" >Manages audience co-hosting: apply/invite/accept/reject co-host requests, member permission control (microphone/camera), and status synchronization.</td>
811
+
812
+ <td rowspan="1" colSpan="1" >[CoGuestStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/cogueststore)</td>
813
+ </tr>
814
+
815
+ <tr>
816
+ <td rowspan="1" colSpan="1" >CoHostStore</td>
817
+
818
+ <td rowspan="1" colSpan="1" >Handles host cross-room connections: supports multiple layout templates (dynamic grid, etc.), initiates/accepts/rejects connections, and manages co-host interactions.</td>
819
+
820
+ <td rowspan="1" colSpan="1" >[CoHostStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/cohoststore)</td>
821
+ </tr>
822
+
823
+ <tr>
824
+ <td rowspan="1" colSpan="1" >BattleStore</td>
825
+
826
+ <td rowspan="1" colSpan="1" >Manages host PK battles: initiate PK (set duration/opponent), manage PK status (start/end), synchronize scores, and listen for battle results.</td>
827
+
828
+ <td rowspan="1" colSpan="1" >[BattleStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/battlestore)</td>
829
+ </tr>
830
+
831
+ <tr>
832
+ <td rowspan="1" colSpan="1" >GiftStore</td>
833
+
834
+ <td rowspan="1" colSpan="1" >Handles gift interactions: get gift list, send/receive gifts, and listen for gift events (including sender and gift details).</td>
835
+
836
+ <td rowspan="1" colSpan="1" >[GiftStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/giftstore)</td>
837
+ </tr>
838
+
839
+ <tr>
840
+ <td rowspan="1" colSpan="1" >BarrageStore</td>
841
+
842
+ <td rowspan="1" colSpan="1" >Supports live chat: send text/custom danmaku, maintain danmaku list, and monitor danmaku status in real time.</td>
843
+
844
+ <td rowspan="1" colSpan="1" >[BarrageStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/barragestore)</td>
845
+ </tr>
846
+
847
+ <tr>
848
+ <td rowspan="1" colSpan="1" >LikeStore</td>
849
+
850
+ <td rowspan="1" colSpan="1" >Handles like interactions: send likes, listen for like events, and synchronize total like count.</td>
851
+
852
+ <td rowspan="1" colSpan="1" >[LikeStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/likestore)</td>
853
+ </tr>
854
+
855
+ <tr>
856
+ <td rowspan="1" colSpan="1" >LiveAudienceStore</td>
857
+
858
+ <td rowspan="1" colSpan="1" >Manages audience: get real-time audience list (ID/name/avatar), count audience, and listen for join/leave events.</td>
859
+
860
+ <td rowspan="1" colSpan="1" >[LiveAudienceStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/liveaudiencestore)</td>
861
+ </tr>
862
+
863
+ <tr>
864
+ <td rowspan="1" colSpan="1" >AudioEffectStore</td>
865
+
866
+ <td rowspan="1" colSpan="1" >Audio effects: voice change (child/male), reverb (KTV, etc.), ear return adjustment, and real-time effect switching.</td>
867
+
868
+ <td rowspan="1" colSpan="1" >[AudioEffectStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/audioeffectstore)</td>
869
+ </tr>
870
+
871
+ <tr>
872
+ <td rowspan="1" colSpan="1" >BaseBeautyStore</td>
873
+
874
+ <td rowspan="1" colSpan="1" >Basic beauty filters: adjust smoothing/whitening/rosiness (0-9), reset beauty status, and synchronize effect parameters.</td>
875
+
876
+ <td rowspan="1" colSpan="1" >[BaseBeautyStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/basebeautystore)</td>
877
+ </tr>
878
+ </table>
879
+
880
+
881
+ ## FAQs
882
+
883
+ ### Why is the screen black with no video after the host calls createLive or the audience calls joinLive?
884
+ - **Check **`setLiveID`: Ensure you have set the correct liveID for the LiveCoreView instance before calling start or join methods.
885
+
886
+ - **Check device permissions**: Ensure the app has system permissions for camera and microphone usage.
887
+
888
+ - **Check the host side**: Has the host called `DeviceStore.shared().openLocalCamera(true)`to enable the camera?
889
+
890
+ - **Check the network**: Ensure the device has a stable network connection.
891
+
892
+
893
+ ### After the host enables the camera, why is there a local video preview after starting the stream, but a black screen before starting?
894
+ - **Check the host side**: Make sure the host streaming view (`LiveCoreView`) has its `viewType` set to `PUSH_VIEW`.
895
+
896
+ - **Check the audience side**: Make sure the audience playback view (`LiveCoreView`) has its `viewType` set to `PLAY_VIEW`.
897
+
898
+
899
+ ### What restrictions and rules apply to `updateLiveMetaData`?
900
+
901
+ To maintain system stability and efficiency, metaData usage follows these rules:
902
+ - **Permissions**: Only hosts and administrators can call `updateLiveMetaData`. Regular audience members cannot.
903
+
904
+ - **Quantity and Size Limits:**
905
+
906
+ - Each room supports up to **10** keys.
907
+
908
+ - Each key can be up to **50 bytes**; each value up to **2KB**.
909
+
910
+ - The total size of all values in a room cannot exceed **16KB**.
911
+
912
+ - **Conflict Resolution**: The update mechanism is "last write wins". If multiple administrators modify the same key in quick succession, the last change takes effect. Avoid concurrent modifications to the same key in your business logic.
913
+
914
+
915
+ ### sync Fails to Copy Third-party Library Resources Due to Insufficient Permissions
916
+
917
+ For example, when integrating the SnapKit framework with Xcode, you may encounter the following build error:
918
+ ``` plaintext
919
+ rsync(xxxx):1:1: SnapKit.framework/SnapKit_Privacy.bundle/: mkpathat: Operation not permitted
920
+ ```
921
+
922
+ **Cause**
923
+
924
+ Xcode's user script sandboxing mechanism restricts the rsync script's write access to `SnapKit.framework` resource files during the build process, causing the `SnapKit_Privacy.bundle` in the framework to fail to copy properly.
925
+
926
+ Solution Steps
927
+ 1. Disable user script sandboxing. Open your Xcode project, go to **Build Settings**, search for User Script Sandboxing (or `ENABLE_USER_SCRIPT_SANDBOXING`), and change its value from YES to NO.
928
+
929
+ 2. Clean and rebuild the project. Run **Product → Clean** Build Folder to clear the project cache, then rebuild and run the project.
930
+
931
+