@tencent-rtc/mcp 1.3.2 → 1.3.3

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 (50) hide show
  1. package/package.json +1 -1
  2. package/resource/doc/livekit/live/android/live-audience-list.md +334 -0
  3. package/resource/doc/livekit/live/android/live-audio-effect.md +380 -0
  4. package/resource/doc/livekit/live/android/live-barrage.md +565 -0
  5. package/resource/doc/livekit/live/android/live-base-beauty.md +275 -0
  6. package/resource/doc/livekit/live/android/live-co-guest-interaction.md +629 -0
  7. package/resource/doc/livekit/live/android/live-gift.md +822 -0
  8. package/resource/doc/livekit/live/android/live-host-interaction.md +888 -0
  9. package/resource/doc/livekit/live/android/live-integration.md +972 -0
  10. package/resource/doc/livekit/live/android/live-live-list.md +575 -0
  11. package/resource/doc/livekit/live/android/workflow.md +189 -0
  12. package/tools/common/record-prompt.js +2 -2
  13. package/tools/common/record-prompt.js.map +1 -1
  14. package/tools/definitions/get_native_live_extra_features_def.js +87 -0
  15. package/tools/definitions/get_native_live_extra_features_def.js.map +1 -0
  16. package/tools/definitions/get_native_live_interaction_def.js +74 -0
  17. package/tools/definitions/get_native_live_interaction_def.js.map +1 -0
  18. package/tools/definitions/get_native_live_uikit_integration_def.js +49 -0
  19. package/tools/definitions/get_native_live_uikit_integration_def.js.map +1 -0
  20. package/tools/definitions/record_prompt_def.js +1 -1
  21. package/tools/definitions/record_prompt_def.js.map +1 -1
  22. package/tools/index.js +6 -0
  23. package/tools/index.js.map +1 -1
  24. package/tools/live/get-native-live-uikit-integration.js +101 -0
  25. package/tools/live/get-native-live-uikit-integration.js.map +1 -0
  26. package/tools/live/get-web-live-component-detail.js +1 -1
  27. package/tools/live/get-web-live-component-detail.js.map +1 -1
  28. package/tools/live/get-web-live-state-detail.js +1 -1
  29. package/tools/live/get-web-live-state-detail.js.map +1 -1
  30. package/tools/live/get-web-live-uikit-integration.js +6 -6
  31. package/tools/live/get-web-live-uikit-integration.js.map +1 -1
  32. package/tools/live/get_native_live_extra_features.js +105 -0
  33. package/tools/live/get_native_live_extra_features.js.map +1 -0
  34. package/tools/live/get_native_live_interaction.js +101 -0
  35. package/tools/live/get_native_live_interaction.js.map +1 -0
  36. package/utils/report-cls-client.js +1 -1
  37. package/utils/report-es-client.js +1 -1
  38. /package/resource/doc/livekit/{vue → live/vue}/components/barrage.md +0 -0
  39. /package/resource/doc/livekit/{vue → live/vue}/components/co-guest-panel.md +0 -0
  40. /package/resource/doc/livekit/{vue → live/vue}/components/live-audience-list.md +0 -0
  41. /package/resource/doc/livekit/{vue → live/vue}/components/live-scene-panel.md +0 -0
  42. /package/resource/doc/livekit/{vue → live/vue}/components/live-view.md +0 -0
  43. /package/resource/doc/livekit/{vue → live/vue}/components/stream-mixer.md +0 -0
  44. /package/resource/doc/livekit/{vue → live/vue}/faq.md +0 -0
  45. /package/resource/doc/livekit/{vue → live/vue}/live-list-integration.md +0 -0
  46. /package/resource/doc/livekit/{vue → live/vue}/live-player-desk-integration.md +0 -0
  47. /package/resource/doc/livekit/{vue → live/vue}/live-player-h5-integration.md +0 -0
  48. /package/resource/doc/livekit/{vue → live/vue}/live-pusher-integration.md +0 -0
  49. /package/resource/doc/livekit/{vue → live/vue}/states/live-state.md +0 -0
  50. /package/resource/doc/livekit/{vue → live/vue}/workflow.md +0 -0
