@tencentcloud/sdk-mcp 1.3.4 → 1.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +4 -4
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/resource/doc/chatuikit/android/features/theme.md +363 -0
- package/resource/doc/chatuikit/{android/client_api_android.md → faq/android_sdk/client-api.md} +0 -1
- package/resource/doc/chatuikit/faq/{native_sdk/faq.md → common/product.md} +8 -0
- package/resource/doc/chatuikit/faq/flutter_sdk/faq.md +54 -0
- package/resource/doc/chatuikit/faq/web_sdk/faq.md +1 -1
- package/resource/doc/chatuikit/flutter/features/theme.md +379 -0
- package/resource/doc/chatuikit/flutter/workflow.md +816 -0
- package/resource/doc/chatuikit/iOS/features/theme.md +416 -0
- package/resource/doc/chatuikit/iOS/workflow.md +0 -0
- package/resource/doc/chatuikit/react/components/chat-setting.md +124 -0
- package/resource/doc/chatuikit/react/components/contact-list.md +1331 -0
- package/resource/doc/chatuikit/react/components/search.md +885 -0
- package/resource/doc/chatuikit/vue/components/chat-setting.md +88 -0
- package/resource/doc/chatuikit/vue/components/contact-list.md +679 -0
- package/resource/doc/chatuikit/vue/components/search.md +1384 -0
- package/resource/doc/livekit/live/android/workflow.md +137 -4
- package/resource/doc/livekit/live/flutter/live-audience-list.md +337 -0
- package/resource/doc/livekit/live/flutter/live-audio-effect.md +739 -0
- package/resource/doc/livekit/live/flutter/live-barrage.md +578 -0
- package/resource/doc/livekit/live/flutter/live-base-beauty.md +484 -0
- package/resource/doc/livekit/live/flutter/live-co-guest-interaction.md +606 -0
- package/resource/doc/livekit/live/flutter/live-gift.md +812 -0
- package/resource/doc/livekit/live/flutter/live-host-interaction.md +1113 -0
- package/resource/doc/livekit/live/flutter/live-integration.md +1029 -0
- package/resource/doc/livekit/live/flutter/live-live-list.md +861 -0
- package/resource/doc/livekit/live/ios/live-audience-list.md +335 -0
- package/resource/doc/livekit/live/ios/live-audio-effect.md +373 -0
- package/resource/doc/livekit/live/ios/live-barrage.md +529 -0
- package/resource/doc/livekit/live/ios/live-base-beauty.md +237 -0
- package/resource/doc/livekit/live/ios/live-co-guest-interaction.md +483 -0
- package/resource/doc/livekit/live/ios/live-gift.md +785 -0
- package/resource/doc/livekit/live/ios/live-host-interaction.md +743 -0
- package/resource/doc/livekit/live/ios/live-integration.md +822 -0
- package/resource/doc/livekit/live/ios/live-live-list.md +535 -0
- package/resource/doc/livekit/live/ios/workflow.md +352 -0
- package/resource/doc/rtcengine/faq/web/web.md +2 -2
- package/resource/doc/rtcengine/web/how_to_integrated_web_sdk.md +2 -2
- package/resource/doc/rtcengine/web/plugin/20-advanced-customized-capture-rendering.md +84 -0
- package/resource/doc/rtcengine/web/plugin/21-advanced-auto-play-policy.md +86 -0
- package/resource/doc/rtcengine/web/plugin/22-advanced-audio-mixer.md +220 -0
- package/resource/doc/rtcengine/web/plugin/23-advanced-support-detection.md +217 -0
- package/resource/doc/rtcengine/web/plugin/24-advanced-network-quality.md +137 -0
- package/resource/doc/rtcengine/web/plugin/25-advanced-device-change.md +97 -0
- package/resource/doc/rtcengine/web/plugin/26-advanced-publish-cdn-stream.md +453 -0
- package/resource/doc/rtcengine/web/plugin/27-advanced-small-stream.md +180 -0
- package/resource/doc/rtcengine/web/plugin/28-advanced-beauty.md +349 -0
- package/resource/doc/rtcengine/web/plugin/29-advanced-water-mark.md +149 -0
- package/resource/doc/rtcengine/web/plugin/30-advanced-cross-room-link.md +96 -0
- package/resource/doc/rtcengine/web/plugin/31-advanced-plugins-overview.md +405 -0
- package/resource/doc/rtcengine/web/plugin/34-advanced-proxy.md +244 -0
- package/resource/doc/rtcengine/web/plugin/35-advanced-ai-denoiser.md +84 -0
- package/resource/doc/rtcengine/web/plugin/36-advanced-virtual-background.md +202 -0
- package/resource/doc/rtcengine/web/plugin/37-advanced-voice-changer.md +98 -0
- package/resource/doc/rtcengine/web/plugin/38-advanced-basic-beauty.md +95 -0
- package/resource/doc/rtcengine/web/plugin/39-advanced-video-decoder.md +33 -0
- package/resource/doc/rtcengine/web/plugin/40-advanced-video-mixer.md +380 -0
- package/resource/doc/rtcengine/web/plugin/41-advanced-small-stream-auto-switcher.md +91 -0
- package/resource/doc/rtcengine/web/plugin/42-advanced-realtime-transcriber.md +314 -0
- package/resource/doc/rtcengine/web/plugin/43-advanced-face-detection.md +180 -0
- package/resource/doc/tuicallkit/android/workflow.md +0 -0
- package/resource/doc/tuicallkit/flutter/integration.md +510 -0
- package/resource/doc/tuicallkit/flutter/workflow.md +331 -0
- package/tools/call/get-native-call-integration.js +27 -11
- package/tools/call/get-native-call-integration.js.map +1 -1
- package/tools/chat/get-native-chat-feature-detail.js +30 -0
- package/tools/chat/get-native-chat-feature-detail.js.map +1 -0
- package/tools/chat/get-native-chat-integration.js +30 -12
- package/tools/chat/get-native-chat-integration.js.map +1 -1
- package/tools/common/get-faq.js +2 -4
- package/tools/common/get-faq.js.map +1 -1
- package/tools/definitions/get_native_call_uikit_integration_def.js +16 -6
- package/tools/definitions/get_native_call_uikit_integration_def.js.map +1 -1
- package/tools/definitions/get_native_chat_feature_detail_def.js +32 -0
- package/tools/definitions/get_native_chat_feature_detail_def.js.map +1 -0
- package/tools/definitions/get_native_chat_uikit_integration_def.js +18 -6
- package/tools/definitions/get_native_chat_uikit_integration_def.js.map +1 -1
- package/tools/definitions/{get_native_live_extra_features_def.js → get_native_live_uikit_extra_features_def.js} +3 -3
- package/tools/definitions/get_native_live_uikit_extra_features_def.js.map +1 -0
- package/tools/definitions/{get_native_live_interaction_def.js → get_native_live_uikit_interaction_def.js} +3 -3
- package/tools/definitions/get_native_live_uikit_interaction_def.js.map +1 -0
- package/tools/definitions/get_web_chat_uikit_component_detail_def.js +46 -7
- package/tools/definitions/get_web_chat_uikit_component_detail_def.js.map +1 -1
- package/tools/index.js +6 -4
- package/tools/index.js.map +1 -1
- package/tools/live/{get_native_live_extra_features.js → get_native_live_uikit_extra_features.js} +4 -4
- package/tools/live/get_native_live_uikit_extra_features.js.map +1 -0
- package/tools/live/{get_native_live_interaction.js → get_native_live_uikit_interaction.js} +4 -4
- package/tools/live/get_native_live_uikit_interaction.js.map +1 -0
- package/tools/rtcengine/get-trtc-web-sdk-faq.js +1 -1
- package/tools/rtcengine/get-trtc-web-sdk-plugin.js +45 -0
- package/tools/rtcengine/get-trtc-web-sdk-plugin.js.map +1 -0
- package/utils/handle-component-name.js +0 -16
- package/utils/handle-component-name.js.map +1 -1
- package/utils/report-cls-client.js +1 -1
- package/utils/report-es-client.js +1 -1
- package/resource/doc/chatuikit/android/integrate_tuichat_only_android.md +0 -382
- package/resource/doc/chatuikit/android/ui_api_android.md +0 -418
- package/resource/doc/chatuikit/iOS/integrate_tuichat_only_iOS.md +0 -993
- package/resource/doc/chatuikit/iOS/ui_api_iOS.md +0 -526
- package/resource/doc/tuicallkit/flutter/how_to_integrated_flutter_callkit.md +0 -226
- package/resource/doc/tuicallkit/flutter/how_to_run_flutter_callkit_demo.md +0 -101
- package/resource/doc/tuicallkit/iOS/how_to_run_iOS_callkit_demo.md +0 -98
- package/tools/definitions/get_native_live_extra_features_def.js.map +0 -1
- package/tools/definitions/get_native_live_interaction_def.js.map +0 -1
- package/tools/live/get_native_live_extra_features.js.map +0 -1
- package/tools/live/get_native_live_interaction.js.map +0 -1
- /package/resource/doc/chatuikit/android/{integrate_tuikit_android.md → integration.md} +0 -0
- /package/resource/doc/{tuicallkit/android/.gitkeep → chatuikit/android/workflow.md} +0 -0
- /package/resource/doc/chatuikit/{flutter/client_api_Flutter.md → faq/flutter_sdk/client-api.md} +0 -0
- /package/resource/doc/chatuikit/{iOS/client_api_iOS.md → faq/ios_sdk/client-api.md} +0 -0
- /package/resource/doc/chatuikit/flutter/{integrate_tuikit_Flutter.md → integration.md} +0 -0
- /package/resource/doc/chatuikit/iOS/{integrate_tuikit_iOS.md → integration.md} +0 -0
- /package/resource/doc/chatuikit/react/components/{chatheader.md → chat-header.md} +0 -0
- /package/resource/doc/chatuikit/vue/components/{chatheader.md → chat-header.md} +0 -0
- /package/resource/doc/tuicallkit/android/{how_to_integrated_android_callkit.md → integration.md} +0 -0
- /package/resource/doc/tuicallkit/{android/api_TUICallObserver.md → faq/android_sdk/call-observer-api.md} +0 -0
- /package/resource/doc/tuicallkit/{android/api_TUICallKit.md → faq/android_sdk/callkit-api.md} +0 -0
- /package/resource/doc/tuicallkit/{flutter/api_TUICallDefine.md → faq/flutter_sdk/call-define-api.md} +0 -0
- /package/resource/doc/tuicallkit/{flutter/api_TUICallObserver.md → faq/flutter_sdk/call-observer-api.md} +0 -0
- /package/resource/doc/tuicallkit/{flutter/api_TUICallKit.md → faq/flutter_sdk/callkit-api.md} +0 -0
- /package/resource/doc/tuicallkit/{iOS/api_TUICallObserver.md → faq/ios_sdk/call-observer-api.md} +0 -0
- /package/resource/doc/tuicallkit/{iOS/api_TUICallKit.md → faq/ios_sdk/callkit-api.md} +0 -0
- /package/resource/doc/tuicallkit/iOS/{how_to_integrated_iOS_callkit.md → integration.md} +0 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
# Native Live AtomicXCore 代码生成工作流指令 (iOS)
|
|
2
|
+
|
|
3
|
+
## 🚨 核心原则(最高优先级)
|
|
4
|
+
|
|
5
|
+
**Agent 必须确保生成的代码可以成功编译运行,严禁将无法编译的代码交付给用户!**
|
|
6
|
+
|
|
7
|
+
### ⚠️ 强制编译验证(必须执行,不可省略)
|
|
8
|
+
|
|
9
|
+
**🚫 严禁行为**:
|
|
10
|
+
- ❌ 只用 `read_lints` 检查就认为代码正确
|
|
11
|
+
- ❌ 用 `grep` 过滤编译输出(会导致命令被跳过)
|
|
12
|
+
- ❌ 跳过编译验证直接交付代码
|
|
13
|
+
|
|
14
|
+
**✅ 唯一正确的验证方式**:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# 步骤 1: 安装依赖(如需要)
|
|
18
|
+
cd <项目目录> && pod install
|
|
19
|
+
|
|
20
|
+
# 步骤 2: 编译验证(使用 tail 限制输出)
|
|
21
|
+
cd <项目目录> && xcodebuild build \
|
|
22
|
+
-scheme <SchemeName> \
|
|
23
|
+
-workspace <WorkspaceName>.xcworkspace \
|
|
24
|
+
-destination 'generic/platform=iOS' \
|
|
25
|
+
CODE_SIGNING_ALLOWED=NO 2>&1 | tail -150
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
**判断标准**:
|
|
29
|
+
- ✅ 输出包含 `BUILD SUCCEEDED` → 编译通过,可交付
|
|
30
|
+
- ❌ 输出包含 `BUILD FAILED` 或 `error:` → 必须修复后重新编译
|
|
31
|
+
|
|
32
|
+
**常见错误与修复**:
|
|
33
|
+
| 错误关键字 | 原因 | 修复方式 |
|
|
34
|
+
|-----------|------|---------|
|
|
35
|
+
| `No such module 'xxx'` | Pod 依赖缺失 | 添加到 Podfile 后执行 `pod install` |
|
|
36
|
+
| `Cannot find 'xxx' in scope` | Import 缺失 | 添加 `import xxx` |
|
|
37
|
+
| `Use of unresolved identifier` | API 名称错误 | 查阅文档确认正确 API |
|
|
38
|
+
| `NSCameraUsageDescription` | Info.plist 权限缺失 | 添加权限描述 |
|
|
39
|
+
|
|
40
|
+
**验证循环(必须遵守)**:
|
|
41
|
+
```
|
|
42
|
+
执行编译 → 失败 → 分析错误 → 修复代码 → 重新执行编译 → ... → BUILD SUCCEEDED → 交付
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 📋 指令目的与架构
|
|
48
|
+
|
|
49
|
+
为 Agent 提供实现 Native (iOS) Live AtomicXCore 核心功能的**代码生成蓝图**。
|
|
50
|
+
|
|
51
|
+
**核心架构**:
|
|
52
|
+
* **容器**:`LiveCoreView` (视图层)
|
|
53
|
+
* **状态**:`Store` (数据驱动)
|
|
54
|
+
* **事件**:`Publisher` (Combine 订阅)
|
|
55
|
+
|
|
56
|
+
**功能依赖逻辑(重要)**:
|
|
57
|
+
1. **基础先行**:必须先使用本工具(`get_native_live_uikit_integration`)完成基础直播(开播/观看/列表)。
|
|
58
|
+
2. **互动叠加**:如果用户需求包含"连麦"、"PK"、"观众列表",必须**在基础功能完成后**,再调用互动工具(`get_native_live_uikit_interaction`)。
|
|
59
|
+
3. **空项目处理**:若用户在空项目中直接请求互动功能,Agent **必须先实现基础功能**,再添加互动能力。
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## ⚙️ 自动化工作流步骤(必须创建为 TODO 任务)
|
|
64
|
+
|
|
65
|
+
**🚨 Agent 必须将以下步骤创建为 TODO 任务列表,逐一完成并打勾:**
|
|
66
|
+
|
|
67
|
+
### 步骤 1: 前置准备
|
|
68
|
+
1. **生成凭证**:调用 `get_usersig` 工具生成测试凭证。
|
|
69
|
+
* 主播: `anchor001`, `anchor002`, `anchor003`
|
|
70
|
+
* 观众: `user001`, `user002`, `user003`
|
|
71
|
+
2. **环境检查**:检查 `Podfile`,若缺失以下依赖则自动添加:
|
|
72
|
+
```ruby
|
|
73
|
+
pod 'AtomicXCore'
|
|
74
|
+
```
|
|
75
|
+
3. **权限注入**:在 `Info.plist` 中添加摄像头、麦克风权限描述:
|
|
76
|
+
```xml
|
|
77
|
+
<key>NSCameraUsageDescription</key>
|
|
78
|
+
<string>需要访问您的相机权限,开启后录制的视频才会有画面</string>
|
|
79
|
+
<key>NSMicrophoneUsageDescription</key>
|
|
80
|
+
<string>需要访问您的麦克风权限,开启后录制的视频才会有声音</string>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 步骤 2: 代码生成
|
|
84
|
+
**必须优先且唯一**使用本工具返回的**实时文档内容**生成代码。
|
|
85
|
+
* **仅主播**:生成 `AnchorViewController`
|
|
86
|
+
* **仅观众**:生成 `AudienceViewController`
|
|
87
|
+
* **主播+观众**:生成 `MainViewController` (入口选择) + `AnchorViewController` + `AudienceViewController`
|
|
88
|
+
|
|
89
|
+
### 步骤 3: 🚨 编译验证(强制执行,不可跳过)
|
|
90
|
+
**此步骤必须作为独立 TODO 任务执行,不能省略或合并!**
|
|
91
|
+
|
|
92
|
+
**执行命令**:
|
|
93
|
+
```bash
|
|
94
|
+
cd <项目目录>/ios && pod install && \
|
|
95
|
+
xcodebuild build -scheme <SchemeName> -workspace <WorkspaceName>.xcworkspace \
|
|
96
|
+
-destination 'platform=iOS Simulator,name=iPhone 16' \
|
|
97
|
+
CODE_SIGNING_ALLOWED=NO 2>&1 | tail -150
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**判断与处理**:
|
|
101
|
+
* 输出包含 **BUILD SUCCEEDED** → 进入步骤 4
|
|
102
|
+
* 输出包含 **BUILD FAILED** 或 **error:** → 分析错误 → 修复代码 → **重新执行本命令**,循环直到成功
|
|
103
|
+
|
|
104
|
+
### 步骤 4: 交付结果
|
|
105
|
+
确认编译通过后,向用户交付代码。
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 🚫 代码生成约束(严格遵守)
|
|
110
|
+
|
|
111
|
+
### 1. 通用代码约束
|
|
112
|
+
* **严禁修改 Import**:文档中的 import 路径经过验证,绝对不可修改。
|
|
113
|
+
* **严禁臆造 API**:如果文档没写,绝对不能自己发明方法名或参数名。
|
|
114
|
+
* **必须查阅 API 文档**:涉及数据模型字段(如 `LiveInfo`),必须查看文档确认字段名(例如确认是 `liveOwner.userName` 而不是 `name`)。
|
|
115
|
+
|
|
116
|
+
### 2. 🧩 Store 与 Publisher 管理约束(生命周期安全)
|
|
117
|
+
**核心原因**:SDK 使用 Combine 的 `Publisher` 进行状态订阅。不正确的生命周期管理会导致监听失效或内存泄漏。
|
|
118
|
+
|
|
119
|
+
* **订阅管理原则**:所有 `AnyCancellable` **必须声明为 ViewController 的成员变量** `cancellableSet`。
|
|
120
|
+
* **严禁忽略返回值**:禁止不存储 `.sink {}` 返回的 `AnyCancellable`。
|
|
121
|
+
* **成对原则**:在 `viewDidLoad` 中设置订阅,订阅会随 `cancellableSet` 在 `deinit` 时自动释放。
|
|
122
|
+
|
|
123
|
+
### 3. ⏱️ 超时时间限制(关键技术点)
|
|
124
|
+
**必须严格遵守以下参数限制,优先使用文档示例中的值:**
|
|
125
|
+
|
|
126
|
+
#### A. 观众连麦 (`CoGuestStore`)
|
|
127
|
+
* **规则**:
|
|
128
|
+
* 可选参数,不填则不检查超时。
|
|
129
|
+
* 若填写,范围必须在 **5 - 1800 秒**之间。
|
|
130
|
+
* **正确示例**:
|
|
131
|
+
```swift
|
|
132
|
+
// ✅ 推荐:跟随文档示例(如 30秒)
|
|
133
|
+
CoGuestStore.shared.applyForSeat(seatIndex: -1, timeout: 30) { ... }
|
|
134
|
+
// ✅ 合法:不检查超时
|
|
135
|
+
CoGuestStore.shared.applyForSeat(seatIndex: -1, timeout: 0) { ... }
|
|
136
|
+
```
|
|
137
|
+
* **错误示例**:❌ `timeout: 3` (太短),❌ `timeout: 2000` (太长)。
|
|
138
|
+
|
|
139
|
+
#### B. 主播连线/PK (`CoHostStore`)
|
|
140
|
+
* **规则**:
|
|
141
|
+
* **最大值 30 秒**(后台硬限制)。
|
|
142
|
+
* **正确示例**:
|
|
143
|
+
```swift
|
|
144
|
+
// ✅ 推荐:使用最大值
|
|
145
|
+
CoHostStore.shared.requestHostConnection(..., timeout: 30) { ... }
|
|
146
|
+
```
|
|
147
|
+
* **错误示例**:❌ `timeout: 60` (会导致请求失败)。
|
|
148
|
+
|
|
149
|
+
### 4. 🎨 扩展功能约束(美颜/音效/UI)
|
|
150
|
+
|
|
151
|
+
#### A. 音效 (Audio Effect)
|
|
152
|
+
* **变声枚举 (`AudioChangerType`)**:
|
|
153
|
+
* ✅ **允许**:`.child, .littleGirl, .man, .ethereal` 等标准枚举。
|
|
154
|
+
* ❌ **禁止**:`.uncle, .loli, .girl, .boy` (这些是旧版或错误的枚举)。
|
|
155
|
+
* **混响枚举 (`AudioReverbType`)**:
|
|
156
|
+
* ✅ **允许**:`.ktv, .smallRoom, .metallic` 等。
|
|
157
|
+
* ❌ **禁止**:`.room, .hall, .low`。
|
|
158
|
+
|
|
159
|
+
#### B. 美颜 (Beauty)
|
|
160
|
+
* **参数范围**:**0.0 - 9.0** (Float)。
|
|
161
|
+
* ❌ 不是 0-1 (Float),也不是 0-100 (Int)。
|
|
162
|
+
* **UI 映射公式**:`sliderValue / 100.0 * 9.0`。
|
|
163
|
+
|
|
164
|
+
#### C. 弹幕、礼物与布局 (Barrage, Gift & UI)
|
|
165
|
+
* **层级要求**:弹幕列表和全屏礼物动画必须使用 `UIView` 覆盖在视频层 `LiveCoreView` **之上**。
|
|
166
|
+
* **禁止分割**:严禁将屏幕分割为"上视频、下弹幕",必须是叠加模式。
|
|
167
|
+
|
|
168
|
+
##### 弹幕输入框 (Barrage Input)
|
|
169
|
+
* **位置**:固定在屏幕底部左侧,与功能按钮(礼物、连麦等)同行。
|
|
170
|
+
* **样式**:半透明圆角背景 + 占位文字「说点什么...」。
|
|
171
|
+
* **键盘适配**:
|
|
172
|
+
* 键盘弹起时,输入框**保持原位置不变**,禁止随键盘上移。
|
|
173
|
+
* 视频画面 `LiveCoreView` 约束固定为 `edges.equalToSuperview()`,禁止变形或上移。
|
|
174
|
+
* **严禁**使用 `UIScrollView.contentInsetAdjustmentBehavior` 或自动调整约束。
|
|
175
|
+
|
|
176
|
+
##### 弹幕显示流 (Barrage Display Flow)
|
|
177
|
+
```
|
|
178
|
+
发送弹幕:
|
|
179
|
+
用户输入 → 点击发送/回车 → BarrageStore.sendTextMessage(text) → 本地立即插入弹幕列表
|
|
180
|
+
|
|
181
|
+
接收弹幕:
|
|
182
|
+
订阅 BarrageStore.barrageState.$barrageList → 收到新消息 → 插入弹幕列表 → 滚动到底部
|
|
183
|
+
```
|
|
184
|
+
* **数据源**:订阅 `BarrageStore.shared.barrageState.$barrageList`。
|
|
185
|
+
* **本地回显**:发送成功后**立即**在本地弹幕列表插入,无需等待服务器回调。
|
|
186
|
+
* **滚动行为**:新消息到达时自动滚动到底部(`scrollToRow(at: lastIndex, animated: true)`)。
|
|
187
|
+
* **消息格式**:`[昵称]: [消息内容]`,昵称使用主题色,内容使用白色。
|
|
188
|
+
|
|
189
|
+
* **礼物弹幕 (Gift Barrage)**:**如果用户需要集成礼物弹幕**,`onReceiveGift` 事件触发时,**主播端和观众端**都必须在弹幕列表(Message List)中插入礼物消息。严禁仅在观众端显示礼物文本。
|
|
190
|
+
|
|
191
|
+
##### 全屏礼物动画 (Full-screen Gift Animation)
|
|
192
|
+
**⚠️ 必须实现**:礼物功能集成时,全屏礼物动画是**强制要求**,不可省略。
|
|
193
|
+
|
|
194
|
+
* **层级**:全屏礼物动画视图必须覆盖在 `LiveCoreView` **之上**,使用独立的 `UIView` 容器。
|
|
195
|
+
* **布局**:约束为 `edges.equalToSuperview()`,覆盖整个屏幕。
|
|
196
|
+
* **双端同步**:收到 `GiftStore.onReceiveGift` 回调后,**主播端和观众端**都必须播放全屏动画。严禁只在观众端播放。
|
|
197
|
+
|
|
198
|
+
### 🎨 默认 UI/UX 设计与交互规范 (仅在用户未指定时生效)
|
|
199
|
+
|
|
200
|
+
**⚠️ 注意:以下规范仅在用户未提供具体 UI 设计图或需求时作为默认标准执行。**
|
|
201
|
+
|
|
202
|
+
### 1. 全局视觉风格 (Global Aesthetics)
|
|
203
|
+
* **沉浸式暗黑**:直播页背景必须为 `.black`,视频层 (`LiveCoreView`) 必须**全屏铺满** (`edges.equalToSuperview()`) 且位于最底层。
|
|
204
|
+
* **安全区域**:所有悬浮 UI 必须约束在 `safeAreaLayoutGuide` 内部,严禁被刘海屏或底部 Home 条遮挡。
|
|
205
|
+
* **文字可读性**:视频之上的白色文字(如弹幕、ID)必须添加**黑色阴影** (`shadowColor = .black, offset = 0x1`)。
|
|
206
|
+
* **错误提示**:统一使用 **Toast**,禁止使用模态 Alert 打断用户。
|
|
207
|
+
|
|
208
|
+
### 2. 通用组件规范 (Component Standards)
|
|
209
|
+
* **顶部胶囊 (Glass Capsule)**:
|
|
210
|
+
* **样式**:**磨砂玻璃背景** (`UIBlurEffect.dark`) + **全圆角**。
|
|
211
|
+
* **应用**:仅用于顶部左侧展示“主播头像+ID+热度”。
|
|
212
|
+
* **通用按钮 (Flat Buttons)**:
|
|
213
|
+
* **样式**:**“文字 + 圆角矩形背景”**。视觉风格扁平简约,背景色为半透明黑或主题色。
|
|
214
|
+
* **关闭按钮**:特例,使用圆形磨砂玻璃图标。
|
|
215
|
+
* **弹出面板 (Floating Panels)**:
|
|
216
|
+
* **样式**:仅顶部大圆角 (`maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]`)。
|
|
217
|
+
* **禁忌**:底部禁止出现非透明的实色背景块,必须保持悬浮感。
|
|
218
|
+
|
|
219
|
+
### 3. 直播间布局蓝图 (Live Room Layout)
|
|
220
|
+
**⚠️ 动态布局原则:仅渲染用户实际集成的功能按钮。若用户未请求某功能(如PK/美颜),严禁添加对应的空按钮**
|
|
221
|
+
|
|
222
|
+
#### A. 顶部栏 (Top Bar)
|
|
223
|
+
* **左侧 [房间信息]**:使用 **磨砂胶囊** 包裹 [主播头像 | 主播昵称]。
|
|
224
|
+
* **右侧 [控制区]**:横向排列 [在线观众人数] + [关闭图标(X)]。
|
|
225
|
+
|
|
226
|
+
#### B. 底部栏 (Bottom Bar) - 根据状态动态切换
|
|
227
|
+
* **预览模式 (Preview)**:
|
|
228
|
+
* 内容**向右靠拢**:[美颜] [音效] [开始直播(主按钮)]。
|
|
229
|
+
* **直播模式 (Anchor Live)**:
|
|
230
|
+
* **左侧**:[弹幕列表(背景透明)] + [聊天输入框]。
|
|
231
|
+
* **右侧**:功能阵列 [美颜] [音效] [连线] [PK]。
|
|
232
|
+
* **观众模式 (Audience Live)**:
|
|
233
|
+
* **左侧**:[弹幕列表] + [聊天输入框]。
|
|
234
|
+
* **右侧**:[礼物] [申请连麦]。
|
|
235
|
+
|
|
236
|
+
### 4. 首页布局与交互 (Home Interaction)
|
|
237
|
+
|
|
238
|
+
#### A. 首页参考布局
|
|
239
|
+
```
|
|
240
|
+
┌─────────────────────────────┐
|
|
241
|
+
│ AtomicXCore 直播 │
|
|
242
|
+
│ │
|
|
243
|
+
│ 直播间 ID │
|
|
244
|
+
│ ┌─────────────────────────┐│
|
|
245
|
+
│ │ live_000001 ││ ← 输入框 (带左侧 Padding, 半透明背景)
|
|
246
|
+
│ └─────────────────────────┘│
|
|
247
|
+
│ │
|
|
248
|
+
│ 主播开播 │
|
|
249
|
+
│ (点击即以 anchor001 登录) │
|
|
250
|
+
│ │
|
|
251
|
+
│ 观众观看 │
|
|
252
|
+
│ (点击即以 user001 登录) │
|
|
253
|
+
│ │
|
|
254
|
+
│ [ 📋 直播列表 ] │
|
|
255
|
+
└─────────────────────────────┘
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### B. 隐式登录流程
|
|
259
|
+
**首页不需要单独的登录按钮**,登录在点击功能按钮时自动完成:
|
|
260
|
+
* 点击「主播开播」→ 使用 `anchor001` 登录 → 跳转主播页。
|
|
261
|
+
* 点击「观众观看」→ 使用 `user001` 登录 → 跳转观众页。
|
|
262
|
+
* 点击「直播列表」→ 使用 `user001` 登录 → 跳转列表页。
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## 🎯 功能实现细节
|
|
267
|
+
|
|
268
|
+
### 1. 主播开播 (`host_streaming`)
|
|
269
|
+
* **核心**:`LiveCoreView(viewType: .pushView)`
|
|
270
|
+
* **流程**:`LiveListStore.shared.createLive()`
|
|
271
|
+
* **销毁**:`deinit` 或退出页面时必须调用 `endLive()`。
|
|
272
|
+
|
|
273
|
+
### 2. 观众观看 (`audience_streaming`)
|
|
274
|
+
* **核心**:`LiveCoreView(viewType: .playView)`
|
|
275
|
+
* **流程**:`LiveListStore.shared.joinLive()`
|
|
276
|
+
* **销毁**:`deinit` 或退出页面时必须调用 `leaveLive()`。
|
|
277
|
+
|
|
278
|
+
### 3. 直播列表 (`live_list`)
|
|
279
|
+
* **核心**:`LiveListStore.shared.fetchLiveList()` + `UITableView/UICollectionView`
|
|
280
|
+
* **数据**:订阅 `liveState.liveList`。
|
|
281
|
+
* **跳转**:点击列表项跳转观众页,传递 `liveID`。
|
|
282
|
+
|
|
283
|
+
### 4. 连麦与连线交互规范 (`co_guest` & `co_host`)
|
|
284
|
+
|
|
285
|
+
#### A. 观众连麦(主播被动接收)
|
|
286
|
+
* **主播端 UI**:❌ **严禁**在底部工具栏或任何位置显示「连麦申请」列表按钮。
|
|
287
|
+
* **交互逻辑**:当收到观众连麦申请回调时,直接在屏幕中心弹出对话框(`UIAlertController`):
|
|
288
|
+
* **标题**:连麦申请
|
|
289
|
+
* **内容**:收到观众 [昵称] 的连麦申请,是否接受?
|
|
290
|
+
* **操作**:[拒绝] [接受]
|
|
291
|
+
|
|
292
|
+
#### B. 主播连线面板(点击底部【连线】按钮弹出)
|
|
293
|
+
* **展现形式**:使用底部浮层面板(`UIView` 动画升起),禁止使用 `UIAlertController`。
|
|
294
|
+
* **UI 布局(严格对照图示)**:
|
|
295
|
+
```
|
|
296
|
+
┌─────────────────────────────────────┐
|
|
297
|
+
│ │
|
|
298
|
+
│ 发起连线 [🚪 结束连线] │ ← 红色文字
|
|
299
|
+
│ │
|
|
300
|
+
│ 连线中 (2 人) │
|
|
301
|
+
│ ┌─────────────────────────────────┐│
|
|
302
|
+
│ │ [👤] 李子明 [💎20] PK中... ││ ← 已连线用户
|
|
303
|
+
│ │ [👤] 菲林娜 [💎32] PK中... ││
|
|
304
|
+
│ └─────────────────────────────────┘│
|
|
305
|
+
├─────────────────────────────────────┤
|
|
306
|
+
│ 其他连线用户 │
|
|
307
|
+
│ ┌─────────────────────────────────┐│
|
|
308
|
+
│ │ [👤] 李子明 [💎20] [取消邀请] ││ ← 灰黑背景按钮
|
|
309
|
+
│ │ [👤] 菲林娜 [💎32] [邀请连线] ││ ← 蓝色背景按钮
|
|
310
|
+
│ │ [👤] 铁柱 [💗99] [邀请连线] ││
|
|
311
|
+
│ └─────────────────────────────────┘│
|
|
312
|
+
└─────────────────────────────────────┘
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
#### C. PK 按钮交互约束
|
|
316
|
+
* **前置检查**:点击底部【PK】按钮时,必须检查当前连线状态(`CoHostStore.shared.connectedUsers.isEmpty`)。
|
|
317
|
+
* **状态处理**:
|
|
318
|
+
* **未连线**:❌ 禁止跳转,使用 Toast 提示:`"请先发起连线"`。
|
|
319
|
+
* **已连线**:✅ 弹出 PK 邀请面板。
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## 📋 Agent 最终检查清单
|
|
324
|
+
|
|
325
|
+
### 🚨 必做项(缺一不可)
|
|
326
|
+
- [ ] **🔴 编译验证**:已执行以下命令且输出包含 **BUILD SUCCEEDED**(此项必须在 TODO 任务中明确列出)
|
|
327
|
+
```bash
|
|
328
|
+
xcodebuild build -scheme <项目名> -workspace <项目名>.xcworkspace -destination 'generic/platform=iOS' CODE_SIGNING_ALLOWED=NO 2>&1 | grep -E "(error:|warning:.*\.swift|BUILD SUCCEEDED|BUILD FAILED)" | head -30
|
|
329
|
+
```
|
|
330
|
+
- [ ] **凭证注入**:已调用 `get_usersig` 生成测试凭证
|
|
331
|
+
- [ ] **依赖完整**:已检查 `Podfile` 和 Info.plist 权限
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### 代码质量检查
|
|
335
|
+
- [ ] **API 准确性**:未修改 Import,未臆造 API,已核对 `LiveInfo` 字段名。
|
|
336
|
+
- [ ] **超时合规**:连麦超时 5-1800s,连线超时 ≤30s。
|
|
337
|
+
- [ ] **扩展合规**:音效枚举正确,美颜范围 0-9,弹幕布局覆盖且键盘适配。
|
|
338
|
+
- [ ] **礼物合规**:主播和观众端均实现了全屏礼物动画显示。
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## 🚨 安全提醒(代码注释模板)
|
|
343
|
+
|
|
344
|
+
```swift
|
|
345
|
+
/**
|
|
346
|
+
* ⚠️ 测试凭证说明
|
|
347
|
+
* - 当前 userSig 由开发工具自动生成,有效期 7 天
|
|
348
|
+
* - ❌ 生产环境严禁在客户端生成 userSig
|
|
349
|
+
* - ✅ 正式上线前必须在后端服务生成
|
|
350
|
+
* - 参考: https://cloud.tencent.com/document/product/647/17275
|
|
351
|
+
*/
|
|
352
|
+
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 自动播放受限处理建议
|
|
2
2
|
|
|
3
3
|
## 简介
|
|
4
4
|
|
|
@@ -83,7 +83,7 @@ function showCustomDialog(event) {
|
|
|
83
83
|
- Android Webview 关闭自动播放限制:调用 [setMediaPlaybackRequiresUserGesture(false)](https://developer.android.com/reference/android/webkit/WebSettings#setMediaPlaybackRequiresUserGesture(boolean)) 关闭自动播放限制。
|
|
84
84
|
- iOS Webview 关闭自动播放限制:[设置 mediaTypesRequiringUserActionForPlayback 为 WKAudiovisualMediaTypeNone](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/1851524-mediatypesrequiringuseractionfor)
|
|
85
85
|
|
|
86
|
-
#
|
|
86
|
+
# 应对防火墙受限
|
|
87
87
|
|
|
88
88
|
## 功能描述
|
|
89
89
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 集成音视频通话
|
|
2
2
|
## 说明
|
|
3
3
|
RTC Engine Web SDK 也称为 TRTC Web SDK,是腾讯云实时音视频 Web SDK。提供 npm package name “trtc-sdk-v5”。
|
|
4
4
|
|
|
@@ -166,7 +166,7 @@ trtc.on(TRTC.EVENT.KICKED_OUT, error => {
|
|
|
166
166
|
});
|
|
167
167
|
```
|
|
168
168
|
|
|
169
|
-
#
|
|
169
|
+
# 互动直播连麦
|
|
170
170
|
|
|
171
171
|
## 主播端
|
|
172
172
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
## 功能描述
|
|
2
|
+
本文主要介绍自定义采集和自定义播放渲染的高阶用法。
|
|
3
|
+
|
|
4
|
+
## 自定义采集
|
|
5
|
+
|
|
6
|
+
默认情况下,{@link TRTC#startLocalVideo trtc.startLocalVideo()},{@link TRTC#startLocalAudio trtc.startLocalAudio()} 是采集并发布摄像头、麦克风,{@link TRTC#startScreenShare trtc.startScreenShare()} 是采集并发布屏幕分享。
|
|
7
|
+
|
|
8
|
+
您可以通过如下参数传入自定义采集的 MediaStreamTrack:
|
|
9
|
+
|
|
10
|
+
- `trtc.startLocalAudio({ option: { audioTrack }})`
|
|
11
|
+
- 传入该参数后,SDK 不会采集麦克风,使用自定义 audioTrack 推流。
|
|
12
|
+
- 若同时设置 microphoneId,audioTrack,则按优先级(microphoneId>audioTrack)进行采集,但不建议混用。
|
|
13
|
+
- `trtc.startLocalVideo({ option: { videoTrack }})`
|
|
14
|
+
- 传入该参数后,SDK 不会采集摄像头,自定义采集的 videoTrack 将会以主流的形式推流。
|
|
15
|
+
- 若同时设置 cameraId,useFrontCamera,videoTrack,则按优先级(cameraId>useFrontCamera>videoTrack)进行采集,但不建议混用。
|
|
16
|
+
- `trtc.startScreenShare({ option: { videoTrack }})`
|
|
17
|
+
- 传入该参数后,SDK 不会采集屏幕分享,自定义采集的 videoTrack 将会以辅流的形式推流。
|
|
18
|
+
|
|
19
|
+
获取 audioTrack,videoTrack 通常有以下几种方式:
|
|
20
|
+
|
|
21
|
+
- 通过 [getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia) 采集摄像头和麦克风。
|
|
22
|
+
- 通过 [getDisplayMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia) 采集屏幕分享。
|
|
23
|
+
- 通过 [videoElement.captureStream](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/captureStream) 采集 video 标签中正在播放的音视频。
|
|
24
|
+
- 通过 [canvas.captureStream](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/captureStream) 采集 canvas 画布中的动画。
|
|
25
|
+
|
|
26
|
+
### 采集 video 标签中正在播放的视频
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
// 检测您当前的浏览器是否支持从 video 元素采集
|
|
30
|
+
if (!HTMLVideoElement.prototype.captureStream) {
|
|
31
|
+
console.log('your browser does not support capturing stream from video element');
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
// 获取您页面在播放视频的 video 标签
|
|
35
|
+
const video = document.getElementByID('your-video-element-ID');
|
|
36
|
+
// 从播放的视频采集视频流
|
|
37
|
+
const stream = video.captureStream();
|
|
38
|
+
const audioTrack = stream.getAudioTracks()[0];
|
|
39
|
+
const videoTrack = stream.getVideoTracks()[0];
|
|
40
|
+
|
|
41
|
+
trtc.startLocalVideo({ option:{ videoTrack } });
|
|
42
|
+
trtc.startLocalAudio({ option:{ audioTrack } });
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 采集 canvas 中的画面
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
// 检测您当前的浏览器是否支持从 canvas 元素采集
|
|
49
|
+
if (!HTMLCanvasElement.prototype.captureStream) {
|
|
50
|
+
console.log('your browser does not support capturing stream from canvas element');
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
// 获取您的 canvas 标签
|
|
54
|
+
const canvas = document.getElementByID('your-canvas-element-ID');
|
|
55
|
+
|
|
56
|
+
// 从 canvas 采集 15 fps 的视频流
|
|
57
|
+
const fps = 15;
|
|
58
|
+
const stream = canvas.captureStream(fps);
|
|
59
|
+
const videoTrack = stream.getVideoTracks()[0];
|
|
60
|
+
|
|
61
|
+
trtc.startLocalVideo({ option:{ videoTrack } });
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 自定义播放渲染
|
|
65
|
+
|
|
66
|
+
正常情况下,在 {@link TRTC#startLocalVideo startLocalVideo()} {@link TRTC#startRemoteVideo startRemoteVideo()} 时,传入 view 参数,SDK 会在指定的 element 标签下,创建 `video` 标签播放视频画面。
|
|
67
|
+
|
|
68
|
+
如果您需要自定义播放渲染,不需要 SDK 播放视频,可参考如下步骤实现:
|
|
69
|
+
|
|
70
|
+
- 在 startLocalVideo 或 startRemoteVideo 方法调用时不填 view 参数或 view 参数传入 null
|
|
71
|
+
- 监听 TRTC.EVENT.TRACK 事件,每当有新的 MediaStreamTrack 时,SDK 会通过该事件通知。
|
|
72
|
+
- 在上述事件触发时,拿到最新的 MediaStreamTrack,此时您可以使用自己的播放器进行视频的播放渲染。
|
|
73
|
+
- 使用这种自定义播放渲染方式后,{@link module:EVENT.VIDEO_PLAY_STATE_CHANGED VIDEO_PLAY_STATE_CHANGED} 事件将不会被触发,您需要自行监听视频轨道 [MediaStreamTrack](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack) 的 `mute/unmute/ended` 等事件来判断当前视频数据流的状态。
|
|
74
|
+
|
|
75
|
+
### 自定义渲染本地视频
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
trtc.on(TRTC.EVENT.TRACK, event => {
|
|
79
|
+
const isLocal = event.userId === ''; // userId === '' means event.track is a local track, otherwise it's a remote track
|
|
80
|
+
const isSubStream = event.streamType === TRTC.TYPE.STREAM_TYPE_SUB; // Usually the sub stream is a screen-sharing video stream.
|
|
81
|
+
const mediaStreamTrack = event.track;
|
|
82
|
+
const kind = event.track.kind; // audio or video
|
|
83
|
+
})
|
|
84
|
+
```
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
## 简介
|
|
2
|
+
|
|
3
|
+
浏览器为了防止网页自动播放音视频对用户造成干扰,对音视频的自动播放功能做了限制:**在用户与网页产生交互(例如点击、触摸页面等)之前,网页将被禁止播放带有声音的媒体。在 iOS 10+ 中,如果开启了省电模式,[无声音的媒体也会被禁止播放](https://discussions.apple.com/thread/254541299?sortBy=best)。**
|
|
4
|
+
|
|
5
|
+
受上述浏览器自动播放策略影响,在使用 TRTC Web SDK 时,可能会出现播放无声的问题。最常见的场景是:您的产品设计中,支持用户刷新页面后,无需用户点击,可自动进房拉流播放。
|
|
6
|
+
|
|
7
|
+
本文主要介绍**如何解决因自动播放策略限制,导致播放失败**的问题。
|
|
8
|
+
|
|
9
|
+
## 方案一:使用 SDK 提供的自动播放弹窗
|
|
10
|
+
|
|
11
|
+
默认情况下,当出现自动播放失败时,SDK 会弹窗引导用户与页面产生交互。当产生交互后,SDK 会主动调用接口恢复播放。
|
|
12
|
+
|
|
13
|
+
- 优点:业务侧无需做任何处理,简单高效。
|
|
14
|
+
|
|
15
|
+
- 缺点:SDK 提供的弹窗不一定符合业务产品设计要求,此时可考虑使用方案二。
|
|
16
|
+
|
|
17
|
+
SDK 提供的弹窗适配桌面端和移动端浏览器,样式如下:
|
|
18
|
+
|
|
19
|
+
<div style="display:flex;align-items:center;">
|
|
20
|
+
<img src="./assets/autoplay-dialog-pc-cn.png" style="width:40%;max-width:450px;margin-right:16px;" />
|
|
21
|
+
<img src="./assets/autoplay-dialog-cn.png" style="width:30%;max-width:300px;" />
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
- SDK 会根据 [navigator.language](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language) 的值来切换中英文弹窗提示。
|
|
25
|
+
|
|
26
|
+
- 当用户点击"确认"时,SDK 自动调用相关接口来恢复播放。
|
|
27
|
+
|
|
28
|
+
- 为尽可能保证弹窗处于最上层展示,其 z-index 值为 1500。
|
|
29
|
+
|
|
30
|
+
## 方案二:自定义处理自动播放限制
|
|
31
|
+
|
|
32
|
+
如果您希望完全控制自动播放失败时的用户体验,可以按照以下步骤来实现:
|
|
33
|
+
|
|
34
|
+
### 步骤 1:关闭 SDK 默认弹窗
|
|
35
|
+
|
|
36
|
+
在调用 [trtc.enterRoom](./TRTC.html#enterRoom) 接口时,将 `enableAutoPlayDialog` 参数设置为 `false`:
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
await trtc.enterRoom({
|
|
40
|
+
// ... 其他参数
|
|
41
|
+
enableAutoPlayDialog: false
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 步骤 2:监听自动播放失败事件(必做)
|
|
46
|
+
|
|
47
|
+
监听 [AUTOPLAY_FAILED](./module-EVENT.html#.AUTOPLAY_FAILED) 事件来处理自动播放失败的情况。SDK 会自动监听用户的点击行为,在用户点击后自动恢复播放。
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
trtc.on(TRTC.EVENT.AUTOPLAY_FAILED, event => {
|
|
51
|
+
// 在此处添加您的自定义处理逻辑
|
|
52
|
+
// 例如:显示自定义提示框,引导用户点击页面
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 步骤 3:主动恢复播放(可选)
|
|
57
|
+
|
|
58
|
+
> 从版本 5.9.0 开始支持
|
|
59
|
+
|
|
60
|
+
在某些特殊场景下(如在 iframe 中或使用特定前端框架时),您可能需要主动调用恢复播放方法。此时可以使用事件中提供的 `resume` 方法:
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
trtc.on(TRTC.EVENT.AUTOPLAY_FAILED, (event) => {
|
|
64
|
+
showCustomDialog(event);
|
|
65
|
+
});
|
|
66
|
+
function showCustomDialog(event) {
|
|
67
|
+
const { userId, resume } = event;
|
|
68
|
+
// 受限的用户 id 为 userId,resume 是恢复这个用户播放的函数
|
|
69
|
+
// 需要显示一个自定义按钮,提示 userId 播放受限,在按钮点击回调里调用 'resume()'
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 重要提示
|
|
74
|
+
|
|
75
|
+
1. 某些浏览器可能在每次播放前都会检查用户交互状态,因此可能多次触发自动播放失败事件。
|
|
76
|
+
|
|
77
|
+
2. 在 iOS 微信浏览器和小程序 webview 中有特殊要求:
|
|
78
|
+
- 首次播放远端流时,必须在用户点击事件的回调函数中直接调用播放接口
|
|
79
|
+
- 不能使用 setTimeout 等异步方式调用播放接口,否则会导致播放失败
|
|
80
|
+
|
|
81
|
+
## Webview 中关闭自动播放策略限制
|
|
82
|
+
|
|
83
|
+
在 Android 和 iOS Webview 中的默认自动播放策略可能和浏览器中的不一致,您可以参考如下文档,在您的 App 中关闭自动播放限制。
|
|
84
|
+
|
|
85
|
+
- Android Webview 关闭自动播放限制:调用 [setMediaPlaybackRequiresUserGesture(false)](https://developer.android.com/reference/android/webkit/WebSettings#setMediaPlaybackRequiresUserGesture(boolean)) 关闭自动播放限制。
|
|
86
|
+
- iOS Webview 关闭自动播放限制:[设置 mediaTypesRequiringUserActionForPlayback 为 WKAudiovisualMediaTypeNone](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/1851524-mediatypesrequiringuseractionfor)
|