@@ -0,0 +1,972 @@
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/100027182498/cb1167dec42d11f0b4a7525400454e06.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> - `CoreViewType.PUSH_VIEW` (host publishing view)<br> - `CoreViewType.PLAY_VIEW` (audience playback view)<br>- `setLiveId()`: Binds the live room ID for this view.<br>- `setVideoViewAdapter():` 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/100027182498/a3996d5cc44911f08c0e52540044a08e.png)
58
+
59
+
60
+ ### Step 2: Import AtomicXCore into Your Project
61
+
62
+ **Install the component**: Add the dependency `implementation 'com.tencent.atomicx:atomicxcore:latest`' to your `build.gradle` file, then perform a **Gradle****Sync**.
63
+ ``` gradle
64
+ dependencies {
65
+ implementation 'io.trtc.uikit:atomicx-core:latest.release'
66
+ api "io.trtc.uikit:rtc_room_engine:3.4.0.1306"
67
+ api "io.trtc.uikit:atomicx-core:3.4.0.1307"
68
+ api "com.tencent.liteav:LiteAVSDK_Professional:12.8.0.19279"
69
+ api "com.tencent.imsdk:imsdk-plus:8.7.7201"
70
+ // Other dependencies...
71
+ }
72
+ ```
73
+
74
+ ### Step 3: Implement Login Logic
75
+
76
+ Call `LoginStore.shared.login` in your project to complete login. **This is required before you can use any functionality in AtomicXCore**.
77
+
78
+ > **Note:**
79
+ >
80
+
81
+ > We recommend calling `LoginStore.shared.login` after your app's own user authentication is successful to ensure clear and consistent login logic.
82
+ >
83
+
84
+ ``` java
85
+ import android.os.Bundle
86
+ import androidx.appcompat.app.AppCompatActivity
87
+ import io.trtc.tuikit.atomicxcore.api.login.LoginStore
88
+ import io.trtc.tuikit.atomicxcore.api.CompletionHandler
89
+ import android.util.Log
90
+
91
+ class MainActivity : AppCompatActivity() {
92
+ override fun onCreate(savedInstanceState: Bundle?) {
93
+ super.onCreate(savedInstanceState)
94
+
95
+ LoginStore.shared.login(
96
+ this, // context
97
+ 1400000001, // Replace with your SDKAppID
98
+ "test_001", // Replace with your UserID
99
+ "xxxxxxxxxxx", // Replace with your UserSig
100
+ object : CompletionHandler {
101
+ override fun onSuccess() {
102
+ // Handle login success
103
+ Log.d("Login", "login success")
104
+ }
105
+
106
+ override fun onFailure(code: Int, desc: String) {
107
+ // Handle login failure
108
+ Log.e("Login", "login failed, code: $code, error: $desc")
109
+ }
110
+ }
111
+ )
112
+ }
113
+ }
114
+ ```
115
+
116
+ **Login API Parameter Description**
117
+ <table>
118
+ <tr>
119
+ <td rowspan="1" colSpan="1" >Parameter</td>
120
+
121
+ <td rowspan="1" colSpan="1" >Type</td>
122
+
123
+ <td rowspan="1" colSpan="1" >Description</td>
124
+ </tr>
125
+
126
+ <tr>
127
+ <td rowspan="1" colSpan="1" >SDKAppID</td>
128
+
129
+ <td rowspan="1" colSpan="1" >Int</td>
130
+
131
+ <td rowspan="1" colSpan="1" >Get this from [TRTC console > Application management](https://console.trtc.io/app).</td>
132
+ </tr>
133
+
134
+ <tr>
135
+ <td rowspan="1" colSpan="1" >UserID</td>
136
+
137
+ <td rowspan="1" colSpan="1" >String</td>
138
+
139
+ <td rowspan="1" colSpan="1" >The unique ID for the current user. Must contain only English letters, numbers, hyphens, and underscores.</td>
140
+ </tr>
141
+
142
+ <tr>
143
+ <td rowspan="1" colSpan="1" >userSig</td>
144
+
145
+ <td rowspan="1" colSpan="1" >String</td>
146
+
147
+ <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).<br>- For more information, see [How to Calculate and Use UserSig](https://write.woa.com/document/89644530319802368).</td>
148
+ </tr>
149
+ </table>
150
+
151
+
152
+ ## Building a Basic Live Room
153
+
154
+ ### Step 1: Implement Host Video Streaming
155
+
156
+ Follow these steps to quickly set up host video streaming:
157
+
158
+ ![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100027182498/a7cb5d4ac45311f0b4a7525400454e06.png)
159
+
160
+
161
+ > **Note:**
162
+ >
163
+
164
+ > For a complete implementation, refer to [VideoLiveAnchorActivity.kt](https://github.com/Tencent-RTC/TUIKit_Android/blob/main/live/tuilivekit/src/main/java/com/trtc/uikit/livekit/livestream/VideoLiveAnchorActivity.kt) in the open-source TUILiveKit project.
165
+ >
166
+
167
+ 1. **Initialize the Broadcaster Streaming View**
168
+
169
+
170
+ In your host `Activity`, create a LiveCoreView instance and set viewType to `PUSH_VIEW` (publishing view).
171
+
172
+ ``` java
173
+ import io.trtc.tuikit.atomicxcore.api.view.CoreViewType
174
+ import io.trtc.tuikit.atomicxcore.api.view.LiveCoreView
175
+ import android.os.Bundle
176
+ import androidx.appcompat.app.AppCompatActivity
177
+ import androidx.constraintlayout.widget.ConstraintLayout
178
+
179
+ class YourAnchorActivity : AppCompatActivity() {
180
+ private lateinit var coreView: LiveCoreView
181
+
182
+ override fun onCreate(savedInstanceState: Bundle?) {
183
+ super.onCreate(savedInstanceState)
184
+
185
+ coreView = LiveCoreView(this, viewType = CoreViewType.PUSH_VIEW)
186
+ coreView.setLiveID("test_live_001")
187
+
188
+ setupUI()
189
+ }
190
+
191
+ private fun setupUI() {
192
+ setContentView(R.layout.activity_anchor)
193
+
194
+ val container = findViewById<ConstraintLayout>(R.id.container)
195
+ container.addView(coreView)
196
+
197
+ val params = ConstraintLayout.LayoutParams(
198
+ ConstraintLayout.LayoutParams.MATCH_PARENT,
199
+ ConstraintLayout.LayoutParams.MATCH_PARENT
200
+ )
201
+ params.topMargin = 36
202
+ params.bottomMargin = 96
203
+ coreView.layoutParams = params
204
+ }
205
+ }
206
+ ```
207
+ 2. **Open Camera and Microphone**
208
+
209
+
210
+ Call the `openLocalCamera` and `openLocalMicrophone` methods of `DeviceStore` to enable the camera and microphone. **No additional action is required—LiveCoreView will automatically preview the current camera video stream**.
211
+
212
+ ``` java
213
+ import androidx.appcompat.app.AppCompatActivity
214
+ import android.os.Bundle
215
+ import io.trtc.tuikit.atomicxcore.api.device.DeviceStore
216
+
217
+ class YourAnchorActivity : AppCompatActivity() {
218
+ // ... other code ...
219
+
220
+ override fun onCreate(savedInstanceState: Bundle?) {
221
+ super.onCreate(savedInstanceState)
222
+ setupUI()
223
+ openDevices()
224
+ }
225
+
226
+ private fun openDevices() {
227
+ DeviceStore.shared().openLocalCamera(true, completion = null)
228
+ DeviceStore.shared().openLocalMicrophone(completion = null)
229
+ }
230
+ }
231
+ ```
232
+ 3. **Start Live Streaming**
233
+
234
+
235
+ Start the live stream by calling `createLive` on `LiveListStore`.
236
+
237
+ ``` java
238
+ import android.util.Log
239
+ import androidx.appcompat.app.AppCompatActivity
240
+ import io.trtc.tuikit.atomicxcore.api.live.LiveInfo
241
+ import io.trtc.tuikit.atomicxcore.api.live.LiveInfoCompletionHandler
242
+ import io.trtc.tuikit.atomicxcore.api.live.LiveListStore
243
+
244
+ class YourAnchorActivity : AppCompatActivity() {
245
+ // ... other code ...
246
+
247
+ private fun startLive() {
248
+ val liveInfo = LiveInfo().apply {
249
+ liveID = "test_live_001"
250
+ liveName = "test live"
251
+ seatLayoutTemplateID = 600 // Default: dynamic grid layout
252
+ keepOwnerOnSeat = true
253
+ }
254
+ LiveListStore.shared().createLive(liveInfo, object: LiveInfoCompletionHandler {
255
+ override fun onFailure(code: Int, desc: String) {
256
+ Log.e("Live", "startLive error: $desc")
257
+ }
258
+
259
+ override fun onSuccess(liveInfo: LiveInfo) {
260
+ Log.d("Live", "startLive success")
261
+ }
262
+ })
263
+ }
264
+ }
265
+ ```
266
+
267
+ `LiveInfo`** Parameter Description:**
268
+
269
+ <table>
270
+ <tr>
271
+ <td rowspan="1" colSpan="1" >**Parameter Name**</td>
272
+
273
+ <td rowspan="1" colSpan="1" >**Type**</td>
274
+
275
+ <td rowspan="1" colSpan="1" >**Required**</td>
276
+
277
+ <td rowspan="1" colSpan="1" >**Description**</td>
278
+ </tr>
279
+
280
+ <tr>
281
+ <td rowspan="1" colSpan="1" >`liveID`</td>
282
+
283
+ <td rowspan="1" colSpan="1" >`String`</td>
284
+
285
+ <td rowspan="1" colSpan="1" >Yes</td>
286
+
287
+ <td rowspan="1" colSpan="1" >Unique identifier for the live room.</td>
288
+ </tr>
289
+
290
+ <tr>
291
+ <td rowspan="1" colSpan="1" >`liveName`</td>
292
+
293
+ <td rowspan="1" colSpan="1" >`String`</td>
294
+
295
+ <td rowspan="1" colSpan="1" >No</td>
296
+
297
+ <td rowspan="1" colSpan="1" >Title of the live room.</td>
298
+ </tr>
299
+
300
+ <tr>
301
+ <td rowspan="1" colSpan="1" >`notice`</td>
302
+
303
+ <td rowspan="1" colSpan="1" >`String`</td>
304
+
305
+ <td rowspan="1" colSpan="1" >No</td>
306
+
307
+ <td rowspan="1" colSpan="1" >Announcement message for the live room.</td>
308
+ </tr>
309
+
310
+ <tr>
311
+ <td rowspan="1" colSpan="1" >`isMessageDisable`</td>
312
+
313
+ <td rowspan="1" colSpan="1" >`Boolean`</td>
314
+
315
+ <td rowspan="1" colSpan="1" >No</td>
316
+
317
+ <td rowspan="1" colSpan="1" >Disable chat (true = yes, false = no).</td>
318
+ </tr>
319
+
320
+ <tr>
321
+ <td rowspan="1" colSpan="1" >`isPublicVisible`</td>
322
+
323
+ <td rowspan="1" colSpan="1" >`Boolean`</td>
324
+
325
+ <td rowspan="1" colSpan="1" >No</td>
326
+
327
+ <td rowspan="1" colSpan="1" >Room is publicly visible (true = yes, false = no).</td>
328
+ </tr>
329
+
330
+ <tr>
331
+ <td rowspan="1" colSpan="1" >`isSeatEnabled`</td>
332
+
333
+ <td rowspan="1" colSpan="1" >`Boolean`</td>
334
+
335
+ <td rowspan="1" colSpan="1" >No</td>
336
+
337
+ <td rowspan="1" colSpan="1" >Enable seat (co-host) functionality (true = yes, false = no).</td>
338
+ </tr>
339
+
340
+ <tr>
341
+ <td rowspan="1" colSpan="1" >`keepOwnerOnSeat`</td>
342
+
343
+ <td rowspan="1" colSpan="1" >`Boolean`</td>
344
+
345
+ <td rowspan="1" colSpan="1" >No</td>
346
+
347
+ <td rowspan="1" colSpan="1" >Keep the owner on a seat.</td>
348
+ </tr>
349
+
350
+ <tr>
351
+ <td rowspan="1" colSpan="1" >`maxSeatCount`</td>
352
+
353
+ <td rowspan="1" colSpan="1" >`Int`</td>
354
+
355
+ <td rowspan="1" colSpan="1" >Yes</td>
356
+
357
+ <td rowspan="1" colSpan="1" >Maximum number of seats.</td>
358
+ </tr>
359
+
360
+ <tr>
361
+ <td rowspan="1" colSpan="1" >`seatMode`</td>
362
+
363
+ <td rowspan="1" colSpan="1" >[TakeSeatMode](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.live/-take-seat-mode/index.html)</td>
364
+
365
+ <td rowspan="1" colSpan="1" >No</td>
366
+
367
+ <td rowspan="1" colSpan="1" >Seat mode (FREE: free to take seat, APPLY: apply to take seat).</td>
368
+ </tr>
369
+
370
+ <tr>
371
+ <td rowspan="1" colSpan="1" >`seatLayoutTemplateID`</td>
372
+
373
+ <td rowspan="1" colSpan="1" >`Int`</td>
374
+
375
+ <td rowspan="1" colSpan="1" >Yes</td>
376
+
377
+ <td rowspan="1" colSpan="1" >Seat layout template ID.</td>
378
+ </tr>
379
+
380
+ <tr>
381
+ <td rowspan="1" colSpan="1" >`coverURL`</td>
382
+
383
+ <td rowspan="1" colSpan="1" >`String`</td>
384
+
385
+ <td rowspan="1" colSpan="1" >No</td>
386
+
387
+ <td rowspan="1" colSpan="1" >Cover image URL for the live room.</td>
388
+ </tr>
389
+
390
+ <tr>
391
+ <td rowspan="1" colSpan="1" >`backgroundURL`</td>
392
+
393
+ <td rowspan="1" colSpan="1" >`String`</td>
394
+
395
+ <td rowspan="1" colSpan="1" >No</td>
396
+
397
+ <td rowspan="1" colSpan="1" >Background image URL for the live room.</td>
398
+ </tr>
399
+
400
+ <tr>
401
+ <td rowspan="1" colSpan="1" >`categoryList`</td>
402
+
403
+ <td rowspan="1" colSpan="1" >`List`<br></td>
404
+
405
+ <td rowspan="1" colSpan="1" >No</td>
406
+
407
+ <td rowspan="1" colSpan="1" >List of category tags for the live room.</td>
408
+ </tr>
409
+
410
+ <tr>
411
+ <td rowspan="1" colSpan="1" >`activityStatus`</td>
412
+
413
+ <td rowspan="1" colSpan="1" >`Int`</td>
414
+
415
+ <td rowspan="1" colSpan="1" >No</td>
416
+
417
+ <td rowspan="1" colSpan="1" >Live activity status.</td>
418
+ </tr>
419
+
420
+ <tr>
421
+ <td rowspan="1" colSpan="1" >`isGiftEnabled`</td>
422
+
423
+ <td rowspan="1" colSpan="1" >`Boolean`</td>
424
+
425
+ <td rowspan="1" colSpan="1" >No</td>
426
+
427
+ <td rowspan="1" colSpan="1" >Whether to enable gift functionality (true: yes, false: no).</td>
428
+ </tr>
429
+ </table>
430
+
431
+ 4. **End Live Streaming**
432
+
433
+
434
+ When the live stream ends, call the `endLive` method of `LiveListStore`. The SDK will handle stopping the stream and destroying the room.
435
+
436
+ ``` java
437
+ import android.util.Log
438
+ import androidx.appcompat.app.AppCompatActivity
439
+ import com.tencent.cloud.tuikit.engine.extension.TUILiveListManager
440
+ import io.trtc.tuikit.atomicxcore.api.device.DeviceStore
441
+ import io.trtc.tuikit.atomicxcore.api.live.LiveListStore
442
+ import io.trtc.tuikit.atomicxcore.api.live.StopLiveCompletionHandler
443
+
444
+ class YourAnchorActivity : AppCompatActivity() {
445
+ // ... other code ...
446
+
447
+ private fun stopLive() {
448
+ LiveListStore.shared().endLive(object : StopLiveCompletionHandler {
449
+ override fun onSuccess(statisticsData: TUILiveListManager.LiveStatisticsData) {
450
+ Log.d("Live", "endLive success, duration: ${statisticsData.liveDuration}, totalViewers: ${statisticsData.totalViewers}")
451
+ }
452
+
453
+ override fun onFailure(code: Int, desc: String) {
454
+ Log.e("Live", "endLive error: $desc")
455
+ }
456
+ })
457
+ }
458
+
459
+ override fun onDestroy() {
460
+ super.onDestroy()
461
+ stopLive()
462
+ DeviceStore.shared().closeLocalCamera()
463
+ DeviceStore.shared().closeLocalMicrophone()
464
+ Log.d("Live", "YourAnchorActivity onDestroy")
465
+ }
466
+ }
467
+ ```
468
+
469
+ ### Step 2: Implement Audience Join and Watch
470
+
471
+ Follow these steps to enable audience viewing:
472
+
473
+ ![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100027182498/d1926a32c45311f0a0935254007c27c5.png)
474
+
475
+
476
+ > **Note:**
477
+ >
478
+
479
+ > For a complete reference implementation of audience viewing logic, see [VideoLiveAudienceActivity.kt](https://github.com/Tencent-RTC/TUIKit_Android/blob/main/live/tuilivekit/src/main/java/com/trtc/uikit/livekit/livestream/VideoLiveAudienceActivity.kt) in the open-source TUILiveKit project.
480
+ >
481
+
482
+ 1. **Add Audience Playback View**
483
+
484
+
485
+ In your audience `Activity`, create a `LiveCoreView` instance and set `viewType` to `PLAY_VIEW` (playback view).
486
+
487
+ ``` java
488
+ import io.trtc.tuikit.atomicxcore.api.view.CoreViewType
489
+ import io.trtc.tuikit.atomicxcore.api.view.LiveCoreView
490
+ import android.os.Bundle
491
+ import androidx.appcompat.app.AppCompatActivity
492
+ import androidx.constraintlayout.widget.ConstraintLayout
493
+
494
+ // YourAudienceActivity represents your audience viewing Activity
495
+ class YourAudienceActivity : AppCompatActivity() {
496
+
497
+ // 1. Initialize the audience playback view
498
+ private lateinit var coreView: LiveCoreView
499
+
500
+ override fun onCreate(savedInstanceState: Bundle?) {
501
+ super.onCreate(savedInstanceState)
502
+
503
+ // 2. Initialize the view
504
+ coreView = LiveCoreView(this, viewType = CoreViewType.PLAY_VIEW)
505
+ coreView.setLiveId("test_live_001")
506
+
507
+ // UI layout
508
+ setupUI()
509
+ }
510
+
511
+ private fun setupUI() {
512
+ setContentView(R.layout.activity_audience)
513
+
514
+ // 3. Add the playback view to your layout
515
+ val container = findViewById<ConstraintLayout>(R.id.container)
516
+ container.addView(coreView)
517
+
518
+ // Set layout parameters
519
+ val params = ConstraintLayout.LayoutParams(
520
+ ConstraintLayout.LayoutParams.MATCH_PARENT,
521
+ ConstraintLayout.LayoutParams.MATCH_PARENT
522
+ )
523
+ params.topMargin = 36
524
+ params.bottomMargin = 96
525
+ coreView.layoutParams = params
526
+ }
527
+ }
528
+ ```
529
+ 2. **Join the Live Room**
530
+
531
+
532
+ Call the `joinLive` method of `LiveListStore` to join the live stream. **No additional setup is required—LiveCoreView will automatically play the video stream.**
533
+
534
+ ``` java
535
+ import io.trtc.tuikit.atomicxcore.api.live.LiveInfo
536
+ import io.trtc.tuikit.atomicxcore.api.live.LiveInfoCompletionHandler
537
+ import io.trtc.tuikit.atomicxcore.api.live.LiveListStore
538
+ import android.os.Bundle
539
+ import androidx.appcompat.app.AppCompatActivity
540
+ import android.util.Log
541
+
542
+ // YourAudienceActivity represents your audience viewing Activity
543
+ class YourAudienceActivity : AppCompatActivity() {
544
+
545
+ // ... other code ...
546
+
547
+ override fun onCreate(savedInstanceState: Bundle?) {
548
+ super.onCreate(savedInstanceState)
549
+ setupUI()
550
+ // 1. Join the live room (liveID must match the host's)
551
+ LiveListStore.shared().joinLive(liveID, object : LiveInfoCompletionHandler {
552
+ override fun onFailure(code: Int, desc: String) {
553
+ Log.e("Live", "joinLive error: $desc")
554
+ }
555
+
556
+ override fun onSuccess(liveInfo: LiveInfo) {
557
+ Log.d("Live", "joinLive success")
558
+ }
559
+ })
560
+ }
561
+ }
562
+ ```
563
+ 3. **Exit the Live Room**
564
+
565
+
566
+ When the audience leaves, call the `leaveLive` method of `LiveListStore`. The SDK will automatically stop playback and exit the room.
567
+
568
+ ``` java
569
+ import io.trtc.tuikit.atomicxcore.api.live.LiveListStore
570
+ import io.trtc.tuikit.atomicxcore.api.CompletionHandler
571
+ import androidx.appcompat.app.AppCompatActivity
572
+ import android.util.Log
573
+
574
+ // YourAudienceActivity represents your audience viewing Activity
575
+ class YourAudienceActivity : AppCompatActivity() {
576
+
577
+ // ... other code ...
578
+
579
+ // Exit the live room
580
+ private fun leaveLive() {
581
+ LiveListStore.shared().leaveLive(object : CompletionHandler {
582
+ override fun onSuccess() {
583
+ Log.d("Live", "leaveLive success")
584
+ }
585
+
586
+ override fun onFailure(code: Int, desc: String) {
587
+ Log.e("Live", "leaveLive error: $desc")
588
+ }
589
+ })
590
+ }
591
+
592
+ // Always call leaveLive when Activity is destroyed
593
+ override fun onDestroy() {
594
+ super.onDestroy()
595
+ leaveLive()
596
+ Log.d("Live", "YourAudienceActivity onDestroy")
597
+ }
598
+ }
599
+ ```
600
+
601
+ ### Step 3: Listen for Live Events
602
+
603
+ After joining a live room, you should handle passive events such as the host ending the stream or the audience being removed for violations. If you do not listen for these events, the audience UI may remain in an invalid state, impacting user experience.
604
+
605
+ Implement the `LiveListListener` interface and register it with `LiveListStore`:
606
+ ``` java
607
+ import io.trtc.tuikit.atomicxcore.api.live.LiveEndedReason
608
+ import io.trtc.tuikit.atomicxcore.api.live.LiveKickedOutReason
609
+ import io.trtc.tuikit.atomicxcore.api.live.LiveListListener
610
+ import io.trtc.tuikit.atomicxcore.api.live.LiveListStore
611
+ import android.os.Bundle
612
+ import androidx.appcompat.app.AppCompatActivity
613
+ import android.util.Log
614
+
615
+ // YourAudienceActivity represents your audience viewing Activity
616
+ class YourAudienceActivity : AppCompatActivity() {
617
+
618
+ // ... (coreView, liveId, setupUI, joinLive, leaveLive, etc.) ...
619
+
620
+ // 2. Define a LiveListListener instance
621
+ private val liveListListener = object : LiveListListener() {
622
+ override fun onLiveEnded(liveID: String, reason: LiveEndedReason, message: String) {
623
+ // Listen for live stream end
624
+ Log.d("Live", "Live ended. liveID: $liveID, reason: $reason, message: $message")
625
+ // Handle exit logic, e.g., finish()
626
+ // finish()
627
+ }
628
+
629
+ override fun onKickedOutOfLive(liveID: String, reason: LiveKickedOutReason, message: String) {
630
+ // Listen for being kicked out of the live room
631
+ Log.d("Live", "Kicked out of live. liveID: $liveID, reason: $reason, message: $message")
632
+ // Handle exit logic
633
+ // finish()
634
+ }
635
+ }
636
+
637
+ override fun onCreate(savedInstanceState: Bundle?) {
638
+ super.onCreate(savedInstanceState)
639
+ setupUI()
640
+
641
+ // 3. Register the listener
642
+ LiveListStore.shared().addLiveListListener(liveListListener)
643
+
644
+ // 4. Join the live room
645
+ joinLive()
646
+ }
647
+
648
+ // ... joinLive() and leaveLive() methods ...
649
+
650
+ override fun onDestroy() {
651
+ super.onDestroy()
652
+ // 5. Remove the listener to prevent memory leaks
653
+ LiveListStore.shared().removeLiveListListener(liveListListener)
654
+ leaveLive()
655
+ Log.d("Live", "YourAudienceActivity onDestroy")
656
+ }
657
+ }
658
+ ```
659
+
660
+ ### Run and Test
661
+
662
+ 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/#789ad452-eaf1-433f-905d-fcb2945c1505).
663
+ <table>
664
+ <tr>
665
+ <td rowspan="1" colSpan="1" ></td>
666
+
667
+ <td rowspan="1" colSpan="1" >Dynamic Grid Layout</td>
668
+
669
+ <td rowspan="1" colSpan="1" >Floating Window Layout</td>
670
+
671
+ <td rowspan="1" colSpan="1" >Fixed Grid Layout</td>
672
+
673
+ <td rowspan="1" colSpan="1" >Fixed Window Layout</td>
674
+ </tr>
675
+
676
+ <tr>
677
+ <td rowspan="1" colSpan="1" >**Template ID**</td>
678
+
679
+ <td rowspan="1" colSpan="1" >600</td>
680
+
681
+ <td rowspan="1" colSpan="1" >601</td>
682
+
683
+ <td rowspan="1" colSpan="1" >800</td>
684
+
685
+ <td rowspan="1" colSpan="1" >801</td>
686
+ </tr>
687
+
688
+ <tr>
689
+ <td rowspan="1" colSpan="1" >**Description**</td>
690
+
691
+ <td rowspan="1" colSpan="1" >Default layout; grid size adjusts dynamically based on number of co-hosts.</td>
692
+
693
+ <td rowspan="1" colSpan="1" >Co-hosts are displayed as floating windows.</td>
694
+
695
+ <td rowspan="1" colSpan="1" >Fixed number of co-hosts; each occupies a fixed grid.</td>
696
+
697
+ <td rowspan="1" colSpan="1" >Fixed number of co-hosts; guests are displayed as fixed windows.</td>
698
+ </tr>
699
+
700
+ <tr>
701
+ <td rowspan="1" colSpan="1" >**Example**</td>
702
+
703
+ <td rowspan="1" colSpan="1" >![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100027182498/394f3851a5b511f09936525400e889b2.png)</td>
704
+
705
+ <td rowspan="1" colSpan="1" >![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100027182498/395e0e3da5b511f0930a5254007c27c5.png)</td>
706
+
707
+ <td rowspan="1" colSpan="1" >![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100027182498/39427c02a5b511f0b1565254001c06ec.png)</td>
708
+
709
+ <td rowspan="1" colSpan="1" >![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100027182498/3942f453a5b511f091df5254005ef0f7.png)</td>
710
+ </tr>
711
+ </table>
712
+
713
+
714
+ ## Advanced Features
715
+
716
+ ### Synchronizing Custom State in Live Streaming Room
717
+
718
+ In Live Streaming Room, hosts may need to synchronize custom information with all participants, such as the current room topic or background music. The `metaData` feature of `LiveListStore` supports this use case.
719
+
720
+ #### Implementation
721
+
722
+ On the host side, set custom information using the `updateLiveMetaData` API. `AtomicXCore` synchronizes these changes in real time to all participants. 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 logic.
723
+
724
+ #### Example Code
725
+ ``` kotlin
726
+ import io.trtc.tuikit.atomicxcore.api.LiveListStore
727
+ import io.trtc.tuikit.atomicxcore.api.CompletionHandler
728
+ import com.google.gson.Gson
729
+ import io.trtc.tuikit.atomicxcore.api.MetaDataCompletionHandler
730
+ import io.trtc.tuikit.atomicxcore.api.LiveListStore
731
+
732
+ // 1. Define a background music model (using data class)
733
+ data class MusicModel(
734
+ val musicId: String,
735
+ val musicName: String
736
+ )
737
+
738
+ // 2. Host side: Add a method to push background music in your Host business logic
739
+ fun updateBackgroundMusic(music: MusicModel) {
740
+ val gson = Gson()
741
+ val jsonString = gson.toJson(music) ?: ""
742
+
743
+ // The metaData to be updated
744
+ val metaData = hashMapOf("music_info" to jsonString)
745
+
746
+ // Update metaData
747
+ LiveListStore.shared()
748
+ .updateLiveMetaData(
749
+ metaData,
750
+ object : CompletionHandler {
751
+ override fun onSuccess() {
752
+ print("Background music ${music.musicName} pushed successfully")
753
+ }
754
+
755
+ override fun onFailure(code: Int, desc: String) {
756
+ print("Failed to push background music: $desc")
757
+ }
758
+ }
759
+ )
760
+ }
761
+
762
+ // 3. Audience side: Add a method to listen for background music changes in your Audience business logic
763
+ private fun subscribeToDataUpdates() {
764
+ CoroutineScope(Dispatchers.Main).launch {
765
+ LiveListStore.shared()
766
+ .liveState
767
+ .currentLive
768
+ .map { it.metaData }
769
+ .collect {
770
+ val musicInfo = it["music_info"]
771
+ // Refresh business state, e.g., play new background music
772
+ }
773
+ }
774
+ }
775
+ ```
776
+
777
+ ## Enriching the Live Streaming Scene
778
+
779
+ Once the basic live streaming functionality is in place, refer to the following guides to add interactive features to your live stream:
780
+ <table>
781
+ <tr>
782
+ <td rowspan="1" colSpan="1" >**Feature**</td>
783
+
784
+ <td rowspan="1" colSpan="1" >**Description**</td>
785
+
786
+ <td rowspan="1" colSpan="1" >**Store**</td>
787
+
788
+ <td rowspan="1" colSpan="1" >**Implementation Guide**</td>
789
+ </tr>
790
+
791
+ <tr>
792
+ <td rowspan="1" colSpan="1" >**Enable Audience Audio/Video Co-hosting**</td>
793
+
794
+ <td rowspan="1" colSpan="1" >Audience can apply to join the host on stage for real-time video interaction.</td>
795
+
796
+ <td rowspan="1" colSpan="1" >[CoGuestStore](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.live/-co-guest-store/index.html)</td>
797
+
798
+ <td rowspan="1" colSpan="1" >[Implementation Guide](https://write.woa.com/document/194571606970114048)</td>
799
+ </tr>
800
+
801
+ <tr>
802
+ <td rowspan="1" colSpan="1" >**Enable Host Cross-room PK**</td>
803
+
804
+ <td rowspan="1" colSpan="1" >Hosts from different rooms can connect for interaction or PK.</td>
805
+
806
+ <td rowspan="1" colSpan="1" >[CoHostStore](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.live/-co-host-store/index.html)<br>[BattleStore](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.live/-battle-store/index.html)</td>
807
+
808
+ <td rowspan="1" colSpan="1" >[Implementation Guide](https://write.woa.com/document/194571607349698560)</td>
809
+ </tr>
810
+
811
+ <tr>
812
+ <td rowspan="1" colSpan="1" >**Add Bullet Chat Feature**</td>
813
+
814
+ <td rowspan="1" colSpan="1" >Audience can send and receive real-time text messages in the live room.</td>
815
+
816
+ <td rowspan="1" colSpan="1" >[BarrageStore](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.barrage/-barrage-store/index.html)</td>
817
+
818
+ <td rowspan="1" colSpan="1" >[Implementation Guide](https://write.woa.com/document/194571607715651584)</td>
819
+ </tr>
820
+
821
+ <tr>
822
+ <td rowspan="1" colSpan="1" >**Build a Gift Giving System**</td>
823
+
824
+ <td rowspan="1" colSpan="1" >Audience can send virtual gifts to the host, increasing engagement and fun.</td>
825
+
826
+ <td rowspan="1" colSpan="1" >[GiftStore](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.gift/-gift-store/index.html)</td>
827
+
828
+ <td rowspan="1" colSpan="1" >[Implementation Guide](https://write.woa.com/document/194571602045140992)</td>
829
+ </tr>
830
+ </table>
831
+
832
+
833
+ ## API Documentation
834
+ <table>
835
+ <tr>
836
+ <td rowspan="1" colSpan="1" >**Store/Component**</td>
837
+
838
+ <td rowspan="1" colSpan="1" >**Description**</td>
839
+
840
+ <td rowspan="1" colSpan="1" >**API Reference**</td>
841
+ </tr>
842
+
843
+ <tr>
844
+ <td rowspan="1" colSpan="1" >LiveCoreView</td>
845
+
846
+ <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>
847
+
848
+ <td rowspan="1" colSpan="1" >[API Documentation](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)</td>
849
+ </tr>
850
+
851
+ <tr>
852
+ <td rowspan="1" colSpan="1" >LiveListStore</td>
853
+
854
+ <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>
855
+
856
+ <td rowspan="1" colSpan="1" >[API Documentation](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.live/-live-list-store/index.html)</td>
857
+ </tr>
858
+
859
+ <tr>
860
+ <td rowspan="1" colSpan="1" >DeviceStore</td>
861
+
862
+ <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>
863
+
864
+ <td rowspan="1" colSpan="1" >[API Documentation](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.device/-device-store/index.html)</td>
865
+ </tr>
866
+
867
+ <tr>
868
+ <td rowspan="1" colSpan="1" >CoGuestStore</td>
869
+
870
+ <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>
871
+
872
+ <td rowspan="1" colSpan="1" >[API Documentation](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.live/-co-guest-store/index.html)</td>
873
+ </tr>
874
+
875
+ <tr>
876
+ <td rowspan="1" colSpan="1" >CoHostStore</td>
877
+
878
+ <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>
879
+
880
+ <td rowspan="1" colSpan="1" >[API Documentation](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.live/-co-host-store/index.html)</td>
881
+ </tr>
882
+
883
+ <tr>
884
+ <td rowspan="1" colSpan="1" >BattleStore</td>
885
+
886
+ <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>
887
+
888
+ <td rowspan="1" colSpan="1" >[API Documentation](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.live/-battle-store/index.html)</td>
889
+ </tr>
890
+
891
+ <tr>
892
+ <td rowspan="1" colSpan="1" >GiftStore</td>
893
+
894
+ <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>
895
+
896
+ <td rowspan="1" colSpan="1" >[API Documentation](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.gift/-gift-store/index.html)</td>
897
+ </tr>
898
+
899
+ <tr>
900
+ <td rowspan="1" colSpan="1" >BarrageStore</td>
901
+
902
+ <td rowspan="1" colSpan="1" >Supports live chat: send text/custom danmaku, maintain danmaku list, and monitor danmaku status in real time.</td>
903
+
904
+ <td rowspan="1" colSpan="1" >[API Documentation](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.barrage/-barrage-store/index.html)</td>
905
+ </tr>
906
+
907
+ <tr>
908
+ <td rowspan="1" colSpan="1" >LikeStore</td>
909
+
910
+ <td rowspan="1" colSpan="1" >Handles like interactions: send likes, listen for like events, and synchronize total like count.</td>
911
+
912
+ <td rowspan="1" colSpan="1" >[API Documentation](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.live/-like-store/index.html)</td>
913
+ </tr>
914
+
915
+ <tr>
916
+ <td rowspan="1" colSpan="1" >LiveAudienceStore</td>
917
+
918
+ <td rowspan="1" colSpan="1" >Manages audience: get real-time audience list (ID/name/avatar), count audience, and listen for join/leave events.</td>
919
+
920
+ <td rowspan="1" colSpan="1" >[API Documentation](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.live/-live-audience-store/index.html)</td>
921
+ </tr>
922
+
923
+ <tr>
924
+ <td rowspan="1" colSpan="1" >AudioEffectStore</td>
925
+
926
+ <td rowspan="1" colSpan="1" >Audio effects: voice change (child/male), reverb (KTV, etc.), ear return adjustment, and real-time effect switching.</td>
927
+
928
+ <td rowspan="1" colSpan="1" >[API Documentation](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.device/-audio-effect-store/index.html)</td>
929
+ </tr>
930
+
931
+ <tr>
932
+ <td rowspan="1" colSpan="1" >BaseBeautyStore</td>
933
+
934
+ <td rowspan="1" colSpan="1" >Basic beauty filters: adjust smoothing/whitening/rosiness (0-9), reset beauty status, and synchronize effect parameters.</td>
935
+
936
+ <td rowspan="1" colSpan="1" >[API Documentation](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.device/-base-beauty-store/index.html)</td>
937
+ </tr>
938
+ </table>
939
+
940
+
941
+ ## FAQs
942
+
943
+ ### Why is the screen black with no video after the host calls createLive or the audience calls joinLive?
944
+ - **Check setLiveID**: Ensure you have set the correct liveID for the LiveCoreView instance before calling start or join methods.
945
+
946
+ - **Check device permissions**: Ensure the app has system permissions for camera and microphone usage.
947
+
948
+ - **Check the host side**: Has the host called `DeviceStore.shared().openLocalCamera(true)`to enable the camera?
949
+
950
+ - **Check the network**: Ensure the device has a stable network connection.
951
+
952
+
953
+ ### After the host enables the camera, why is there a local video preview after starting the stream, but a black screen before starting?
954
+ - **Check the host side**: Make sure the host streaming view (LiveCoreView) has its `viewType` set to `PUSH_VIEW`.
955
+
956
+ - **Check the audience side**: Make sure the audience playback view (LiveCoreView) has its `viewType` set to `PLAY_VIEW`.
957
+
958
+
959
+ ### What restrictions and rules apply to `updateLiveMetaData`?
960
+
961
+ To maintain system stability and efficiency, metaData usage follows these rules:
962
+ - **Permissions**: Only hosts and administrators can call `updateLiveMetaData`. Regular audience members cannot.
963
+
964
+ - **Quantity and Size Limits:**
965
+
966
+ - Each room supports up to **10** keys.
967
+
968
+ - Each key can be up to **50 bytes**; each value up to **2KB**.
969
+
970
+ - The total size of all values in a room cannot exceed **16KB**.
971
+
972
+ - **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.