@give-tech/ec-player-vue 0.0.1-beta.41 → 0.0.1-beta.42
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/dist/composables/usePlayer.d.ts +2 -0
- package/dist/composables/usePlayer.d.ts.map +1 -1
- package/dist/ec-player-vue.css +99 -45
- package/dist/index.js +64 -15
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePlayer.d.ts","sourceRoot":"","sources":["../../src/composables/usePlayer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAA0C,KAAK,GAAG,EAAE,MAAM,KAAK,CAAA;AACtE,OAAO,EACL,YAAY,EAIZ,KAAK,aAAa,EAEnB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAiB,aAAa,EAAE,MAAM,UAAU,CAAA;AAG5D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kBAAkB;IAClB,SAAS,EAAE,GAAG,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;IACxC,YAAY;IACZ,MAAM,EAAE,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IAChC,YAAY;IACZ,KAAK,EAAE,aAAa,CAAA;IACpB,aAAa;IACb,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACvB,aAAa;IACb,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC3B,aAAa;IACb,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACpB,SAAS;IACT,IAAI,EAAE,CAAC,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnE,WAAW;IACX,UAAU,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;IAC5C,aAAa;IACb,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,SAAS;IACT,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,WAAW;IACX,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,SAAS;IACT,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,cAAc;IACd,SAAS,EAAE,MAAM,YAAY,GAAG,IAAI,CAAA;IACpC,WAAW;IACX,QAAQ,EAAE,MAAM,aAAa,CAAA;IAC7B,aAAa;IACb,cAAc,EAAE,MAAM,MAAM,CAAA;IAC5B,YAAY;IACZ,WAAW,EAAE,MAAM,MAAM,CAAA;IACzB,YAAY;IACZ,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAkBD;;GAEG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE;IACJ,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACjB,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;CACnB,GACA,eAAe,
|
|
1
|
+
{"version":3,"file":"usePlayer.d.ts","sourceRoot":"","sources":["../../src/composables/usePlayer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAA0C,KAAK,GAAG,EAAE,MAAM,KAAK,CAAA;AACtE,OAAO,EACL,YAAY,EAIZ,KAAK,aAAa,EAEnB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAiB,aAAa,EAAE,MAAM,UAAU,CAAA;AAG5D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kBAAkB;IAClB,SAAS,EAAE,GAAG,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;IACxC,YAAY;IACZ,MAAM,EAAE,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IAChC,YAAY;IACZ,KAAK,EAAE,aAAa,CAAA;IACpB,aAAa;IACb,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACvB,aAAa;IACb,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC3B,aAAa;IACb,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACpB,SAAS;IACT,IAAI,EAAE,CAAC,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnE,WAAW;IACX,UAAU,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;IAC5C,aAAa;IACb,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,SAAS;IACT,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,WAAW;IACX,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,SAAS;IACT,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,WAAW;IACX,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,cAAc;IACd,SAAS,EAAE,MAAM,YAAY,GAAG,IAAI,CAAA;IACpC,WAAW;IACX,QAAQ,EAAE,MAAM,aAAa,CAAA;IAC7B,aAAa;IACb,cAAc,EAAE,MAAM,MAAM,CAAA;IAC5B,YAAY;IACZ,WAAW,EAAE,MAAM,MAAM,CAAA;IACzB,YAAY;IACZ,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAkBD;;GAEG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE;IACJ,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACjB,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;CACnB,GACA,eAAe,CAsQjB"}
|
package/dist/ec-player-vue.css
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
|
|
2
|
-
.gt-player-container[data-v-
|
|
2
|
+
.gt-player-container[data-v-8da5b44d] {
|
|
3
3
|
width: 100%;
|
|
4
4
|
height: 100%;
|
|
5
5
|
}
|
|
6
|
-
.gt-video-wrapper[data-v-
|
|
6
|
+
.gt-video-wrapper[data-v-8da5b44d] {
|
|
7
7
|
position: relative;
|
|
8
8
|
width: 100%;
|
|
9
9
|
height: 100%;
|
|
10
10
|
background: #000;
|
|
11
11
|
overflow: hidden;
|
|
12
12
|
}
|
|
13
|
-
.gt-player-canvas[data-v-
|
|
13
|
+
.gt-player-canvas[data-v-8da5b44d] {
|
|
14
14
|
width: 100%;
|
|
15
15
|
height: 100%;
|
|
16
16
|
object-fit: contain;
|
|
17
17
|
}
|
|
18
|
-
.gt-placeholder[data-v-
|
|
18
|
+
.gt-placeholder[data-v-8da5b44d] {
|
|
19
19
|
position: absolute;
|
|
20
20
|
top: 0;
|
|
21
21
|
left: 0;
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/* 加载中动画 */
|
|
31
|
-
.gt-loading-spinner[data-v-
|
|
31
|
+
.gt-loading-spinner[data-v-8da5b44d] {
|
|
32
32
|
position: absolute;
|
|
33
33
|
top: 0;
|
|
34
34
|
left: 0;
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
background: rgba(0, 0, 0, 0.5);
|
|
41
41
|
z-index: 10;
|
|
42
42
|
}
|
|
43
|
-
.gt-spinner[data-v-
|
|
43
|
+
.gt-spinner[data-v-8da5b44d] {
|
|
44
44
|
width: 10%;
|
|
45
45
|
max-width: 48px;
|
|
46
46
|
min-width: 20px;
|
|
@@ -48,16 +48,16 @@
|
|
|
48
48
|
border: 0.3em solid rgba(255, 255, 255, 0.3);
|
|
49
49
|
border-top-color: #fff;
|
|
50
50
|
border-radius: 50%;
|
|
51
|
-
animation: gt-spin-
|
|
51
|
+
animation: gt-spin-8da5b44d 1s linear infinite;
|
|
52
52
|
}
|
|
53
|
-
@keyframes gt-spin-
|
|
53
|
+
@keyframes gt-spin-8da5b44d {
|
|
54
54
|
to {
|
|
55
55
|
transform: rotate(360deg);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/* 视频控制条 */
|
|
60
|
-
.gt-video-controls[data-v-
|
|
60
|
+
.gt-video-controls[data-v-8da5b44d] {
|
|
61
61
|
position: absolute;
|
|
62
62
|
bottom: 0;
|
|
63
63
|
left: 0;
|
|
@@ -70,13 +70,13 @@ to {
|
|
|
70
70
|
align-items: center;
|
|
71
71
|
gap: 12px;
|
|
72
72
|
}
|
|
73
|
-
.gt-flex-spacer[data-v-
|
|
73
|
+
.gt-flex-spacer[data-v-8da5b44d] {
|
|
74
74
|
flex: 1;
|
|
75
75
|
}
|
|
76
|
-
.gt-video-controls.visible[data-v-
|
|
76
|
+
.gt-video-controls.visible[data-v-8da5b44d] {
|
|
77
77
|
opacity: 1;
|
|
78
78
|
}
|
|
79
|
-
.gt-control-btn[data-v-
|
|
79
|
+
.gt-control-btn[data-v-8da5b44d] {
|
|
80
80
|
width: 28px;
|
|
81
81
|
height: 28px;
|
|
82
82
|
border: none;
|
|
@@ -90,14 +90,14 @@ to {
|
|
|
90
90
|
transition: all 0.2s ease;
|
|
91
91
|
flex-shrink: 0;
|
|
92
92
|
}
|
|
93
|
-
.gt-control-btn[data-v-
|
|
93
|
+
.gt-control-btn[data-v-8da5b44d]:hover {
|
|
94
94
|
background: rgba(255, 255, 255, 0.2);
|
|
95
95
|
}
|
|
96
|
-
.gt-control-btn svg[data-v-
|
|
96
|
+
.gt-control-btn svg[data-v-8da5b44d] {
|
|
97
97
|
width: 14px;
|
|
98
98
|
height: 14px;
|
|
99
99
|
}
|
|
100
|
-
.gt-progress-container[data-v-
|
|
100
|
+
.gt-progress-container[data-v-8da5b44d] {
|
|
101
101
|
flex: 1;
|
|
102
102
|
position: relative;
|
|
103
103
|
cursor: pointer;
|
|
@@ -105,7 +105,7 @@ to {
|
|
|
105
105
|
display: flex;
|
|
106
106
|
align-items: center;
|
|
107
107
|
}
|
|
108
|
-
.gt-progress-bar[data-v-
|
|
108
|
+
.gt-progress-bar[data-v-8da5b44d] {
|
|
109
109
|
width: 100%;
|
|
110
110
|
height: 4px;
|
|
111
111
|
background: rgba(255, 255, 255, 0.2);
|
|
@@ -114,10 +114,10 @@ to {
|
|
|
114
114
|
overflow: hidden;
|
|
115
115
|
transition: height 0.2s ease;
|
|
116
116
|
}
|
|
117
|
-
.gt-progress-container:hover .gt-progress-bar[data-v-
|
|
117
|
+
.gt-progress-container:hover .gt-progress-bar[data-v-8da5b44d] {
|
|
118
118
|
height: 6px;
|
|
119
119
|
}
|
|
120
|
-
.gt-progress-buffered[data-v-
|
|
120
|
+
.gt-progress-buffered[data-v-8da5b44d] {
|
|
121
121
|
position: absolute;
|
|
122
122
|
top: 0;
|
|
123
123
|
left: 0;
|
|
@@ -126,7 +126,7 @@ to {
|
|
|
126
126
|
border-radius: 2px;
|
|
127
127
|
transition: width 0.1s;
|
|
128
128
|
}
|
|
129
|
-
.gt-progress-played[data-v-
|
|
129
|
+
.gt-progress-played[data-v-8da5b44d] {
|
|
130
130
|
position: absolute;
|
|
131
131
|
top: 0;
|
|
132
132
|
left: 0;
|
|
@@ -135,7 +135,7 @@ to {
|
|
|
135
135
|
border-radius: 2px;
|
|
136
136
|
transition: width 0.1s;
|
|
137
137
|
}
|
|
138
|
-
.gt-progress-handle[data-v-
|
|
138
|
+
.gt-progress-handle[data-v-8da5b44d] {
|
|
139
139
|
position: absolute;
|
|
140
140
|
right: -6px;
|
|
141
141
|
top: 50%;
|
|
@@ -148,11 +148,11 @@ to {
|
|
|
148
148
|
opacity: 0;
|
|
149
149
|
transition: opacity 0.2s, transform 0.2s;
|
|
150
150
|
}
|
|
151
|
-
.gt-progress-container:hover .gt-progress-handle[data-v-
|
|
151
|
+
.gt-progress-container:hover .gt-progress-handle[data-v-8da5b44d] {
|
|
152
152
|
opacity: 1;
|
|
153
153
|
transform: translateY(-50%) scale(1.2);
|
|
154
154
|
}
|
|
155
|
-
.gt-progress-tooltip[data-v-
|
|
155
|
+
.gt-progress-tooltip[data-v-8da5b44d] {
|
|
156
156
|
position: absolute;
|
|
157
157
|
bottom: calc(100% + 8px);
|
|
158
158
|
transform: translateX(-50%);
|
|
@@ -164,20 +164,20 @@ to {
|
|
|
164
164
|
white-space: nowrap;
|
|
165
165
|
pointer-events: none;
|
|
166
166
|
}
|
|
167
|
-
.gt-time-display[data-v-
|
|
167
|
+
.gt-time-display[data-v-8da5b44d] {
|
|
168
168
|
color: white;
|
|
169
169
|
font-size: 12px;
|
|
170
170
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
171
171
|
white-space: nowrap;
|
|
172
172
|
flex-shrink: 0;
|
|
173
173
|
}
|
|
174
|
-
.gt-time-separator[data-v-
|
|
174
|
+
.gt-time-separator[data-v-8da5b44d] {
|
|
175
175
|
margin: 0 4px;
|
|
176
176
|
opacity: 0.6;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
/* 直播指示器 */
|
|
180
|
-
.gt-live-indicator[data-v-
|
|
180
|
+
.gt-live-indicator[data-v-8da5b44d] {
|
|
181
181
|
display: flex;
|
|
182
182
|
align-items: center;
|
|
183
183
|
gap: 6px;
|
|
@@ -185,17 +185,17 @@ to {
|
|
|
185
185
|
font-size: 12px;
|
|
186
186
|
font-weight: 500;
|
|
187
187
|
}
|
|
188
|
-
.gt-live-dot[data-v-
|
|
188
|
+
.gt-live-dot[data-v-8da5b44d] {
|
|
189
189
|
width: 8px;
|
|
190
190
|
height: 8px;
|
|
191
191
|
background: #ff2d55;
|
|
192
192
|
border-radius: 50%;
|
|
193
|
-
animation: gt-live-pulse-
|
|
193
|
+
animation: gt-live-pulse-8da5b44d 1.5s ease-in-out infinite;
|
|
194
194
|
}
|
|
195
|
-
.gt-live-text[data-v-
|
|
195
|
+
.gt-live-text[data-v-8da5b44d] {
|
|
196
196
|
color: #ff2d55;
|
|
197
197
|
}
|
|
198
|
-
@keyframes gt-live-pulse-
|
|
198
|
+
@keyframes gt-live-pulse-8da5b44d {
|
|
199
199
|
0%, 100% {
|
|
200
200
|
opacity: 1;
|
|
201
201
|
}
|
|
@@ -204,8 +204,62 @@ to {
|
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
/* 倍速按钮 */
|
|
208
|
+
.gt-playback-rate-container[data-v-8da5b44d] {
|
|
209
|
+
position: relative;
|
|
210
|
+
flex-shrink: 0;
|
|
211
|
+
}
|
|
212
|
+
.gt-playback-rate-btn[data-v-8da5b44d] {
|
|
213
|
+
width: auto !important;
|
|
214
|
+
min-width: 28px;
|
|
215
|
+
padding: 0 8px;
|
|
216
|
+
font-size: 12px;
|
|
217
|
+
font-weight: 500;
|
|
218
|
+
}
|
|
219
|
+
.gt-playback-rate-text[data-v-8da5b44d] {
|
|
220
|
+
color: white;
|
|
221
|
+
}
|
|
222
|
+
.gt-playback-rate-menu[data-v-8da5b44d] {
|
|
223
|
+
position: absolute;
|
|
224
|
+
bottom: calc(100% + 8px);
|
|
225
|
+
left: 50%;
|
|
226
|
+
transform: translateX(-50%);
|
|
227
|
+
background: rgba(0, 0, 0, 0.85);
|
|
228
|
+
border-radius: 6px;
|
|
229
|
+
padding: 4px 0;
|
|
230
|
+
min-width: 60px;
|
|
231
|
+
z-index: 20;
|
|
232
|
+
animation: gt-rate-menu-fade-in-8da5b44d 0.15s ease;
|
|
233
|
+
}
|
|
234
|
+
@keyframes gt-rate-menu-fade-in-8da5b44d {
|
|
235
|
+
from { opacity: 0; transform: translateX(-50%) translateY(4px);
|
|
236
|
+
}
|
|
237
|
+
to { opacity: 1; transform: translateX(-50%) translateY(0);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
.gt-playback-rate-option[data-v-8da5b44d] {
|
|
241
|
+
display: block;
|
|
242
|
+
width: 100%;
|
|
243
|
+
padding: 6px 12px;
|
|
244
|
+
border: none;
|
|
245
|
+
background: transparent;
|
|
246
|
+
color: rgba(255, 255, 255, 0.8);
|
|
247
|
+
font-size: 12px;
|
|
248
|
+
cursor: pointer;
|
|
249
|
+
text-align: center;
|
|
250
|
+
transition: all 0.15s ease;
|
|
251
|
+
}
|
|
252
|
+
.gt-playback-rate-option[data-v-8da5b44d]:hover {
|
|
253
|
+
background: rgba(255, 255, 255, 0.1);
|
|
254
|
+
color: white;
|
|
255
|
+
}
|
|
256
|
+
.gt-playback-rate-option.active[data-v-8da5b44d] {
|
|
257
|
+
color: #ff2d55;
|
|
258
|
+
font-weight: 500;
|
|
259
|
+
}
|
|
260
|
+
|
|
207
261
|
/* 居中播放按钮 */
|
|
208
|
-
.gt-center-play-btn[data-v-
|
|
262
|
+
.gt-center-play-btn[data-v-8da5b44d] {
|
|
209
263
|
position: absolute;
|
|
210
264
|
top: 50%;
|
|
211
265
|
left: 50%;
|
|
@@ -220,11 +274,11 @@ to {
|
|
|
220
274
|
cursor: pointer;
|
|
221
275
|
transition: all 0.2s ease;
|
|
222
276
|
}
|
|
223
|
-
.gt-center-play-btn[data-v-
|
|
277
|
+
.gt-center-play-btn[data-v-8da5b44d]:hover {
|
|
224
278
|
background: rgba(0, 0, 0, 0.7);
|
|
225
279
|
transform: translate(-50%, -50%) scale(1.05);
|
|
226
280
|
}
|
|
227
|
-
.gt-center-play-btn svg[data-v-
|
|
281
|
+
.gt-center-play-btn svg[data-v-8da5b44d] {
|
|
228
282
|
width: 24px;
|
|
229
283
|
height: 24px;
|
|
230
284
|
color: white;
|
|
@@ -232,7 +286,7 @@ to {
|
|
|
232
286
|
}
|
|
233
287
|
|
|
234
288
|
/* 环境信息面板 */
|
|
235
|
-
.gt-env-panel[data-v-
|
|
289
|
+
.gt-env-panel[data-v-8da5b44d] {
|
|
236
290
|
position: absolute;
|
|
237
291
|
top: 12px;
|
|
238
292
|
left: 12px;
|
|
@@ -246,46 +300,46 @@ to {
|
|
|
246
300
|
max-height: calc(100% - 24px);
|
|
247
301
|
overflow-y: auto;
|
|
248
302
|
backdrop-filter: blur(10px);
|
|
249
|
-
animation: gt-env-fade-in-
|
|
303
|
+
animation: gt-env-fade-in-8da5b44d 0.15s ease;
|
|
250
304
|
z-index: 15;
|
|
251
305
|
}
|
|
252
|
-
.gt-env-panel[data-v-
|
|
306
|
+
.gt-env-panel[data-v-8da5b44d]::-webkit-scrollbar {
|
|
253
307
|
width: 4px;
|
|
254
308
|
}
|
|
255
|
-
.gt-env-panel[data-v-
|
|
309
|
+
.gt-env-panel[data-v-8da5b44d]::-webkit-scrollbar-track {
|
|
256
310
|
background: transparent;
|
|
257
311
|
}
|
|
258
|
-
.gt-env-panel[data-v-
|
|
312
|
+
.gt-env-panel[data-v-8da5b44d]::-webkit-scrollbar-thumb {
|
|
259
313
|
background: rgba(255, 255, 255, 0.3);
|
|
260
314
|
border-radius: 2px;
|
|
261
315
|
}
|
|
262
|
-
@keyframes gt-env-fade-in-
|
|
316
|
+
@keyframes gt-env-fade-in-8da5b44d {
|
|
263
317
|
from { opacity: 0; transform: translateY(-4px);
|
|
264
318
|
}
|
|
265
319
|
to { opacity: 1; transform: translateY(0);
|
|
266
320
|
}
|
|
267
321
|
}
|
|
268
|
-
.gt-env-panel .gt-env-row[data-v-
|
|
322
|
+
.gt-env-panel .gt-env-row[data-v-8da5b44d] {
|
|
269
323
|
display: flex;
|
|
270
324
|
justify-content: space-between;
|
|
271
325
|
align-items: center;
|
|
272
326
|
padding: 2px 0;
|
|
273
327
|
color: rgba(255, 255, 255, 0.7);
|
|
274
328
|
}
|
|
275
|
-
.gt-env-panel .gt-env-row span[data-v-
|
|
329
|
+
.gt-env-panel .gt-env-row span[data-v-8da5b44d]:first-child {
|
|
276
330
|
color: rgba(255, 255, 255, 0.5);
|
|
277
331
|
margin-right: 16px;
|
|
278
332
|
}
|
|
279
|
-
.gt-env-panel .gt-env-row span[data-v-
|
|
333
|
+
.gt-env-panel .gt-env-row span[data-v-8da5b44d]:last-child {
|
|
280
334
|
font-variant-numeric: tabular-nums;
|
|
281
335
|
}
|
|
282
|
-
.gt-env-panel .gt-env-row .ok[data-v-
|
|
336
|
+
.gt-env-panel .gt-env-row .ok[data-v-8da5b44d] { color: #4caf50;
|
|
283
337
|
}
|
|
284
|
-
.gt-env-panel .gt-env-row .warn[data-v-
|
|
338
|
+
.gt-env-panel .gt-env-row .warn[data-v-8da5b44d] { color: #ff9800;
|
|
285
339
|
}
|
|
286
|
-
.gt-env-panel .gt-env-row .err[data-v-
|
|
340
|
+
.gt-env-panel .gt-env-row .err[data-v-8da5b44d] { color: #f44336;
|
|
287
341
|
}
|
|
288
|
-
.gt-env-divider[data-v-
|
|
342
|
+
.gt-env-divider[data-v-8da5b44d] {
|
|
289
343
|
height: 1px;
|
|
290
344
|
background: rgba(255, 255, 255, 0.1);
|
|
291
345
|
margin: 4px 0;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ref, shallowRef, reactive, onUnmounted, computed, onMounted, defineComponent, watch, openBlock, createElementBlock, createElementVNode, unref, renderSlot, createCommentVNode, normalizeClass, toDisplayString, Fragment, normalizeStyle, mergeDefaults } from "vue";
|
|
1
|
+
import { ref, shallowRef, reactive, onUnmounted, computed, onMounted, defineComponent, watch, openBlock, createElementBlock, createElementVNode, unref, renderSlot, createCommentVNode, normalizeClass, toDisplayString, Fragment, normalizeStyle, renderList, mergeDefaults } from "vue";
|
|
2
2
|
import { setLogLevel, EcPlayerCore, EnvDetector } from "@give-tech/ec-player";
|
|
3
3
|
import { LogLevel, WASMLoader } from "@give-tech/ec-player";
|
|
4
4
|
const DEFAULT_EC_PLAYER_PROPS = {
|
|
@@ -6,7 +6,8 @@ const DEFAULT_EC_PLAYER_PROPS = {
|
|
|
6
6
|
controlOption: {
|
|
7
7
|
show: true,
|
|
8
8
|
fullscreen: true,
|
|
9
|
-
info: true
|
|
9
|
+
info: true,
|
|
10
|
+
playbackRate: true
|
|
10
11
|
}
|
|
11
12
|
};
|
|
12
13
|
const DEFAULT_PLAYER_OPTIONS = {
|
|
@@ -37,7 +38,8 @@ function getMergedConfig(props) {
|
|
|
37
38
|
controlOption: {
|
|
38
39
|
show: props.controlOption?.show ?? globalConfig.showControls ?? DEFAULT_EC_PLAYER_PROPS.controlOption.show,
|
|
39
40
|
fullscreen: props.controlOption?.fullscreen ?? DEFAULT_EC_PLAYER_PROPS.controlOption.fullscreen,
|
|
40
|
-
info: props.controlOption?.info ?? DEFAULT_EC_PLAYER_PROPS.controlOption.info
|
|
41
|
+
info: props.controlOption?.info ?? DEFAULT_EC_PLAYER_PROPS.controlOption.info,
|
|
42
|
+
playbackRate: props.controlOption?.playbackRate ?? DEFAULT_EC_PLAYER_PROPS.controlOption.playbackRate
|
|
41
43
|
}
|
|
42
44
|
};
|
|
43
45
|
}
|
|
@@ -118,7 +120,8 @@ function usePlayer(emit) {
|
|
|
118
120
|
totalSegments: 0,
|
|
119
121
|
downloadSpeed: 0,
|
|
120
122
|
currentTime: 0,
|
|
121
|
-
duration: 0
|
|
123
|
+
duration: 0,
|
|
124
|
+
playbackRate: 1
|
|
122
125
|
});
|
|
123
126
|
const callbacks = {
|
|
124
127
|
onStateChange: (partial) => {
|
|
@@ -235,6 +238,10 @@ function usePlayer(emit) {
|
|
|
235
238
|
if (!player.value) return;
|
|
236
239
|
await player.value.seek(time);
|
|
237
240
|
}
|
|
241
|
+
function setPlaybackRate(rate) {
|
|
242
|
+
if (!player.value) return;
|
|
243
|
+
player.value.setPlaybackRate(rate);
|
|
244
|
+
}
|
|
238
245
|
function getPlayer() {
|
|
239
246
|
return player.value;
|
|
240
247
|
}
|
|
@@ -269,6 +276,7 @@ function usePlayer(emit) {
|
|
|
269
276
|
pause,
|
|
270
277
|
resume,
|
|
271
278
|
seek,
|
|
279
|
+
setPlaybackRate,
|
|
272
280
|
getPlayer,
|
|
273
281
|
getState,
|
|
274
282
|
getCurrentTime,
|
|
@@ -445,14 +453,25 @@ const _hoisted_26 = {
|
|
|
445
453
|
key: 3,
|
|
446
454
|
class: "gt-flex-spacer"
|
|
447
455
|
};
|
|
448
|
-
const _hoisted_27 =
|
|
456
|
+
const _hoisted_27 = {
|
|
457
|
+
key: 4,
|
|
458
|
+
class: "gt-playback-rate-container"
|
|
459
|
+
};
|
|
449
460
|
const _hoisted_28 = ["title"];
|
|
450
|
-
const _hoisted_29 = {
|
|
461
|
+
const _hoisted_29 = { class: "gt-playback-rate-text" };
|
|
462
|
+
const _hoisted_30 = {
|
|
463
|
+
key: 0,
|
|
464
|
+
class: "gt-playback-rate-menu"
|
|
465
|
+
};
|
|
466
|
+
const _hoisted_31 = ["onClick"];
|
|
467
|
+
const _hoisted_32 = ["title"];
|
|
468
|
+
const _hoisted_33 = ["title"];
|
|
469
|
+
const _hoisted_34 = {
|
|
451
470
|
key: 0,
|
|
452
471
|
viewBox: "0 0 24 24",
|
|
453
472
|
fill: "currentColor"
|
|
454
473
|
};
|
|
455
|
-
const
|
|
474
|
+
const _hoisted_35 = {
|
|
456
475
|
key: 1,
|
|
457
476
|
viewBox: "0 0 24 24",
|
|
458
477
|
fill: "currentColor"
|
|
@@ -470,10 +489,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
470
489
|
const canvasRef = ref(null);
|
|
471
490
|
const containerRef = ref(null);
|
|
472
491
|
const isFullscreen = ref(false);
|
|
492
|
+
const playbackRates = [1, 2, 4];
|
|
493
|
+
const currentPlaybackRate = ref(1);
|
|
494
|
+
const showPlaybackRateMenu = ref(false);
|
|
473
495
|
const controlOption = computed(() => ({
|
|
474
496
|
show: props.controlOption?.show ?? DEFAULT_EC_PLAYER_PROPS.controlOption.show,
|
|
475
497
|
fullscreen: props.controlOption?.fullscreen ?? DEFAULT_EC_PLAYER_PROPS.controlOption.fullscreen,
|
|
476
|
-
info: props.controlOption?.info ?? DEFAULT_EC_PLAYER_PROPS.controlOption.info
|
|
498
|
+
info: props.controlOption?.info ?? DEFAULT_EC_PLAYER_PROPS.controlOption.info,
|
|
499
|
+
playbackRate: props.controlOption?.playbackRate ?? DEFAULT_EC_PLAYER_PROPS.controlOption.playbackRate
|
|
477
500
|
}));
|
|
478
501
|
const { envInfo, showEnvPanel, envTypeText, toggleEnvPanel } = useEnvInfo(false);
|
|
479
502
|
const player = usePlayer(emit);
|
|
@@ -523,6 +546,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
523
546
|
}
|
|
524
547
|
}
|
|
525
548
|
}
|
|
549
|
+
function setPlaybackRate(rate) {
|
|
550
|
+
currentPlaybackRate.value = rate;
|
|
551
|
+
showPlaybackRateMenu.value = false;
|
|
552
|
+
player.setPlaybackRate(rate);
|
|
553
|
+
}
|
|
554
|
+
function togglePlaybackRateMenu() {
|
|
555
|
+
showPlaybackRateMenu.value = !showPlaybackRateMenu.value;
|
|
556
|
+
}
|
|
526
557
|
function handleFullscreenChange() {
|
|
527
558
|
isFullscreen.value = !!document.fullscreenElement;
|
|
528
559
|
}
|
|
@@ -723,8 +754,26 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
723
754
|
style: normalizeStyle({ left: unref(controls).hoverPosition.value + "%" })
|
|
724
755
|
}, toDisplayString(unref(controls).formatTime(unref(controls).hoverTime.value)), 5)) : createCommentVNode("", true)
|
|
725
756
|
], 32)) : (openBlock(), createElementBlock("div", _hoisted_26)),
|
|
757
|
+
controlOption.value.playbackRate && !isLive.value ? (openBlock(), createElementBlock("div", _hoisted_27, [
|
|
758
|
+
createElementVNode("button", {
|
|
759
|
+
class: "gt-control-btn gt-playback-rate-btn",
|
|
760
|
+
onClick: togglePlaybackRateMenu,
|
|
761
|
+
title: "倍速: " + currentPlaybackRate.value + "x"
|
|
762
|
+
}, [
|
|
763
|
+
createElementVNode("span", _hoisted_29, toDisplayString(currentPlaybackRate.value) + "x", 1)
|
|
764
|
+
], 8, _hoisted_28),
|
|
765
|
+
showPlaybackRateMenu.value ? (openBlock(), createElementBlock("div", _hoisted_30, [
|
|
766
|
+
(openBlock(), createElementBlock(Fragment, null, renderList(playbackRates, (rate) => {
|
|
767
|
+
return createElementVNode("button", {
|
|
768
|
+
key: rate,
|
|
769
|
+
class: normalizeClass(["gt-playback-rate-option", { active: currentPlaybackRate.value === rate }]),
|
|
770
|
+
onClick: ($event) => setPlaybackRate(rate)
|
|
771
|
+
}, toDisplayString(rate) + "x ", 11, _hoisted_31);
|
|
772
|
+
}), 64))
|
|
773
|
+
])) : createCommentVNode("", true)
|
|
774
|
+
])) : createCommentVNode("", true),
|
|
726
775
|
controlOption.value.info ? (openBlock(), createElementBlock("button", {
|
|
727
|
-
key:
|
|
776
|
+
key: 5,
|
|
728
777
|
class: "gt-control-btn gt-env-info-btn",
|
|
729
778
|
onClick: _cache[3] || (_cache[3] = //@ts-ignore
|
|
730
779
|
(...args) => unref(toggleEnvPanel) && unref(toggleEnvPanel)(...args)),
|
|
@@ -736,19 +785,19 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
736
785
|
}, [
|
|
737
786
|
createElementVNode("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z" })
|
|
738
787
|
], -1)
|
|
739
|
-
])], 8,
|
|
788
|
+
])], 8, _hoisted_32)) : createCommentVNode("", true),
|
|
740
789
|
controlOption.value.fullscreen ? (openBlock(), createElementBlock("button", {
|
|
741
|
-
key:
|
|
790
|
+
key: 6,
|
|
742
791
|
class: "gt-control-btn gt-fullscreen-btn",
|
|
743
792
|
onClick: toggleFullscreen,
|
|
744
793
|
title: isFullscreen.value ? "退出全屏" : "全屏"
|
|
745
794
|
}, [
|
|
746
|
-
isFullscreen.value ? (openBlock(), createElementBlock("svg",
|
|
795
|
+
isFullscreen.value ? (openBlock(), createElementBlock("svg", _hoisted_34, [..._cache[31] || (_cache[31] = [
|
|
747
796
|
createElementVNode("path", { d: "M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z" }, null, -1)
|
|
748
|
-
])])) : (openBlock(), createElementBlock("svg",
|
|
797
|
+
])])) : (openBlock(), createElementBlock("svg", _hoisted_35, [..._cache[32] || (_cache[32] = [
|
|
749
798
|
createElementVNode("path", { d: "M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" }, null, -1)
|
|
750
799
|
])]))
|
|
751
|
-
], 8,
|
|
800
|
+
], 8, _hoisted_33)) : createCommentVNode("", true)
|
|
752
801
|
], 2)) : createCommentVNode("", true),
|
|
753
802
|
unref(player).state.isLoaded && !unref(player).state.isPlaying && !unref(player).isLoading.value ? (openBlock(), createElementBlock("div", {
|
|
754
803
|
key: 4,
|
|
@@ -774,7 +823,7 @@ const _export_sfc = (sfc, props) => {
|
|
|
774
823
|
}
|
|
775
824
|
return target;
|
|
776
825
|
};
|
|
777
|
-
const EcPlayer = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
826
|
+
const EcPlayer = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-8da5b44d"]]);
|
|
778
827
|
export {
|
|
779
828
|
DEFAULT_EC_PLAYER_PROPS,
|
|
780
829
|
DEFAULT_PLAYER_OPTIONS,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/types.ts","../src/composables/usePlayer.ts","../src/composables/useControls.ts","../src/composables/useEnvInfo.ts","../src/components/EcPlayer.vue"],"sourcesContent":["/**\n * Vue 组件类型定义\n */\n\nimport type { EcPlayerCoreConfig, EcPlayerState, EnvInfo } from '@give-tech/ec-player'\nexport { LogLevel } from '@give-tech/ec-player'\n\n/**\n * WASM 路径配置\n */\nexport interface WasmPathConfig {\n /**\n * SIMD 版本 WASM 路径(推荐,性能更好)\n * 用于支持 SIMD 的现代浏览器\n */\n simd?: string\n /**\n * 非 SIMD 版本 WASM 路径\n * 用于不支持 SIMD 的旧浏览器作为降级方案\n */\n nonSimd?: string\n}\n\n/**\n * 全局配置\n *\n * 必须在使用 EcPlayer 组件前调用\n *\n * @example\n * ```typescript\n * // main.ts\n * import { configureEcPlayer } from '@give-tech/ec-player-vue'\n *\n * // 配置 SIMD 和非 SIMD 路径,支持自动降级\n * configureEcPlayer({\n * wasm: {\n * simd: '/wasm/decoder-simd.js',\n * nonSimd: '/wasm/decoder.js'\n * }\n * })\n *\n * // 使用 CDN\n * configureEcPlayer({\n * wasm: {\n * simd: 'https://unpkg.com/@give-tech/ec-player@latest/wasm/decoder-simd.js',\n * nonSimd: 'https://unpkg.com/@give-tech/ec-player@latest/wasm/decoder.js'\n * }\n * })\n * ```\n */\nexport interface EcPlayerGlobalConfig {\n /**\n * WASM 路径配置(必填)\n * 支持 SIMD 和非 SIMD 自动降级\n */\n wasm?: WasmPathConfig\n /** 默认是否显示控制条 */\n showControls?: boolean\n /** 默认缓冲目标帧数 */\n targetBufferSize?: number\n /** 默认每批解码帧数 */\n decodeBatchSize?: number\n /** 默认队列上限 */\n maxQueueSize?: number\n}\n\n/**\n * 播放器配置选项\n */\nexport interface PlayerOptions {\n /** 帧缓冲区目标大小 */\n targetBufferSize?: number\n /** 每批解码帧数 */\n decodeBatchSize?: number\n /** NAL/Sample 队列上限 */\n maxQueueSize?: number\n}\n\n/**\n * 视频源配置\n */\nexport interface EcPlayerSource {\n /** 视频 URL */\n url: string\n /** 是否为直播流 */\n isLive?: boolean\n /** 版本号,用于强制重新加载 */\n version?: number\n}\n\n/**\n * 控制条选项\n */\nexport interface EcPlayerControlOption {\n /** 是否显示控制条 */\n show?: boolean\n /** 是否显示全屏按钮 */\n fullscreen?: boolean\n /** 是否显示环境信息按钮 */\n info?: boolean\n}\n\n/**\n * EcPlayer 组件 Props\n */\nexport interface EcPlayerProps {\n /** 视频源 */\n src?: EcPlayerSource\n /** 控制条选项 */\n controlOption?: EcPlayerControlOption\n}\n\n/**\n * EcPlayer 组件 Emits\n */\nexport interface EcPlayerEmits {\n /** 播放时触发 */\n (e: 'play'): void\n /** 暂停时触发 */\n (e: 'pause'): void\n}\n\n/**\n * EcPlayer 组件 Expose 方法\n */\nexport interface EcPlayerExpose {\n /** 播放 */\n play: () => void\n /** 暂停 */\n pause: () => void\n /** 跳转到指定时间(毫秒) */\n seek: (time: number) => Promise<void>\n}\n\n/**\n * 环境信息面板数据\n */\nexport interface EnvPanelData {\n envInfo: EnvInfo | null\n state: Partial<EcPlayerState>\n}\n\n/**\n * 播放器配置(从 Props 转换)\n */\nexport interface PlayerConfigFromProps extends EcPlayerCoreConfig {\n wasmPath: string\n targetBufferSize: number\n decodeBatchSize: number\n maxQueueSize: number\n}\n\n/**\n * 默认 Props 值\n */\nexport const DEFAULT_EC_PLAYER_PROPS = {\n src: undefined as EcPlayerSource | undefined,\n controlOption: {\n show: true,\n fullscreen: true,\n info: true\n }\n}\n\n/**\n * 默认播放器配置\n */\nexport const DEFAULT_PLAYER_OPTIONS: Required<PlayerOptions> = {\n targetBufferSize: 60,\n decodeBatchSize: 2,\n maxQueueSize: 200\n}\n\n/**\n * 默认 WASM 配置\n */\nexport const DEFAULT_WASM_CONFIG: WasmPathConfig = {\n simd: '/wasm/decoder-simd.js',\n nonSimd: '/wasm/decoder.js'\n}\n\n/**\n * 全局配置存储\n */\nlet globalConfig: EcPlayerGlobalConfig = {}\n\n/**\n * 配置 EcPlayer 全局默认值\n *\n * @example\n * ```typescript\n * // main.ts\n * import { configureEcPlayer } from '@give-tech/ec-player-vue'\n *\n * // 配置 SIMD 和非 SIMD 路径,支持自动降级\n * configureEcPlayer({\n * wasm: {\n * simd: '/wasm/decoder-simd.js',\n * nonSimd: '/wasm/decoder.js'\n * }\n * })\n *\n * // 使用 CDN\n * configureEcPlayer({\n * wasm: {\n * simd: 'https://unpkg.com/@give-tech/ec-player@latest/wasm/decoder-simd.js',\n * nonSimd: 'https://unpkg.com/@give-tech/ec-player@latest/wasm/decoder.js'\n * }\n * })\n * ```\n */\nexport function configureEcPlayer(config: EcPlayerGlobalConfig): void {\n globalConfig = { ...globalConfig, ...config }\n}\n\n/**\n * 获取全局配置\n */\nexport function getGlobalConfig(): EcPlayerGlobalConfig {\n return { ...globalConfig }\n}\n\n/**\n * 获取 WASM 路径配置\n */\nexport function getWasmConfig(): WasmPathConfig {\n return {\n simd: globalConfig.wasm?.simd ?? DEFAULT_WASM_CONFIG.simd,\n nonSimd: globalConfig.wasm?.nonSimd ?? DEFAULT_WASM_CONFIG.nonSimd\n }\n}\n\n/**\n * 获取合并后的配置(props > 全局配置 > 默认值)\n */\nexport function getMergedConfig(props: EcPlayerProps) {\n return {\n src: props.src ?? DEFAULT_EC_PLAYER_PROPS.src,\n controlOption: {\n show: props.controlOption?.show ?? globalConfig.showControls ?? DEFAULT_EC_PLAYER_PROPS.controlOption.show,\n fullscreen: props.controlOption?.fullscreen ?? DEFAULT_EC_PLAYER_PROPS.controlOption.fullscreen,\n info: props.controlOption?.info ?? DEFAULT_EC_PLAYER_PROPS.controlOption.info\n }\n }\n}\n\n/**\n * 获取合并后的播放器配置(options > 全局配置 > 默认值)\n */\nexport function getMergedPlayerOptions(options: PlayerOptions): Required<PlayerOptions> {\n return {\n targetBufferSize: options.targetBufferSize ?? globalConfig.targetBufferSize ?? DEFAULT_PLAYER_OPTIONS.targetBufferSize,\n decodeBatchSize: options.decodeBatchSize ?? globalConfig.decodeBatchSize ?? DEFAULT_PLAYER_OPTIONS.decodeBatchSize,\n maxQueueSize: options.maxQueueSize ?? globalConfig.maxQueueSize ?? DEFAULT_PLAYER_OPTIONS.maxQueueSize\n }\n}\n\n/**\n * 根据环境能力选择合适的 WASM 路径\n *\n * @param hasSimdSupport 是否支持 SIMD\n * @returns 实际使用的 WASM 路径\n */\nexport function resolveWasmPath(hasSimdSupport: boolean): string {\n const wasmConfig = getWasmConfig()\n\n // 根据 SIMD 支持情况选择\n if (hasSimdSupport && wasmConfig.simd) {\n console.log('[EcPlayer] Using SIMD WASM:', wasmConfig.simd)\n return wasmConfig.simd\n }\n\n if (wasmConfig.nonSimd) {\n console.log('[EcPlayer] SIMD not supported, using non-SIMD WASM:', wasmConfig.nonSimd)\n return wasmConfig.nonSimd\n }\n\n // 降级到 SIMD 版本(兜底)\n console.log('[EcPlayer] No non-SIMD path configured, falling back to SIMD:', wasmConfig.simd)\n return wasmConfig.simd!\n}\n\n/**\n * 预加载 WASM 模块\n *\n * @example\n * import { preloadWasm } from '@give-tech/ec-player-vue'\n * preloadWasm() // 预加载所有\n * preloadWasm({ preloadNonSimd: false }) // 只预加载 SIMD\n */\nexport function preloadWasm(options?: {\n preloadSimd?: boolean\n preloadNonSimd?: boolean\n}): void {\n const { preloadSimd = true, preloadNonSimd = true } = options ?? {}\n const wasmConfig = getWasmConfig()\n const paths: string[] = []\n\n if (preloadSimd && wasmConfig.simd) {\n paths.push(wasmConfig.simd)\n }\n if (preloadNonSimd && wasmConfig.nonSimd) {\n paths.push(wasmConfig.nonSimd)\n }\n\n if (paths.length > 0) {\n import('@give-tech/ec-player').then(({ WASMLoader }) => {\n WASMLoader.preloadAll(paths)\n console.log('[EcPlayer] Preloading WASM:', paths)\n }).catch(err => {\n console.warn('[EcPlayer] Failed to preload WASM:', err)\n })\n }\n}\n","/**\n * 播放器核心逻辑\n */\n\nimport { ref, shallowRef, reactive, onUnmounted, type Ref } from 'vue'\nimport {\n EcPlayerCore,\n EnvDetector,\n setLogLevel as coreSetLogLevel,\n type EcPlayerCoreConfig,\n type EcPlayerState,\n type EcPlayerCallbacks\n} from '@give-tech/ec-player'\nimport type { EcPlayerProps, PlayerOptions } from '../types'\nimport { resolveWasmPath, DEFAULT_PLAYER_OPTIONS, getGlobalConfig } from '../types'\n\n/**\n * 播放器逻辑返回值\n */\nexport interface UsePlayerReturn {\n /** Canvas 元素引用 */\n canvasRef: Ref<HTMLCanvasElement | null>\n /** 播放器实例 */\n player: Ref<EcPlayerCore | null>\n /** 响应式状态 */\n state: EcPlayerState\n /** 是否正在加载 */\n isLoading: Ref<boolean>\n /** 检测到的格式 */\n detectedFormat: Ref<string>\n /** 是否为直播流 */\n isLive: Ref<boolean>\n /** 播放 */\n play: (options: { url: string; isLive?: boolean }) => Promise<void>\n /** 设置配置 */\n setOptions: (options: PlayerOptions) => void\n /** 设置日志级别 */\n setLogLevel: (level: number) => void\n /** 暂停 */\n pause: () => void\n /** 恢复播放 */\n resume: () => Promise<void>\n /** 跳转 */\n seek: (time: number) => Promise<void>\n /** 获取播放器实例 */\n getPlayer: () => EcPlayerCore | null\n /** 获取状态 */\n getState: () => EcPlayerState\n /** 获取当前时间 */\n getCurrentTime: () => number\n /** 获取总时长 */\n getDuration: () => number\n /** 销毁播放器 */\n destroy: () => void\n}\n\n/**\n * 从配置选项创建播放器配置\n */\nfunction createConfig(options: Required<PlayerOptions>): Omit<EcPlayerCoreConfig, 'isLive'> {\n // 检测 SIMD 支持\n const envInfo = EnvDetector.detect()\n const wasmPath = resolveWasmPath(envInfo.capabilities.wasmSimd)\n\n return {\n wasmPath,\n targetBufferSize: options.targetBufferSize,\n decodeBatchSize: options.decodeBatchSize,\n maxQueueSize: options.maxQueueSize\n }\n}\n\n/**\n * 播放器逻辑 Hook\n */\nexport function usePlayer(\n emit: {\n (e: 'play'): void\n (e: 'pause'): void\n }\n): UsePlayerReturn {\n const canvasRef = ref<HTMLCanvasElement | null>(null)\n const player = shallowRef<EcPlayerCore | null>(null)\n const isLoading = ref(false)\n const detectedFormat = ref('')\n const isLive = ref(false) // 跟踪当前是否为直播流\n\n // 用于追踪最新的 play 请求,解决快速切换源时的竞态条件\n let playRequestId = 0\n\n // 当前播放器配置(初始化时合并全局配置和默认值)\n const globalConfig = getGlobalConfig()\n const currentOptions = reactive<Required<PlayerOptions>>({\n targetBufferSize: globalConfig.targetBufferSize ?? DEFAULT_PLAYER_OPTIONS.targetBufferSize,\n decodeBatchSize: globalConfig.decodeBatchSize ?? DEFAULT_PLAYER_OPTIONS.decodeBatchSize,\n maxQueueSize: globalConfig.maxQueueSize ?? DEFAULT_PLAYER_OPTIONS.maxQueueSize\n })\n\n // 响应式状态\n const state = reactive<EcPlayerState>({\n isPlaying: false,\n isLoaded: false,\n isLoading: false,\n fps: 0,\n resolution: '-',\n decoded: 0,\n downloaded: 0,\n droppedFrames: 0,\n isPrefetching: false,\n segmentIndex: 0,\n fetchedSegmentCount: 0,\n totalSegments: 0,\n downloadSpeed: 0,\n currentTime: 0,\n duration: 0\n })\n\n // 创建回调\n const callbacks: EcPlayerCallbacks = {\n onStateChange: (partial) => {\n Object.assign(state, partial)\n\n // 派发 play/pause 事件\n if (partial.isPlaying === true) {\n emit('play')\n } else if (partial.isPlaying === false && state.isPlaying) {\n emit('pause')\n }\n },\n onError: (error) => {\n console.error('[EcPlayer] Error:', error)\n },\n onReady: () => {\n // 第一帧已准备好,取消 loading 状态\n isLoading.value = false\n console.log('[EcPlayer] First frame ready, loading finished')\n }\n }\n\n // 播放(加载并播放)\n async function play(options: { url: string; isLive?: boolean }): Promise<void> {\n const { url, isLive: isLiveParam = false } = options\n if (!url) {\n console.error('[EcPlayer] URL is required')\n return\n }\n\n // 递增请求 ID,用于追踪这次调用\n const currentRequestId = ++playRequestId\n console.log('[EcPlayer] play() called, requestId:', currentRequestId)\n\n // 如果正在加载中,先销毁当前播放器\n if (isLoading.value && player.value) {\n console.log('[EcPlayer] Aborting current load to start new one...')\n player.value.destroy()\n player.value = null\n }\n\n // 等待 canvas 准备好\n let retries = 10\n while (!canvasRef.value && retries > 0) {\n await new Promise(resolve => setTimeout(resolve, 100))\n retries--\n }\n\n // 检查是否有更新的请求\n if (currentRequestId !== playRequestId) {\n console.log('[EcPlayer] Request obsolete after waiting for canvas, aborting')\n return\n }\n\n if (!canvasRef.value) {\n console.error('[EcPlayer] Canvas element not found')\n return\n }\n\n isLoading.value = true\n isLive.value = isLiveParam\n\n try {\n // 销毁旧播放器\n if (player.value) {\n player.value.destroy()\n player.value = null\n }\n\n // 重置状态\n state.isPlaying = false\n state.isLoaded = false\n state.fps = 0\n state.resolution = '-'\n state.decoded = 0\n state.downloaded = 0\n state.droppedFrames = 0\n state.segmentIndex = 0\n state.totalSegments = 0\n state.downloadSpeed = 0\n state.currentTime = 0\n state.duration = 0\n detectedFormat.value = ''\n\n // 创建配置\n const config: EcPlayerCoreConfig & { canvas: HTMLCanvasElement } = {\n ...createConfig(currentOptions),\n canvas: canvasRef.value,\n isLive: isLiveParam\n }\n\n // 创建播放器\n player.value = new EcPlayerCore(config, callbacks)\n\n // 加载视频\n await player.value.load(url, isLiveParam)\n\n // 检查是否有更新的请求\n if (currentRequestId !== playRequestId) {\n console.log('[EcPlayer] Request obsolete after load, aborting')\n // 销毁刚创建的播放器\n if (player.value) {\n player.value.destroy()\n player.value = null\n }\n return\n }\n\n // 获取检测到的格式\n detectedFormat.value = player.value.getDetectedFormat()\n\n // 标记加载完成\n state.isLoaded = true\n\n // 开始播放\n await player.value.play()\n\n console.log('[EcPlayer] Playing stream, format:', detectedFormat.value)\n } catch (error: any) {\n console.error('[EcPlayer] Failed to play:', error?.message || error)\n // 发生错误时也要取消 loading 状态\n if (currentRequestId === playRequestId) {\n isLoading.value = false\n }\n }\n // 注意:isLoading 不在 finally 中重置,而是等待 onReady 事件\n // 这样可以确保转圈动画持续到第一帧准备好为止\n }\n\n // 设置配置\n function setOptions(options: PlayerOptions): void {\n if (options.targetBufferSize !== undefined) {\n currentOptions.targetBufferSize = options.targetBufferSize\n }\n if (options.decodeBatchSize !== undefined) {\n currentOptions.decodeBatchSize = options.decodeBatchSize\n }\n if (options.maxQueueSize !== undefined) {\n currentOptions.maxQueueSize = options.maxQueueSize\n }\n console.log('[EcPlayer] Options updated:', currentOptions)\n }\n\n // 设置日志级别\n function setLogLevel(level: number): void {\n coreSetLogLevel(level)\n }\n\n // 暂停\n function pause(): void {\n player.value?.pause()\n }\n\n // 恢复播放\n async function resume(): Promise<void> {\n if (!player.value) return\n await player.value.play()\n }\n\n // 跳转\n async function seek(time: number): Promise<void> {\n if (!player.value) return\n await player.value.seek(time)\n }\n\n // 获取播放器实例\n function getPlayer(): EcPlayerCore | null {\n return player.value\n }\n\n // 获取状态\n function getState(): EcPlayerState {\n return player.value?.getState() ?? { ...state }\n }\n\n // 获取当前时间\n function getCurrentTime(): number {\n return player.value?.getCurrentTime() ?? 0\n }\n\n // 获取总时长\n function getDuration(): number {\n return player.value?.getDuration() ?? 0\n }\n\n // 销毁播放器\n function destroy(): void {\n if (player.value) {\n player.value.destroy()\n player.value = null\n }\n }\n\n // 组件卸载时销毁\n onUnmounted(() => {\n destroy()\n })\n\n return {\n canvasRef,\n player,\n state,\n isLoading,\n detectedFormat,\n isLive,\n play,\n setOptions,\n setLogLevel,\n pause,\n resume,\n seek,\n getPlayer,\n getState,\n getCurrentTime,\n getDuration,\n destroy\n }\n}\n","/**\n * 播放器控制条逻辑\n */\n\nimport { ref, computed, type Ref } from 'vue'\n\n/**\n * 控制条逻辑参数\n */\nexport interface UseControlsParams {\n /** 是否正在播放 */\n isPlaying: Ref<boolean>\n /** 是否已加载 */\n isLoaded: Ref<boolean>\n /** 当前时间(毫秒) */\n currentTime: Ref<number>\n /** 总时长(毫秒) */\n duration: Ref<number>\n /** 已解析的分片索引 */\n segmentIndex: Ref<number>\n /** 已下载的分片总数 */\n fetchedSegmentCount: Ref<number>\n /** 总分片数 */\n totalSegments: Ref<number>\n /** 是否为直播流 */\n isLive: Ref<boolean>\n /** 跳转方法 */\n seek: (time: number) => Promise<void>\n}\n\n/**\n * 控制条逻辑返回值\n */\nexport interface UseControlsReturn {\n /** 是否显示控制条 */\n showControls: Ref<boolean>\n /** 进度条 hover 时间 */\n hoverTime: Ref<number | null>\n /** 进度条 hover 位置 */\n hoverPosition: Ref<number>\n /** 播放进度百分比 */\n playProgress: Ref<number>\n /** 缓冲进度百分比 */\n bufferProgress: Ref<number>\n /** 显示控制条 */\n showControlsBar: () => void\n /** 隐藏控制条 */\n hideControlsBar: () => void\n /** 处理进度条点击 */\n handleProgressClick: (event: MouseEvent) => Promise<void>\n /** 处理进度条悬停 */\n handleProgressHover: (event: MouseEvent) => void\n /** 格式化时间 */\n formatTime: (ms: number) => string\n}\n\n/**\n * 控制条逻辑 Hook\n */\nexport function useControls(params: UseControlsParams): UseControlsReturn {\n let hideControlsTimer: number | null = null\n const {\n isPlaying,\n isLoaded,\n currentTime,\n duration,\n segmentIndex,\n fetchedSegmentCount,\n totalSegments,\n isLive,\n seek\n } = params\n\n const showControls = ref(true)\n const hoverTime = ref<number | null>(null)\n const hoverPosition = ref(0)\n\n // 计算播放进度\n const playProgress = computed(() => {\n if (duration.value === 0) return 0\n return (currentTime.value / duration.value) * 100\n })\n\n // 计算缓冲进度(已下载的分段数)\n const bufferProgress = computed(() => {\n if (totalSegments.value === 0) return 0\n return (fetchedSegmentCount.value / totalSegments.value) * 100\n })\n\n // 显示控制条\n function showControlsBar(): void {\n showControls.value = true\n if (hideControlsTimer) {\n clearTimeout(hideControlsTimer)\n }\n hideControlsTimer = window.setTimeout(() => {\n if (isPlaying.value) {\n showControls.value = false\n }\n }, 3000)\n }\n\n // 隐藏控制条\n function hideControlsBar(): void {\n if (isPlaying.value) {\n showControls.value = false\n }\n }\n\n // 处理进度条点击\n async function handleProgressClick(event: MouseEvent): Promise<void> {\n if (duration.value === 0) return\n\n const target = event.currentTarget as HTMLElement\n const rect = target.getBoundingClientRect()\n const clickX = event.clientX - rect.left\n const percentage = clickX / rect.width\n const targetTime = percentage * duration.value\n\n await seek(targetTime)\n }\n\n // 处理进度条悬停\n function handleProgressHover(event: MouseEvent): void {\n if (duration.value === 0) return\n\n const target = event.currentTarget as HTMLElement\n const rect = target.getBoundingClientRect()\n const hoverX = event.clientX - rect.left\n const percentage = Math.max(0, Math.min(1, hoverX / rect.width))\n\n hoverTime.value = percentage * duration.value\n hoverPosition.value = percentage * 100\n }\n\n // 格式化时间\n function formatTime(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000)\n const hours = Math.floor(totalSeconds / 3600)\n const minutes = Math.floor((totalSeconds % 3600) / 60)\n const seconds = totalSeconds % 60\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`\n }\n return `${minutes}:${seconds.toString().padStart(2, '0')}`\n }\n\n return {\n showControls,\n hoverTime,\n hoverPosition,\n playProgress,\n bufferProgress,\n showControlsBar,\n hideControlsBar,\n handleProgressClick,\n handleProgressHover,\n formatTime\n }\n}\n","/**\n * 环境信息逻辑\n */\n\nimport { ref, computed, onMounted, type Ref } from 'vue'\nimport { EnvDetector, type EnvInfo } from '@give-tech/ec-player'\n\n/**\n * 环境信息逻辑返回值\n */\nexport interface UseEnvInfoReturn {\n /** 环境信息 */\n envInfo: Ref<EnvInfo | null>\n /** 是否显示环境面板 */\n showEnvPanel: Ref<boolean>\n /** 环境类型文本 */\n envTypeText: Ref<string>\n /** 切换环境面板显示 */\n toggleEnvPanel: () => void\n /** 检测环境 */\n detectEnv: () => void\n}\n\n/**\n * 环境信息逻辑 Hook\n */\nexport function useEnvInfo(\n initialShowPanel: boolean = false\n): UseEnvInfoReturn {\n const envInfo = ref<EnvInfo | null>(null)\n const showEnvPanel = ref(initialShowPanel)\n\n // 环境类型文本\n const envTypeText = computed(() => {\n if (!envInfo.value) return '未知'\n const typeMap: Record<string, string> = {\n 'pc-browser': 'PC 浏览器',\n 'mobile-browser': '移动端浏览器',\n 'wechat-miniprogram': '微信小程序',\n 'alipay-miniprogram': '支付宝小程序',\n 'other-miniprogram': '其他小程序',\n 'unknown': '未知',\n }\n return typeMap[envInfo.value.platform] || envInfo.value.platform\n })\n\n // 切换环境面板显示\n function toggleEnvPanel(): void {\n showEnvPanel.value = !showEnvPanel.value\n }\n\n // 检测环境\n function detectEnv(): void {\n envInfo.value = EnvDetector.detect()\n console.log('[EcPlayer] 环境检测结果:', envInfo.value)\n }\n\n // 组件挂载时检测环境\n onMounted(() => {\n detectEnv()\n })\n\n return {\n envInfo,\n showEnvPanel,\n envTypeText,\n toggleEnvPanel,\n detectEnv\n }\n}\n","<template>\n <div class=\"gt-player-container\" ref=\"containerRef\">\n <div\n class=\"gt-video-wrapper\"\n ref=\"videoWrapperRef\"\n @mouseenter=\"controls.showControlsBar\"\n @mousemove=\"controls.showControlsBar\"\n @mouseleave=\"controls.hideControlsBar\"\n >\n <!-- Canvas 视频渲染 -->\n <canvas ref=\"canvasRef\" class=\"gt-player-canvas\"></canvas>\n\n <!-- 封面/占位内容(未加载时显示) -->\n <div v-if=\"!player.state.isLoaded\" class=\"gt-placeholder\">\n <slot name=\"placeholder\"></slot>\n </div>\n\n <!-- 环境信息面板 -->\n <div v-if=\"showEnvPanel && envInfo\" class=\"gt-env-panel\">\n <div class=\"gt-env-row\">\n <span>platform</span>\n <span :class=\"envInfo.isMiniProgram ? 'warn' : ''\">{{ envTypeText }}</span>\n </div>\n <div class=\"gt-env-divider\"></div>\n <div class=\"gt-env-row\">\n <span>SIMD</span>\n <span :class=\"envInfo.capabilities.wasmSimd ? 'ok' : 'err'\">\n {{ envInfo.capabilities.wasmSimd ? 'Yes' : 'No' }}\n </span>\n </div>\n <div class=\"gt-env-row\">\n <span>WebGL</span>\n <span :class=\"envInfo.capabilities.webGL ? 'ok' : 'err'\">\n {{ envInfo.capabilities.webGL ? 'Yes' : 'No' }}\n </span>\n </div>\n <div class=\"gt-env-row\">\n <span>WebGL2</span>\n <span :class=\"envInfo.capabilities.webGL2 ? 'ok' : 'err'\">\n {{ envInfo.capabilities.webGL2 ? 'Yes' : 'No' }}\n </span>\n </div>\n <div class=\"gt-env-row\">\n <span>SAB</span>\n <span :class=\"envInfo.capabilities.sharedArrayBuffer ? 'ok' : 'err'\">\n {{ envInfo.capabilities.sharedArrayBuffer ? 'Yes' : 'No' }}\n </span>\n </div>\n <div class=\"gt-env-row\">\n <span>Threads</span>\n <span :class=\"envInfo.capabilities.wasmThreads ? 'ok' : 'err'\">\n {{ envInfo.capabilities.wasmThreads ? 'Yes' : 'No' }}\n </span>\n </div>\n <div class=\"gt-env-row\">\n <span>WebAudio</span>\n <span :class=\"envInfo.capabilities.webAudio ? 'ok' : 'err'\">\n {{ envInfo.capabilities.webAudio ? 'Yes' : 'No' }}\n </span>\n </div>\n <div class=\"gt-env-row\">\n <span>Stream</span>\n <span :class=\"envInfo.capabilities.readableStream ? 'ok' : 'err'\">\n {{ envInfo.capabilities.readableStream ? 'Yes' : 'No' }}\n </span>\n </div>\n <template v-if=\"player.state.isLoaded\">\n <div class=\"gt-env-divider\"></div>\n <div class=\"gt-env-row\" v-if=\"player.detectedFormat.value\"><span>Format</span><span>{{ player.detectedFormat.value }}</span></div>\n <div class=\"gt-env-row\"><span>FPS</span><span>{{ player.state.fps }}</span></div>\n <div class=\"gt-env-row\"><span>Resolution</span><span>{{ player.state.resolution }}</span></div>\n <div class=\"gt-env-row\"><span>downloaded</span><span>{{ player.state.downloaded }}</span></div>\n <div class=\"gt-env-row\"><span>decoded</span><span>{{ player.state.decoded }}</span></div>\n <div class=\"gt-env-row\"><span>Dropped</span><span>{{ player.state.droppedFrames }}</span></div>\n <div class=\"gt-env-row\"><span>Speed</span><span>{{ player.state.downloadSpeed || 0 }} KB/s</span></div>\n </template>\n </div>\n\n <!-- 加载中动画 -->\n <div class=\"gt-loading-spinner\" v-if=\"player.isLoading.value\">\n <slot name=\"loading\">\n <div class=\"gt-spinner\"></div>\n </slot>\n </div>\n\n <!-- 视频控制条 -->\n <div\n v-if=\"controlOption.show\"\n class=\"gt-video-controls\"\n :class=\"{ visible: controls.showControls.value || !player.state.isPlaying }\"\n >\n <button class=\"gt-control-btn\" @click=\"togglePlayback\">\n <svg v-if=\"player.state.isPlaying\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n </svg>\n <svg v-else viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\"/>\n </svg>\n </button>\n\n <!-- 直播标识 -->\n <span class=\"gt-live-indicator\" v-if=\"isLive\">\n <span class=\"gt-live-dot\"></span>\n <span class=\"gt-live-text\">实时</span>\n </span>\n\n <!-- 点播时间显示 -->\n <span class=\"gt-time-display\" v-else>\n <span class=\"gt-time-current\">{{ controls.formatTime(player.state.currentTime) }}</span>\n <span class=\"gt-time-separator\">/</span>\n <span class=\"gt-time-duration\">{{ controls.formatTime(player.state.duration) }}</span>\n </span>\n\n <!-- 进度条 (仅点播) -->\n <div\n v-if=\"!isLive\"\n class=\"gt-progress-container\"\n @click=\"controls.handleProgressClick\"\n @mousemove=\"controls.handleProgressHover\"\n @mouseleave=\"controls.hoverTime.value = null\"\n >\n <div class=\"gt-progress-bar\">\n <div class=\"gt-progress-buffered\" :style=\"{ width: controls.bufferProgress.value + '%' }\"></div>\n <div class=\"gt-progress-played\" :style=\"{ width: controls.playProgress.value + '%' }\">\n <div class=\"gt-progress-handle\"></div>\n </div>\n </div>\n <div\n class=\"gt-progress-tooltip\"\n v-if=\"controls.hoverTime.value !== null\"\n :style=\"{ left: controls.hoverPosition.value + '%' }\"\n >\n {{ controls.formatTime(controls.hoverTime.value) }}\n </div>\n </div>\n\n <!-- 直播流占位符 -->\n <div class=\"gt-flex-spacer\" v-else></div>\n\n <!-- 环境信息按钮 -->\n <button v-if=\"controlOption.info\" class=\"gt-control-btn gt-env-info-btn\" @click=\"toggleEnvPanel\" :title=\"showEnvPanel ? '隐藏信息' : '显示信息'\">\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z\"/>\n </svg>\n </button>\n\n <!-- 全屏按钮 -->\n <button v-if=\"controlOption.fullscreen\" class=\"gt-control-btn gt-fullscreen-btn\" @click=\"toggleFullscreen\" :title=\"isFullscreen ? '退出全屏' : '全屏'\">\n <!-- 退出全屏图标 -->\n <svg v-if=\"isFullscreen\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z\"/>\n </svg>\n <!-- 全屏图标 -->\n <svg v-else viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"/>\n </svg>\n </button>\n </div>\n\n <!-- 大播放按钮(居中) -->\n <div\n class=\"gt-center-play-btn\"\n v-if=\"player.state.isLoaded && !player.state.isPlaying && !player.isLoading.value\"\n @click=\"togglePlayback\"\n >\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\"/>\n </svg>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch, onMounted, onUnmounted } from 'vue'\nimport { usePlayer } from '../composables/usePlayer'\nimport { useControls } from '../composables/useControls'\nimport { useEnvInfo } from '../composables/useEnvInfo'\nimport type { EcPlayerProps, EcPlayerExpose, EcPlayerSource, EcPlayerControlOption } from '../types'\nimport { DEFAULT_EC_PLAYER_PROPS } from '../types'\n\n// Props\nconst props = withDefaults(defineProps<EcPlayerProps>(), DEFAULT_EC_PLAYER_PROPS)\n\n// Emits\nconst emit = defineEmits<{\n (e: 'play'): void\n (e: 'pause'): void\n}>()\n\n// Canvas ref(本地)\nconst canvasRef = ref<HTMLCanvasElement | null>(null)\n\n// 容器引用(用于全屏)\nconst containerRef = ref<HTMLElement | null>(null)\n\n// 全屏状态\nconst isFullscreen = ref(false)\n\n// 解析 controlOption\nconst controlOption = computed<Required<EcPlayerControlOption>>(() => ({\n show: props.controlOption?.show ?? DEFAULT_EC_PLAYER_PROPS.controlOption.show,\n fullscreen: props.controlOption?.fullscreen ?? DEFAULT_EC_PLAYER_PROPS.controlOption.fullscreen,\n info: props.controlOption?.info ?? DEFAULT_EC_PLAYER_PROPS.controlOption.info\n}))\n\n// 环境信息逻辑\nconst { envInfo, showEnvPanel, envTypeText, toggleEnvPanel } = useEnvInfo(false)\n\n// 播放器逻辑\nconst player = usePlayer(emit)\n\n// 同步 canvas ref 到 player\nwatch(canvasRef, (el) => {\n player.canvasRef.value = el\n}, { immediate: true })\n\n// isLive 计算属性(用于模板)\nconst isLive = computed(() => player.isLive.value)\n\n// 控制条逻辑\nconst isPlayingRef = computed(() => player.state.isPlaying)\nconst isLoadedRef = computed(() => player.state.isLoaded)\nconst currentTimeRef = computed(() => player.state.currentTime)\nconst durationRef = computed(() => player.state.duration)\nconst segmentIndexRef = computed(() => player.state.segmentIndex)\nconst fetchedSegmentCountRef = computed(() => player.state.fetchedSegmentCount)\nconst totalSegmentsRef = computed(() => player.state.totalSegments)\n\nconst controls = useControls({\n isPlaying: isPlayingRef,\n isLoaded: isLoadedRef,\n currentTime: currentTimeRef,\n duration: durationRef,\n segmentIndex: segmentIndexRef,\n fetchedSegmentCount: fetchedSegmentCountRef,\n totalSegments: totalSegmentsRef,\n isLive,\n seek: player.seek\n})\n\n// 视频包装器引用\nconst videoWrapperRef = ref<HTMLElement | null>(null)\n\n// 解析 src\nfunction parseSrc(src: EcPlayerSource | undefined): { url: string; isLive: boolean } | null {\n if (!src || !src.url) return null\n return { url: src.url, isLive: src.isLive ?? false }\n}\n\n// 切换播放/暂停\nfunction togglePlayback(): void {\n if (player.state.isPlaying) {\n player.pause()\n } else {\n player.resume()\n }\n}\n\n// 切换全屏\nfunction toggleFullscreen(): void {\n if (!containerRef.value) return\n\n if (!isFullscreen.value) {\n if (containerRef.value.requestFullscreen) {\n containerRef.value.requestFullscreen()\n }\n } else {\n if (document.exitFullscreen) {\n document.exitFullscreen()\n }\n }\n}\n\n// 监听全屏变化\nfunction handleFullscreenChange(): void {\n isFullscreen.value = !!document.fullscreenElement\n}\n\n// 暴露的 play 方法(简化版)\nfunction play(): void {\n const parsed = parseSrc(props.src)\n if (parsed) {\n player.play(parsed)\n }\n}\n\n// 监听 src 变化,自动播放\nwatch(() => props.src, (newSrc) => {\n const parsed = parseSrc(newSrc)\n if (parsed && parsed.url) {\n player.play(parsed)\n }\n}, { immediate: true, deep: true })\n\n// 挂载时监听全屏事件\nonMounted(() => {\n document.addEventListener('fullscreenchange', handleFullscreenChange)\n})\n\n// 卸载时移除监听\nonUnmounted(() => {\n document.removeEventListener('fullscreenchange', handleFullscreenChange)\n})\n\n// Expose 方法\ndefineExpose<EcPlayerExpose>({\n play,\n pause: player.pause,\n seek: player.seek\n})\n</script>\n\n<style scoped>\n.gt-player-container {\n width: 100%;\n height: 100%;\n}\n\n.gt-video-wrapper {\n position: relative;\n width: 100%;\n height: 100%;\n background: #000;\n overflow: hidden;\n}\n\n.gt-player-canvas {\n width: 100%;\n height: 100%;\n object-fit: contain;\n}\n\n.gt-placeholder {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #000;\n}\n\n/* 加载中动画 */\n.gt-loading-spinner {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.5);\n z-index: 10;\n}\n\n.gt-spinner {\n width: 10%;\n max-width: 48px;\n min-width: 20px;\n aspect-ratio: 1/1;\n border: 0.3em solid rgba(255, 255, 255, 0.3);\n border-top-color: #fff;\n border-radius: 50%;\n animation: gt-spin 1s linear infinite;\n}\n\n@keyframes gt-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* 视频控制条 */\n.gt-video-controls {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n padding: 10px 16px;\n background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));\n opacity: 0;\n transition: opacity 0.3s ease;\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.gt-flex-spacer {\n flex: 1;\n}\n\n.gt-video-controls.visible {\n opacity: 1;\n}\n\n.gt-control-btn {\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n\n.gt-control-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n}\n\n.gt-control-btn svg {\n width: 14px;\n height: 14px;\n}\n\n.gt-progress-container {\n flex: 1;\n position: relative;\n cursor: pointer;\n height: 20px;\n display: flex;\n align-items: center;\n}\n\n.gt-progress-bar {\n width: 100%;\n height: 4px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 2px;\n position: relative;\n overflow: hidden;\n transition: height 0.2s ease;\n}\n\n.gt-progress-container:hover .gt-progress-bar {\n height: 6px;\n}\n\n.gt-progress-buffered {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: rgba(255, 255, 255, 0.4);\n border-radius: 2px;\n transition: width 0.1s;\n}\n\n.gt-progress-played {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: #ff2d55;\n border-radius: 2px;\n transition: width 0.1s;\n}\n\n.gt-progress-handle {\n position: absolute;\n right: -6px;\n top: 50%;\n transform: translateY(-50%);\n width: 14px;\n height: 14px;\n background: #ff2d55;\n border-radius: 50%;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n opacity: 0;\n transition: opacity 0.2s, transform 0.2s;\n}\n\n.gt-progress-container:hover .gt-progress-handle {\n opacity: 1;\n transform: translateY(-50%) scale(1.2);\n}\n\n.gt-progress-tooltip {\n position: absolute;\n bottom: calc(100% + 8px);\n transform: translateX(-50%);\n background: rgba(0, 0, 0, 0.85);\n color: white;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 11px;\n white-space: nowrap;\n pointer-events: none;\n}\n\n.gt-time-display {\n color: white;\n font-size: 12px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.gt-time-separator {\n margin: 0 4px;\n opacity: 0.6;\n}\n\n/* 直播指示器 */\n.gt-live-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n color: white;\n font-size: 12px;\n font-weight: 500;\n}\n\n.gt-live-dot {\n width: 8px;\n height: 8px;\n background: #ff2d55;\n border-radius: 50%;\n animation: gt-live-pulse 1.5s ease-in-out infinite;\n}\n\n.gt-live-text {\n color: #ff2d55;\n}\n\n@keyframes gt-live-pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.4;\n }\n}\n\n/* 居中播放按钮 */\n.gt-center-play-btn {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 56px;\n height: 56px;\n background: rgba(0, 0, 0, 0.5);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.gt-center-play-btn:hover {\n background: rgba(0, 0, 0, 0.7);\n transform: translate(-50%, -50%) scale(1.05);\n}\n\n.gt-center-play-btn svg {\n width: 24px;\n height: 24px;\n color: white;\n margin-left: 3px;\n}\n\n/* 环境信息面板 */\n.gt-env-panel {\n position: absolute;\n top: 12px;\n left: 12px;\n background: rgba(0, 0, 0, 0.8);\n border-radius: 6px;\n padding: 8px 10px;\n font-size: 11px;\n font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n min-width: 160px;\n max-width: 200px;\n max-height: calc(100% - 24px);\n overflow-y: auto;\n backdrop-filter: blur(10px);\n animation: gt-env-fade-in 0.15s ease;\n z-index: 15;\n}\n\n.gt-env-panel::-webkit-scrollbar {\n width: 4px;\n}\n\n.gt-env-panel::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.gt-env-panel::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 2px;\n}\n\n@keyframes gt-env-fade-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.gt-env-panel .gt-env-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 2px 0;\n color: rgba(255, 255, 255, 0.7);\n}\n\n.gt-env-panel .gt-env-row span:first-child {\n color: rgba(255, 255, 255, 0.5);\n margin-right: 16px;\n}\n\n.gt-env-panel .gt-env-row span:last-child {\n font-variant-numeric: tabular-nums;\n}\n\n.gt-env-panel .gt-env-row .ok { color: #4caf50; }\n.gt-env-panel .gt-env-row .warn { color: #ff9800; }\n.gt-env-panel .gt-env-row .err { color: #f44336; }\n\n.gt-env-divider {\n height: 1px;\n background: rgba(255, 255, 255, 0.1);\n margin: 4px 0;\n}\n</style>\n"],"names":["WASMLoader","globalConfig","setLogLevel","coreSetLogLevel","_createElementBlock","_createElementVNode","_unref","_openBlock","_renderSlot","_normalizeClass","_Fragment","_toDisplayString","_normalizeStyle"],"mappings":";;;AA2JO,MAAM,0BAA0B;AAAA,EACrC,KAAK;AAAA,EACL,eAAe;AAAA,IACb,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,MAAM;AAAA,EAAA;AAEV;AAKO,MAAM,yBAAkD;AAAA,EAC7D,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,cAAc;AAChB;AAKO,MAAM,sBAAsC;AAAA,EACjD,MAAM;AAAA,EACN,SAAS;AACX;AAKA,IAAI,eAAqC,CAAA;AA2BlC,SAAS,kBAAkB,QAAoC;AACpE,iBAAe,EAAE,GAAG,cAAc,GAAG,OAAA;AACvC;AAKO,SAAS,kBAAwC;AACtD,SAAO,EAAE,GAAG,aAAA;AACd;AAKO,SAAS,gBAAgC;AAC9C,SAAO;AAAA,IACL,MAAM,aAAa,MAAM,QAAQ,oBAAoB;AAAA,IACrD,SAAS,aAAa,MAAM,WAAW,oBAAoB;AAAA,EAAA;AAE/D;AAKO,SAAS,gBAAgB,OAAsB;AACpD,SAAO;AAAA,IACL,KAAK,MAAM,OAAO,wBAAwB;AAAA,IAC1C,eAAe;AAAA,MACb,MAAM,MAAM,eAAe,QAAQ,aAAa,gBAAgB,wBAAwB,cAAc;AAAA,MACtG,YAAY,MAAM,eAAe,cAAc,wBAAwB,cAAc;AAAA,MACrF,MAAM,MAAM,eAAe,QAAQ,wBAAwB,cAAc;AAAA,IAAA;AAAA,EAC3E;AAEJ;AAKO,SAAS,uBAAuB,SAAiD;AACtF,SAAO;AAAA,IACL,kBAAkB,QAAQ,oBAAoB,aAAa,oBAAoB,uBAAuB;AAAA,IACtG,iBAAiB,QAAQ,mBAAmB,aAAa,mBAAmB,uBAAuB;AAAA,IACnG,cAAc,QAAQ,gBAAgB,aAAa,gBAAgB,uBAAuB;AAAA,EAAA;AAE9F;AAQO,SAAS,gBAAgB,gBAAiC;AAC/D,QAAM,aAAa,cAAA;AAGnB,MAAI,kBAAkB,WAAW,MAAM;AACrC,YAAQ,IAAI,+BAA+B,WAAW,IAAI;AAC1D,WAAO,WAAW;AAAA,EACpB;AAEA,MAAI,WAAW,SAAS;AACtB,YAAQ,IAAI,uDAAuD,WAAW,OAAO;AACrF,WAAO,WAAW;AAAA,EACpB;AAGA,UAAQ,IAAI,iEAAiE,WAAW,IAAI;AAC5F,SAAO,WAAW;AACpB;AAUO,SAAS,YAAY,SAGnB;AACP,QAAM,EAAE,cAAc,MAAM,iBAAiB,KAAA,IAAS,WAAW,CAAA;AACjE,QAAM,aAAa,cAAA;AACnB,QAAM,QAAkB,CAAA;AAExB,MAAI,eAAe,WAAW,MAAM;AAClC,UAAM,KAAK,WAAW,IAAI;AAAA,EAC5B;AACA,MAAI,kBAAkB,WAAW,SAAS;AACxC,UAAM,KAAK,WAAW,OAAO;AAAA,EAC/B;AAEA,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO,sBAAsB,EAAE,KAAK,CAAC,EAAE,YAAAA,kBAAiB;AACtD,MAAAA,YAAW,WAAW,KAAK;AAC3B,cAAQ,IAAI,+BAA+B,KAAK;AAAA,IAClD,CAAC,EAAE,MAAM,CAAA,QAAO;AACd,cAAQ,KAAK,sCAAsC,GAAG;AAAA,IACxD,CAAC;AAAA,EACH;AACF;AC9PA,SAAS,aAAa,SAAsE;AAE1F,QAAM,UAAU,YAAY,OAAA;AAC5B,QAAM,WAAW,gBAAgB,QAAQ,aAAa,QAAQ;AAE9D,SAAO;AAAA,IACL;AAAA,IACA,kBAAkB,QAAQ;AAAA,IAC1B,iBAAiB,QAAQ;AAAA,IACzB,cAAc,QAAQ;AAAA,EAAA;AAE1B;AAKO,SAAS,UACd,MAIiB;AACjB,QAAM,YAAY,IAA8B,IAAI;AACpD,QAAM,SAAS,WAAgC,IAAI;AACnD,QAAM,YAAY,IAAI,KAAK;AAC3B,QAAM,iBAAiB,IAAI,EAAE;AAC7B,QAAM,SAAS,IAAI,KAAK;AAGxB,MAAI,gBAAgB;AAGpB,QAAMC,gBAAe,gBAAA;AACrB,QAAM,iBAAiB,SAAkC;AAAA,IACvD,kBAAkBA,cAAa,oBAAoB,uBAAuB;AAAA,IAC1E,iBAAiBA,cAAa,mBAAmB,uBAAuB;AAAA,IACxE,cAAcA,cAAa,gBAAgB,uBAAuB;AAAA,EAAA,CACnE;AAGD,QAAM,QAAQ,SAAwB;AAAA,IACpC,WAAW;AAAA,IACX,UAAU;AAAA,IACV,WAAW;AAAA,IACX,KAAK;AAAA,IACL,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,eAAe;AAAA,IACf,cAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,eAAe;AAAA,IACf,eAAe;AAAA,IACf,aAAa;AAAA,IACb,UAAU;AAAA,EAAA,CACX;AAGD,QAAM,YAA+B;AAAA,IACnC,eAAe,CAAC,YAAY;AAC1B,aAAO,OAAO,OAAO,OAAO;AAG5B,UAAI,QAAQ,cAAc,MAAM;AAC9B,aAAK,MAAM;AAAA,MACb,WAAW,QAAQ,cAAc,SAAS,MAAM,WAAW;AACzD,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAAA,IACA,SAAS,CAAC,UAAU;AAClB,cAAQ,MAAM,qBAAqB,KAAK;AAAA,IAC1C;AAAA,IACA,SAAS,MAAM;AAEb,gBAAU,QAAQ;AAClB,cAAQ,IAAI,gDAAgD;AAAA,IAC9D;AAAA,EAAA;AAIF,iBAAe,KAAK,SAA2D;AAC7E,UAAM,EAAE,KAAK,QAAQ,cAAc,UAAU;AAC7C,QAAI,CAAC,KAAK;AACR,cAAQ,MAAM,4BAA4B;AAC1C;AAAA,IACF;AAGA,UAAM,mBAAmB,EAAE;AAC3B,YAAQ,IAAI,wCAAwC,gBAAgB;AAGpE,QAAI,UAAU,SAAS,OAAO,OAAO;AACnC,cAAQ,IAAI,sDAAsD;AAClE,aAAO,MAAM,QAAA;AACb,aAAO,QAAQ;AAAA,IACjB;AAGA,QAAI,UAAU;AACd,WAAO,CAAC,UAAU,SAAS,UAAU,GAAG;AACtC,YAAM,IAAI,QAAQ,CAAA,YAAW,WAAW,SAAS,GAAG,CAAC;AACrD;AAAA,IACF;AAGA,QAAI,qBAAqB,eAAe;AACtC,cAAQ,IAAI,gEAAgE;AAC5E;AAAA,IACF;AAEA,QAAI,CAAC,UAAU,OAAO;AACpB,cAAQ,MAAM,qCAAqC;AACnD;AAAA,IACF;AAEA,cAAU,QAAQ;AAClB,WAAO,QAAQ;AAEf,QAAI;AAEF,UAAI,OAAO,OAAO;AAChB,eAAO,MAAM,QAAA;AACb,eAAO,QAAQ;AAAA,MACjB;AAGA,YAAM,YAAY;AAClB,YAAM,WAAW;AACjB,YAAM,MAAM;AACZ,YAAM,aAAa;AACnB,YAAM,UAAU;AAChB,YAAM,aAAa;AACnB,YAAM,gBAAgB;AACtB,YAAM,eAAe;AACrB,YAAM,gBAAgB;AACtB,YAAM,gBAAgB;AACtB,YAAM,cAAc;AACpB,YAAM,WAAW;AACjB,qBAAe,QAAQ;AAGvB,YAAM,SAA6D;AAAA,QACjE,GAAG,aAAa,cAAc;AAAA,QAC9B,QAAQ,UAAU;AAAA,QAClB,QAAQ;AAAA,MAAA;AAIV,aAAO,QAAQ,IAAI,aAAa,QAAQ,SAAS;AAGjD,YAAM,OAAO,MAAM,KAAK,KAAK,WAAW;AAGxC,UAAI,qBAAqB,eAAe;AACtC,gBAAQ,IAAI,kDAAkD;AAE9D,YAAI,OAAO,OAAO;AAChB,iBAAO,MAAM,QAAA;AACb,iBAAO,QAAQ;AAAA,QACjB;AACA;AAAA,MACF;AAGA,qBAAe,QAAQ,OAAO,MAAM,kBAAA;AAGpC,YAAM,WAAW;AAGjB,YAAM,OAAO,MAAM,KAAA;AAEnB,cAAQ,IAAI,sCAAsC,eAAe,KAAK;AAAA,IACxE,SAAS,OAAY;AACnB,cAAQ,MAAM,8BAA8B,OAAO,WAAW,KAAK;AAEnE,UAAI,qBAAqB,eAAe;AACtC,kBAAU,QAAQ;AAAA,MACpB;AAAA,IACF;AAAA,EAGF;AAGA,WAAS,WAAW,SAA8B;AAChD,QAAI,QAAQ,qBAAqB,QAAW;AAC1C,qBAAe,mBAAmB,QAAQ;AAAA,IAC5C;AACA,QAAI,QAAQ,oBAAoB,QAAW;AACzC,qBAAe,kBAAkB,QAAQ;AAAA,IAC3C;AACA,QAAI,QAAQ,iBAAiB,QAAW;AACtC,qBAAe,eAAe,QAAQ;AAAA,IACxC;AACA,YAAQ,IAAI,+BAA+B,cAAc;AAAA,EAC3D;AAGA,WAASC,cAAY,OAAqB;AACxCC,gBAAgB,KAAK;AAAA,EACvB;AAGA,WAAS,QAAc;AACrB,WAAO,OAAO,MAAA;AAAA,EAChB;AAGA,iBAAe,SAAwB;AACrC,QAAI,CAAC,OAAO,MAAO;AACnB,UAAM,OAAO,MAAM,KAAA;AAAA,EACrB;AAGA,iBAAe,KAAK,MAA6B;AAC/C,QAAI,CAAC,OAAO,MAAO;AACnB,UAAM,OAAO,MAAM,KAAK,IAAI;AAAA,EAC9B;AAGA,WAAS,YAAiC;AACxC,WAAO,OAAO;AAAA,EAChB;AAGA,WAAS,WAA0B;AACjC,WAAO,OAAO,OAAO,SAAA,KAAc,EAAE,GAAG,MAAA;AAAA,EAC1C;AAGA,WAAS,iBAAyB;AAChC,WAAO,OAAO,OAAO,eAAA,KAAoB;AAAA,EAC3C;AAGA,WAAS,cAAsB;AAC7B,WAAO,OAAO,OAAO,YAAA,KAAiB;AAAA,EACxC;AAGA,WAAS,UAAgB;AACvB,QAAI,OAAO,OAAO;AAChB,aAAO,MAAM,QAAA;AACb,aAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AAGA,cAAY,MAAM;AAChB,YAAA;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IAAA,aACAD;AAAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;ACnRO,SAAS,YAAY,QAA8C;AACxE,MAAI,oBAAmC;AACvC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACE;AAEJ,QAAM,eAAe,IAAI,IAAI;AAC7B,QAAM,YAAY,IAAmB,IAAI;AACzC,QAAM,gBAAgB,IAAI,CAAC;AAG3B,QAAM,eAAe,SAAS,MAAM;AAClC,QAAI,SAAS,UAAU,EAAG,QAAO;AACjC,WAAQ,YAAY,QAAQ,SAAS,QAAS;AAAA,EAChD,CAAC;AAGD,QAAM,iBAAiB,SAAS,MAAM;AACpC,QAAI,cAAc,UAAU,EAAG,QAAO;AACtC,WAAQ,oBAAoB,QAAQ,cAAc,QAAS;AAAA,EAC7D,CAAC;AAGD,WAAS,kBAAwB;AAC/B,iBAAa,QAAQ;AACrB,QAAI,mBAAmB;AACrB,mBAAa,iBAAiB;AAAA,IAChC;AACA,wBAAoB,OAAO,WAAW,MAAM;AAC1C,UAAI,UAAU,OAAO;AACnB,qBAAa,QAAQ;AAAA,MACvB;AAAA,IACF,GAAG,GAAI;AAAA,EACT;AAGA,WAAS,kBAAwB;AAC/B,QAAI,UAAU,OAAO;AACnB,mBAAa,QAAQ;AAAA,IACvB;AAAA,EACF;AAGA,iBAAe,oBAAoB,OAAkC;AACnE,QAAI,SAAS,UAAU,EAAG;AAE1B,UAAM,SAAS,MAAM;AACrB,UAAM,OAAO,OAAO,sBAAA;AACpB,UAAM,SAAS,MAAM,UAAU,KAAK;AACpC,UAAM,aAAa,SAAS,KAAK;AACjC,UAAM,aAAa,aAAa,SAAS;AAEzC,UAAM,KAAK,UAAU;AAAA,EACvB;AAGA,WAAS,oBAAoB,OAAyB;AACpD,QAAI,SAAS,UAAU,EAAG;AAE1B,UAAM,SAAS,MAAM;AACrB,UAAM,OAAO,OAAO,sBAAA;AACpB,UAAM,SAAS,MAAM,UAAU,KAAK;AACpC,UAAM,aAAa,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,SAAS,KAAK,KAAK,CAAC;AAE/D,cAAU,QAAQ,aAAa,SAAS;AACxC,kBAAc,QAAQ,aAAa;AAAA,EACrC;AAGA,WAAS,WAAW,IAAoB;AACtC,UAAM,eAAe,KAAK,MAAM,KAAK,GAAI;AACzC,UAAM,QAAQ,KAAK,MAAM,eAAe,IAAI;AAC5C,UAAM,UAAU,KAAK,MAAO,eAAe,OAAQ,EAAE;AACrD,UAAM,UAAU,eAAe;AAE/B,QAAI,QAAQ,GAAG;AACb,aAAO,GAAG,KAAK,IAAI,QAAQ,SAAA,EAAW,SAAS,GAAG,GAAG,CAAC,IAAI,QAAQ,SAAA,EAAW,SAAS,GAAG,GAAG,CAAC;AAAA,IAC/F;AACA,WAAO,GAAG,OAAO,IAAI,QAAQ,WAAW,SAAS,GAAG,GAAG,CAAC;AAAA,EAC1D;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;ACtIO,SAAS,WACd,mBAA4B,OACV;AAClB,QAAM,UAAU,IAAoB,IAAI;AACxC,QAAM,eAAe,IAAI,gBAAgB;AAGzC,QAAM,cAAc,SAAS,MAAM;AACjC,QAAI,CAAC,QAAQ,MAAO,QAAO;AAC3B,UAAM,UAAkC;AAAA,MACtC,cAAc;AAAA,MACd,kBAAkB;AAAA,MAClB,sBAAsB;AAAA,MACtB,sBAAsB;AAAA,MACtB,qBAAqB;AAAA,MACrB,WAAW;AAAA,IAAA;AAEb,WAAO,QAAQ,QAAQ,MAAM,QAAQ,KAAK,QAAQ,MAAM;AAAA,EAC1D,CAAC;AAGD,WAAS,iBAAuB;AAC9B,iBAAa,QAAQ,CAAC,aAAa;AAAA,EACrC;AAGA,WAAS,YAAkB;AACzB,YAAQ,QAAQ,YAAY,OAAA;AAC5B,YAAQ,IAAI,sBAAsB,QAAQ,KAAK;AAAA,EACjD;AAGA,YAAU,MAAM;AACd,cAAA;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACkHA,UAAM,QAAQ;AAGd,UAAM,OAAO;AAMb,UAAM,YAAY,IAA8B,IAAI;AAGpD,UAAM,eAAe,IAAwB,IAAI;AAGjD,UAAM,eAAe,IAAI,KAAK;AAG9B,UAAM,gBAAgB,SAA0C,OAAO;AAAA,MACrE,MAAM,MAAM,eAAe,QAAQ,wBAAwB,cAAc;AAAA,MACzE,YAAY,MAAM,eAAe,cAAc,wBAAwB,cAAc;AAAA,MACrF,MAAM,MAAM,eAAe,QAAQ,wBAAwB,cAAc;AAAA,IAAA,EACzE;AAGF,UAAM,EAAE,SAAS,cAAc,aAAa,eAAA,IAAmB,WAAW,KAAK;AAG/E,UAAM,SAAS,UAAU,IAAI;AAG7B,UAAM,WAAW,CAAC,OAAO;AACvB,aAAO,UAAU,QAAQ;AAAA,IAC3B,GAAG,EAAE,WAAW,MAAM;AAGtB,UAAM,SAAS,SAAS,MAAM,OAAO,OAAO,KAAK;AAGjD,UAAM,eAAe,SAAS,MAAM,OAAO,MAAM,SAAS;AAC1D,UAAM,cAAc,SAAS,MAAM,OAAO,MAAM,QAAQ;AACxD,UAAM,iBAAiB,SAAS,MAAM,OAAO,MAAM,WAAW;AAC9D,UAAM,cAAc,SAAS,MAAM,OAAO,MAAM,QAAQ;AACxD,UAAM,kBAAkB,SAAS,MAAM,OAAO,MAAM,YAAY;AAChE,UAAM,yBAAyB,SAAS,MAAM,OAAO,MAAM,mBAAmB;AAC9E,UAAM,mBAAmB,SAAS,MAAM,OAAO,MAAM,aAAa;AAElE,UAAM,WAAW,YAAY;AAAA,MAC3B,WAAW;AAAA,MACX,UAAU;AAAA,MACV,aAAa;AAAA,MACb,UAAU;AAAA,MACV,cAAc;AAAA,MACd,qBAAqB;AAAA,MACrB,eAAe;AAAA,MACf;AAAA,MACA,MAAM,OAAO;AAAA,IAAA,CACd;AAGD,UAAM,kBAAkB,IAAwB,IAAI;AAGpD,aAAS,SAAS,KAA0E;AAC1F,UAAI,CAAC,OAAO,CAAC,IAAI,IAAK,QAAO;AAC7B,aAAO,EAAE,KAAK,IAAI,KAAK,QAAQ,IAAI,UAAU,MAAA;AAAA,IAC/C;AAGA,aAAS,iBAAuB;AAC9B,UAAI,OAAO,MAAM,WAAW;AAC1B,eAAO,MAAA;AAAA,MACT,OAAO;AACL,eAAO,OAAA;AAAA,MACT;AAAA,IACF;AAGA,aAAS,mBAAyB;AAChC,UAAI,CAAC,aAAa,MAAO;AAEzB,UAAI,CAAC,aAAa,OAAO;AACvB,YAAI,aAAa,MAAM,mBAAmB;AACxC,uBAAa,MAAM,kBAAA;AAAA,QACrB;AAAA,MACF,OAAO;AACL,YAAI,SAAS,gBAAgB;AAC3B,mBAAS,eAAA;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAGA,aAAS,yBAA+B;AACtC,mBAAa,QAAQ,CAAC,CAAC,SAAS;AAAA,IAClC;AAGA,aAAS,OAAa;AACpB,YAAM,SAAS,SAAS,MAAM,GAAG;AACjC,UAAI,QAAQ;AACV,eAAO,KAAK,MAAM;AAAA,MACpB;AAAA,IACF;AAGA,UAAM,MAAM,MAAM,KAAK,CAAC,WAAW;AACjC,YAAM,SAAS,SAAS,MAAM;AAC9B,UAAI,UAAU,OAAO,KAAK;AACxB,eAAO,KAAK,MAAM;AAAA,MACpB;AAAA,IACF,GAAG,EAAE,WAAW,MAAM,MAAM,MAAM;AAGlC,cAAU,MAAM;AACd,eAAS,iBAAiB,oBAAoB,sBAAsB;AAAA,IACtE,CAAC;AAGD,gBAAY,MAAM;AAChB,eAAS,oBAAoB,oBAAoB,sBAAsB;AAAA,IACzE,CAAC;AAGD,aAA6B;AAAA,MAC3B;AAAA,MACA,OAAO,OAAO;AAAA,MACd,MAAM,OAAO;AAAA,IAAA,CACd;;0BAtTCE,mBA0KM,OAAA;AAAA,QA1KD,OAAM;AAAA,iBAA0B;AAAA,QAAJ,KAAI;AAAA,MAAA;QACnCC,mBAwKM,OAAA;AAAA,UAvKJ,OAAM;AAAA,mBACF;AAAA,UAAJ,KAAI;AAAA,UACH,cAAU,OAAA,CAAA,MAAA,OAAA,CAAA;AAAA,UAAE,IAAA,SAAAC,MAAA,QAAA,EAAS,mBAATA,MAAA,QAAA,EAAS,gBAAe,GAAA,IAAA;AAAA,UACpC,aAAS,OAAA,CAAA,MAAA,OAAA,CAAA;AAAA,UAAE,IAAA,SAAAA,MAAA,QAAA,EAAS,mBAATA,MAAA,QAAA,EAAS,gBAAe,GAAA,IAAA;AAAA,UACnC,cAAU,OAAA,CAAA,MAAA,OAAA,CAAA;AAAA,UAAE,IAAA,SAAAA,MAAA,QAAA,EAAS,mBAATA,MAAA,QAAA,EAAS,gBAAe,GAAA,IAAA;AAAA,QAAA;UAGrCD,mBAA0D,UAAA;AAAA,qBAA9C;AAAA,YAAJ,KAAI;AAAA,YAAY,OAAM;AAAA,UAAA;WAGlBC,MAAA,MAAA,EAAO,MAAM,YAAzBC,aAAAH,mBAEM,OAFN,YAEM;AAAA,YADJI,WAAgC,KAAA,QAAA,eAAA,CAAA,GAAA,QAAA,IAAA;AAAA,UAAA;UAIvBF,MAAA,YAAA,KAAgBA,MAAA,OAAA,KAA3BC,aAAAH,mBA0DM,OA1DN,YA0DM;AAAA,YAzDJC,mBAGM,OAHN,YAGM;AAAA,cAFJ,OAAA,CAAA,MAAA,OAAA,CAAA,IAAAA,mBAAqB,cAAf,YAAQ,EAAA;AAAA,cACdA,mBAA2E,QAAA;AAAA,gBAApE,OAAKI,eAAEH,MAAA,OAAA,EAAQ,gBAAa,SAAA,EAAA;AAAA,cAAA,mBAAmBA,MAAA,WAAA,CAAW,GAAA,CAAA;AAAA,YAAA;wCAEnED,mBAAkC,OAAA,EAA7B,OAAM,iBAAA,GAAgB,MAAA,EAAA;AAAA,YAC3BA,mBAKM,OALN,YAKM;AAAA,cAJJ,OAAA,CAAA,MAAA,OAAA,CAAA,IAAAA,mBAAiB,cAAX,QAAI,EAAA;AAAA,cACVA,mBAEO,QAAA;AAAA,gBAFA,OAAKI,eAAEH,MAAA,OAAA,EAAQ,aAAa,WAAQ,OAAA,KAAA;AAAA,cAAA,mBACtCA,MAAA,OAAA,EAAQ,aAAa,WAAQ,QAAA,IAAA,GAAA,CAAA;AAAA,YAAA;YAGpCD,mBAKM,OALN,YAKM;AAAA,cAJJ,OAAA,CAAA,MAAA,OAAA,CAAA,IAAAA,mBAAkB,cAAZ,SAAK,EAAA;AAAA,cACXA,mBAEO,QAAA;AAAA,gBAFA,OAAKI,eAAEH,MAAA,OAAA,EAAQ,aAAa,QAAK,OAAA,KAAA;AAAA,cAAA,mBACnCA,MAAA,OAAA,EAAQ,aAAa,QAAK,QAAA,IAAA,GAAA,CAAA;AAAA,YAAA;YAGjCD,mBAKM,OALN,YAKM;AAAA,cAJJ,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,mBAAmB,cAAb,UAAM,EAAA;AAAA,cACZA,mBAEO,QAAA;AAAA,gBAFA,OAAKI,eAAEH,MAAA,OAAA,EAAQ,aAAa,SAAM,OAAA,KAAA;AAAA,cAAA,mBACpCA,MAAA,OAAA,EAAQ,aAAa,SAAM,QAAA,IAAA,GAAA,CAAA;AAAA,YAAA;YAGlCD,mBAKM,OALN,YAKM;AAAA,cAJJ,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,mBAAgB,cAAV,OAAG,EAAA;AAAA,cACTA,mBAEO,QAAA;AAAA,gBAFA,OAAKI,eAAEH,MAAA,OAAA,EAAQ,aAAa,oBAAiB,OAAA,KAAA;AAAA,cAAA,mBAC/CA,MAAA,OAAA,EAAQ,aAAa,oBAAiB,QAAA,IAAA,GAAA,CAAA;AAAA,YAAA;YAG7CD,mBAKM,OALN,YAKM;AAAA,cAJJ,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,mBAAoB,cAAd,WAAO,EAAA;AAAA,cACbA,mBAEO,QAAA;AAAA,gBAFA,OAAKI,eAAEH,MAAA,OAAA,EAAQ,aAAa,cAAW,OAAA,KAAA;AAAA,cAAA,mBACzCA,MAAA,OAAA,EAAQ,aAAa,cAAW,QAAA,IAAA,GAAA,CAAA;AAAA,YAAA;YAGvCD,mBAKM,OALN,YAKM;AAAA,cAJJ,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,mBAAqB,cAAf,YAAQ,EAAA;AAAA,cACdA,mBAEO,QAAA;AAAA,gBAFA,OAAKI,eAAEH,MAAA,OAAA,EAAQ,aAAa,WAAQ,OAAA,KAAA;AAAA,cAAA,mBACtCA,MAAA,OAAA,EAAQ,aAAa,WAAQ,QAAA,IAAA,GAAA,CAAA;AAAA,YAAA;YAGpCD,mBAKM,OALN,aAKM;AAAA,cAJJ,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,mBAAmB,cAAb,UAAM,EAAA;AAAA,cACZA,mBAEO,QAAA;AAAA,gBAFA,OAAKI,eAAEH,MAAA,OAAA,EAAQ,aAAa,iBAAc,OAAA,KAAA;AAAA,cAAA,mBAC5CA,MAAA,OAAA,EAAQ,aAAa,iBAAc,QAAA,IAAA,GAAA,CAAA;AAAA,YAAA;YAG1BA,MAAA,MAAA,EAAO,MAAM,yBAA7BF,mBASWM,UAAA,EAAA,KAAA,EAAA,GAAA;AAAA,0CARTL,mBAAkC,OAAA,EAA7B,OAAM,iBAAA,GAAgB,MAAA,EAAA;AAAA,cACGC,MAAA,MAAA,EAAO,eAAe,SAApDC,aAAAH,mBAAkI,OAAlI,aAAkI;AAAA,gBAAvE,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAC,mBAAmB,cAAb,UAAM,EAAA;AAAA,gBAAOA,mBAA8C,QAAA,MAAAM,gBAArCL,MAAA,MAAA,EAAO,eAAe,KAAK,GAAA,CAAA;AAAA,cAAA;cAClHD,mBAAiF,OAAjF,aAAiF;AAAA,gBAAzD,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,mBAAgB,cAAV,OAAG,EAAA;AAAA,gBAAOA,mBAAmC,QAAA,MAAAM,gBAA1BL,MAAA,MAAA,EAAO,MAAM,GAAG,GAAA,CAAA;AAAA,cAAA;cACjED,mBAA+F,OAA/F,aAA+F;AAAA,gBAAvE,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,mBAAuB,cAAjB,cAAU,EAAA;AAAA,gBAAOA,mBAA0C,QAAA,MAAAM,gBAAjCL,MAAA,MAAA,EAAO,MAAM,UAAU,GAAA,CAAA;AAAA,cAAA;cAC/ED,mBAA+F,OAA/F,aAA+F;AAAA,gBAAvE,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,mBAAuB,cAAjB,cAAU,EAAA;AAAA,gBAAOA,mBAA0C,QAAA,MAAAM,gBAAjCL,MAAA,MAAA,EAAO,MAAM,UAAU,GAAA,CAAA;AAAA,cAAA;cAC/ED,mBAAyF,OAAzF,aAAyF;AAAA,gBAAjE,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,mBAAoB,cAAd,WAAO,EAAA;AAAA,gBAAOA,mBAAuC,QAAA,MAAAM,gBAA9BL,MAAA,MAAA,EAAO,MAAM,OAAO,GAAA,CAAA;AAAA,cAAA;cACzED,mBAA+F,OAA/F,aAA+F;AAAA,gBAAvE,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,mBAAoB,cAAd,WAAO,EAAA;AAAA,gBAAOA,mBAA6C,QAAA,MAAAM,gBAApCL,MAAA,MAAA,EAAO,MAAM,aAAa,GAAA,CAAA;AAAA,cAAA;cAC/ED,mBAAuG,OAAvG,aAAuG;AAAA,gBAA/E,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,mBAAkB,cAAZ,SAAK,EAAA;AAAA,gBAAOA,mBAAuD,8BAA9CC,MAAA,MAAA,EAAO,MAAM,sBAAqB,SAAK,CAAA;AAAA,cAAA;;;UAKxDA,MAAA,MAAA,EAAO,UAAU,SAAvDC,aAAAH,mBAIM,OAJN,aAIM;AAAA,YAHJI,WAEO,4BAFP,MAEO;AAAA,0CADLH,mBAA8B,OAAA,EAAzB,OAAM,gBAAY,MAAA,EAAA;AAAA,YAAA;;UAMnB,cAAA,MAAc,qBADtBD,mBAwEM,OAAA;AAAA;YAtEJ,OAAKK,eAAA,CAAC,qBAAmB,EAAA,SACNH,MAAA,QAAA,EAAS,aAAa,SAAK,CAAKA,MAAA,MAAA,EAAO,MAAM,WAAS,CAAA;AAAA,UAAA;YAEzED,mBAQS,UAAA;AAAA,cARD,OAAM;AAAA,cAAkB,SAAO;AAAA,YAAA;cAC1BC,MAAA,MAAA,EAAO,MAAM,aAAxBC,aAAAH,mBAGM,OAHN,aAGM,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,gBAFJC,mBAAgD,QAAA;AAAA,kBAA1C,GAAE;AAAA,kBAAI,GAAE;AAAA,kBAAI,OAAM;AAAA,kBAAI,QAAO;AAAA,kBAAK,IAAG;AAAA,gBAAA;gBAC3CA,mBAAiD,QAAA;AAAA,kBAA3C,GAAE;AAAA,kBAAK,GAAE;AAAA,kBAAI,OAAM;AAAA,kBAAI,QAAO;AAAA,kBAAK,IAAG;AAAA,gBAAA;uBAE9CE,aAAAH,mBAEM,OAFN,aAEM,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,gBADJC,mBAAyB,QAAA,EAAnB,GAAE,gBAAA,GAAe,MAAA,EAAA;AAAA,cAAA;;YAKW,OAAA,SAAtCE,aAAAH,mBAGO,QAHP,aAGO,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,cAFLC,mBAAiC,QAAA,EAA3B,OAAM,cAAA,GAAa,MAAA,EAAA;AAAA,cACzBA,mBAAoC,QAAA,EAA9B,OAAM,eAAA,GAAe,MAAE,EAAA;AAAA,YAAA,SAI/BE,aAAAH,mBAIO,QAJP,aAIO;AAAA,cAHLC,mBAAwF,QAAxF,aAAwFM,gBAAvDL,MAAA,QAAA,EAAS,WAAWA,MAAA,MAAA,EAAO,MAAM,WAAW,CAAA,GAAA,CAAA;AAAA,cAC7E,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAD,mBAAwC,QAAA,EAAlC,OAAM,oBAAA,GAAoB,KAAC,EAAA;AAAA,cACjCA,mBAAsF,QAAtF,aAAsFM,gBAApDL,MAAA,QAAA,EAAS,WAAWA,MAAA,MAAA,EAAO,MAAM,QAAQ,CAAA,GAAA,CAAA;AAAA,YAAA;aAKpE,OAAA,sBADTF,mBAoBM,OAAA;AAAA;cAlBJ,OAAM;AAAA,cACL,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA;AAAA,cAAE,IAAA,SAAAE,MAAA,QAAA,EAAS,uBAATA,MAAA,QAAA,EAAS,oBAAmB,GAAA,IAAA;AAAA,cACnC,aAAS,OAAA,CAAA,MAAA,OAAA,CAAA;AAAA,cAAE,IAAA,SAAAA,MAAA,QAAA,EAAS,uBAATA,MAAA,QAAA,EAAS,oBAAmB,GAAA,IAAA;AAAA,cACvC,cAAU,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAEA,MAAA,QAAA,EAAS,UAAU,QAAK;AAAA,YAAA;cAErCD,mBAKM,OALN,aAKM;AAAA,gBAJJA,mBAAgG,OAAA;AAAA,kBAA3F,OAAM;AAAA,kBAAwB,OAAKO,eAAA,EAAA,OAAWN,MAAA,QAAA,EAAS,eAAe,QAAK,IAAA,CAAA;AAAA,gBAAA;gBAChFD,mBAEM,OAAA;AAAA,kBAFD,OAAM;AAAA,kBAAsB,OAAKO,eAAA,EAAA,OAAWN,MAAA,QAAA,EAAS,aAAa,QAAK,IAAA,CAAA;AAAA,gBAAA;kBAC1ED,mBAAsC,OAAA,EAAjC,OAAM,qBAAA,GAAoB,MAAA,EAAA;AAAA,gBAAA;;cAK3BC,MAAA,QAAA,EAAS,UAAU,UAAK,qBAFhCF,mBAMM,OAAA;AAAA;gBALJ,OAAM;AAAA,gBAEL,OAAKQ,eAAA,EAAA,MAAUN,MAAA,QAAA,EAAS,cAAc,QAAK,IAAA,CAAA;AAAA,cAAA,GAEzCK,gBAAAL,MAAA,QAAA,EAAS,WAAWA,gBAAS,UAAU,KAAK,CAAA,GAAA,CAAA;uBAKnDC,aAAAH,mBAAyC,OAAzC,WAAyC;AAAA,YAG3B,cAAA,MAAc,qBAA5BA,mBAIS,UAAA;AAAA;cAJyB,OAAM;AAAA,cAAkC,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA;AAAA,2BAAEE,MAAA,cAAA,KAAAA,MAAA,cAAA,EAAA,GAAA,IAAA;AAAA,cAAiB,OAAOA,MAAA,YAAA,IAAY,SAAA;AAAA,YAAA;cACnHD,mBAEM,OAAA;AAAA,gBAFD,SAAQ;AAAA,gBAAY,MAAK;AAAA,cAAA;gBAC5BA,mBAA4G,QAAA,EAAtG,GAAE,oGAAkG;AAAA,cAAA;;YAKhG,cAAA,MAAc,2BAA5BD,mBASS,UAAA;AAAA;cAT+B,OAAM;AAAA,cAAoC,SAAO;AAAA,cAAmB,OAAO,aAAA,QAAY,SAAA;AAAA,YAAA;cAElH,aAAA,SAAXG,aAAAH,mBAEM,OAFN,aAEM,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,gBADJC,mBAAyF,QAAA,EAAnF,GAAE,gFAAA,GAA+E,MAAA,EAAA;AAAA,cAAA,SAGzFE,aAAAH,mBAEM,OAFN,aAEM,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,gBADJC,mBAA0F,QAAA,EAApF,GAAE,iFAAA,GAAgF,MAAA,EAAA;AAAA,cAAA;;;UAQtFC,MAAA,MAAA,EAAO,MAAM,aAAaA,MAAA,MAAA,EAAO,MAAM,aAAS,CAAKA,MAAA,MAAA,EAAO,UAAU,sBAF9EF,mBAQM,OAAA;AAAA;YAPJ,OAAM;AAAA,YAEL,SAAO;AAAA,UAAA;YAERC,mBAEM,OAAA;AAAA,cAFD,SAAQ;AAAA,cAAY,MAAK;AAAA,YAAA;cAC5BA,mBAAyB,QAAA,EAAnB,GAAE,iBAAe;AAAA,YAAA;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/types.ts","../src/composables/usePlayer.ts","../src/composables/useControls.ts","../src/composables/useEnvInfo.ts","../src/components/EcPlayer.vue"],"sourcesContent":["/**\n * Vue 组件类型定义\n */\n\nimport type { EcPlayerCoreConfig, EcPlayerState, EnvInfo } from '@give-tech/ec-player'\nexport { LogLevel } from '@give-tech/ec-player'\n\n/**\n * WASM 路径配置\n */\nexport interface WasmPathConfig {\n /**\n * SIMD 版本 WASM 路径(推荐,性能更好)\n * 用于支持 SIMD 的现代浏览器\n */\n simd?: string\n /**\n * 非 SIMD 版本 WASM 路径\n * 用于不支持 SIMD 的旧浏览器作为降级方案\n */\n nonSimd?: string\n}\n\n/**\n * 全局配置\n *\n * 必须在使用 EcPlayer 组件前调用\n *\n * @example\n * ```typescript\n * // main.ts\n * import { configureEcPlayer } from '@give-tech/ec-player-vue'\n *\n * // 配置 SIMD 和非 SIMD 路径,支持自动降级\n * configureEcPlayer({\n * wasm: {\n * simd: '/wasm/decoder-simd.js',\n * nonSimd: '/wasm/decoder.js'\n * }\n * })\n *\n * // 使用 CDN\n * configureEcPlayer({\n * wasm: {\n * simd: 'https://unpkg.com/@give-tech/ec-player@latest/wasm/decoder-simd.js',\n * nonSimd: 'https://unpkg.com/@give-tech/ec-player@latest/wasm/decoder.js'\n * }\n * })\n * ```\n */\nexport interface EcPlayerGlobalConfig {\n /**\n * WASM 路径配置(必填)\n * 支持 SIMD 和非 SIMD 自动降级\n */\n wasm?: WasmPathConfig\n /** 默认是否显示控制条 */\n showControls?: boolean\n /** 默认缓冲目标帧数 */\n targetBufferSize?: number\n /** 默认每批解码帧数 */\n decodeBatchSize?: number\n /** 默认队列上限 */\n maxQueueSize?: number\n}\n\n/**\n * 播放器配置选项\n */\nexport interface PlayerOptions {\n /** 帧缓冲区目标大小 */\n targetBufferSize?: number\n /** 每批解码帧数 */\n decodeBatchSize?: number\n /** NAL/Sample 队列上限 */\n maxQueueSize?: number\n}\n\n/**\n * 视频源配置\n */\nexport interface EcPlayerSource {\n /** 视频 URL */\n url: string\n /** 是否为直播流 */\n isLive?: boolean\n /** 版本号,用于强制重新加载 */\n version?: number\n}\n\n/**\n * 控制条选项\n */\nexport interface EcPlayerControlOption {\n /** 是否显示控制条 */\n show?: boolean\n /** 是否显示全屏按钮 */\n fullscreen?: boolean\n /** 是否显示环境信息按钮 */\n info?: boolean\n /** 是否显示倍速按钮(仅点播) */\n playbackRate?: boolean\n}\n\n/**\n * EcPlayer 组件 Props\n */\nexport interface EcPlayerProps {\n /** 视频源 */\n src?: EcPlayerSource\n /** 控制条选项 */\n controlOption?: EcPlayerControlOption\n}\n\n/**\n * EcPlayer 组件 Emits\n */\nexport interface EcPlayerEmits {\n /** 播放时触发 */\n (e: 'play'): void\n /** 暂停时触发 */\n (e: 'pause'): void\n}\n\n/**\n * EcPlayer 组件 Expose 方法\n */\nexport interface EcPlayerExpose {\n /** 播放 */\n play: () => void\n /** 暂停 */\n pause: () => void\n /** 跳转到指定时间(毫秒) */\n seek: (time: number) => Promise<void>\n}\n\n/**\n * 环境信息面板数据\n */\nexport interface EnvPanelData {\n envInfo: EnvInfo | null\n state: Partial<EcPlayerState>\n}\n\n/**\n * 播放器配置(从 Props 转换)\n */\nexport interface PlayerConfigFromProps extends EcPlayerCoreConfig {\n wasmPath: string\n targetBufferSize: number\n decodeBatchSize: number\n maxQueueSize: number\n}\n\n/**\n * 默认 Props 值\n */\nexport const DEFAULT_EC_PLAYER_PROPS = {\n src: undefined as EcPlayerSource | undefined,\n controlOption: {\n show: true,\n fullscreen: true,\n info: true,\n playbackRate: true\n }\n}\n\n/**\n * 默认播放器配置\n */\nexport const DEFAULT_PLAYER_OPTIONS: Required<PlayerOptions> = {\n targetBufferSize: 60,\n decodeBatchSize: 2,\n maxQueueSize: 200\n}\n\n/**\n * 默认 WASM 配置\n */\nexport const DEFAULT_WASM_CONFIG: WasmPathConfig = {\n simd: '/wasm/decoder-simd.js',\n nonSimd: '/wasm/decoder.js'\n}\n\n/**\n * 全局配置存储\n */\nlet globalConfig: EcPlayerGlobalConfig = {}\n\n/**\n * 配置 EcPlayer 全局默认值\n *\n * @example\n * ```typescript\n * // main.ts\n * import { configureEcPlayer } from '@give-tech/ec-player-vue'\n *\n * // 配置 SIMD 和非 SIMD 路径,支持自动降级\n * configureEcPlayer({\n * wasm: {\n * simd: '/wasm/decoder-simd.js',\n * nonSimd: '/wasm/decoder.js'\n * }\n * })\n *\n * // 使用 CDN\n * configureEcPlayer({\n * wasm: {\n * simd: 'https://unpkg.com/@give-tech/ec-player@latest/wasm/decoder-simd.js',\n * nonSimd: 'https://unpkg.com/@give-tech/ec-player@latest/wasm/decoder.js'\n * }\n * })\n * ```\n */\nexport function configureEcPlayer(config: EcPlayerGlobalConfig): void {\n globalConfig = { ...globalConfig, ...config }\n}\n\n/**\n * 获取全局配置\n */\nexport function getGlobalConfig(): EcPlayerGlobalConfig {\n return { ...globalConfig }\n}\n\n/**\n * 获取 WASM 路径配置\n */\nexport function getWasmConfig(): WasmPathConfig {\n return {\n simd: globalConfig.wasm?.simd ?? DEFAULT_WASM_CONFIG.simd,\n nonSimd: globalConfig.wasm?.nonSimd ?? DEFAULT_WASM_CONFIG.nonSimd\n }\n}\n\n/**\n * 获取合并后的配置(props > 全局配置 > 默认值)\n */\nexport function getMergedConfig(props: EcPlayerProps) {\n return {\n src: props.src ?? DEFAULT_EC_PLAYER_PROPS.src,\n controlOption: {\n show: props.controlOption?.show ?? globalConfig.showControls ?? DEFAULT_EC_PLAYER_PROPS.controlOption.show,\n fullscreen: props.controlOption?.fullscreen ?? DEFAULT_EC_PLAYER_PROPS.controlOption.fullscreen,\n info: props.controlOption?.info ?? DEFAULT_EC_PLAYER_PROPS.controlOption.info,\n playbackRate: props.controlOption?.playbackRate ?? DEFAULT_EC_PLAYER_PROPS.controlOption.playbackRate\n }\n }\n}\n\n/**\n * 获取合并后的播放器配置(options > 全局配置 > 默认值)\n */\nexport function getMergedPlayerOptions(options: PlayerOptions): Required<PlayerOptions> {\n return {\n targetBufferSize: options.targetBufferSize ?? globalConfig.targetBufferSize ?? DEFAULT_PLAYER_OPTIONS.targetBufferSize,\n decodeBatchSize: options.decodeBatchSize ?? globalConfig.decodeBatchSize ?? DEFAULT_PLAYER_OPTIONS.decodeBatchSize,\n maxQueueSize: options.maxQueueSize ?? globalConfig.maxQueueSize ?? DEFAULT_PLAYER_OPTIONS.maxQueueSize\n }\n}\n\n/**\n * 根据环境能力选择合适的 WASM 路径\n *\n * @param hasSimdSupport 是否支持 SIMD\n * @returns 实际使用的 WASM 路径\n */\nexport function resolveWasmPath(hasSimdSupport: boolean): string {\n const wasmConfig = getWasmConfig()\n\n // 根据 SIMD 支持情况选择\n if (hasSimdSupport && wasmConfig.simd) {\n console.log('[EcPlayer] Using SIMD WASM:', wasmConfig.simd)\n return wasmConfig.simd\n }\n\n if (wasmConfig.nonSimd) {\n console.log('[EcPlayer] SIMD not supported, using non-SIMD WASM:', wasmConfig.nonSimd)\n return wasmConfig.nonSimd\n }\n\n // 降级到 SIMD 版本(兜底)\n console.log('[EcPlayer] No non-SIMD path configured, falling back to SIMD:', wasmConfig.simd)\n return wasmConfig.simd!\n}\n\n/**\n * 预加载 WASM 模块\n *\n * @example\n * import { preloadWasm } from '@give-tech/ec-player-vue'\n * preloadWasm() // 预加载所有\n * preloadWasm({ preloadNonSimd: false }) // 只预加载 SIMD\n */\nexport function preloadWasm(options?: {\n preloadSimd?: boolean\n preloadNonSimd?: boolean\n}): void {\n const { preloadSimd = true, preloadNonSimd = true } = options ?? {}\n const wasmConfig = getWasmConfig()\n const paths: string[] = []\n\n if (preloadSimd && wasmConfig.simd) {\n paths.push(wasmConfig.simd)\n }\n if (preloadNonSimd && wasmConfig.nonSimd) {\n paths.push(wasmConfig.nonSimd)\n }\n\n if (paths.length > 0) {\n import('@give-tech/ec-player').then(({ WASMLoader }) => {\n WASMLoader.preloadAll(paths)\n console.log('[EcPlayer] Preloading WASM:', paths)\n }).catch(err => {\n console.warn('[EcPlayer] Failed to preload WASM:', err)\n })\n }\n}\n","/**\n * 播放器核心逻辑\n */\n\nimport { ref, shallowRef, reactive, onUnmounted, type Ref } from 'vue'\nimport {\n EcPlayerCore,\n EnvDetector,\n setLogLevel as coreSetLogLevel,\n type EcPlayerCoreConfig,\n type EcPlayerState,\n type EcPlayerCallbacks\n} from '@give-tech/ec-player'\nimport type { EcPlayerProps, PlayerOptions } from '../types'\nimport { resolveWasmPath, DEFAULT_PLAYER_OPTIONS, getGlobalConfig } from '../types'\n\n/**\n * 播放器逻辑返回值\n */\nexport interface UsePlayerReturn {\n /** Canvas 元素引用 */\n canvasRef: Ref<HTMLCanvasElement | null>\n /** 播放器实例 */\n player: Ref<EcPlayerCore | null>\n /** 响应式状态 */\n state: EcPlayerState\n /** 是否正在加载 */\n isLoading: Ref<boolean>\n /** 检测到的格式 */\n detectedFormat: Ref<string>\n /** 是否为直播流 */\n isLive: Ref<boolean>\n /** 播放 */\n play: (options: { url: string; isLive?: boolean }) => Promise<void>\n /** 设置配置 */\n setOptions: (options: PlayerOptions) => void\n /** 设置日志级别 */\n setLogLevel: (level: number) => void\n /** 暂停 */\n pause: () => void\n /** 恢复播放 */\n resume: () => Promise<void>\n /** 跳转 */\n seek: (time: number) => Promise<void>\n /** 设置倍速 */\n setPlaybackRate: (rate: number) => void\n /** 获取播放器实例 */\n getPlayer: () => EcPlayerCore | null\n /** 获取状态 */\n getState: () => EcPlayerState\n /** 获取当前时间 */\n getCurrentTime: () => number\n /** 获取总时长 */\n getDuration: () => number\n /** 销毁播放器 */\n destroy: () => void\n}\n\n/**\n * 从配置选项创建播放器配置\n */\nfunction createConfig(options: Required<PlayerOptions>): Omit<EcPlayerCoreConfig, 'isLive'> {\n // 检测 SIMD 支持\n const envInfo = EnvDetector.detect()\n const wasmPath = resolveWasmPath(envInfo.capabilities.wasmSimd)\n\n return {\n wasmPath,\n targetBufferSize: options.targetBufferSize,\n decodeBatchSize: options.decodeBatchSize,\n maxQueueSize: options.maxQueueSize\n }\n}\n\n/**\n * 播放器逻辑 Hook\n */\nexport function usePlayer(\n emit: {\n (e: 'play'): void\n (e: 'pause'): void\n }\n): UsePlayerReturn {\n const canvasRef = ref<HTMLCanvasElement | null>(null)\n const player = shallowRef<EcPlayerCore | null>(null)\n const isLoading = ref(false)\n const detectedFormat = ref('')\n const isLive = ref(false) // 跟踪当前是否为直播流\n\n // 用于追踪最新的 play 请求,解决快速切换源时的竞态条件\n let playRequestId = 0\n\n // 当前播放器配置(初始化时合并全局配置和默认值)\n const globalConfig = getGlobalConfig()\n const currentOptions = reactive<Required<PlayerOptions>>({\n targetBufferSize: globalConfig.targetBufferSize ?? DEFAULT_PLAYER_OPTIONS.targetBufferSize,\n decodeBatchSize: globalConfig.decodeBatchSize ?? DEFAULT_PLAYER_OPTIONS.decodeBatchSize,\n maxQueueSize: globalConfig.maxQueueSize ?? DEFAULT_PLAYER_OPTIONS.maxQueueSize\n })\n\n // 响应式状态\n const state = reactive<EcPlayerState>({\n isPlaying: false,\n isLoaded: false,\n isLoading: false,\n fps: 0,\n resolution: '-',\n decoded: 0,\n downloaded: 0,\n droppedFrames: 0,\n isPrefetching: false,\n segmentIndex: 0,\n fetchedSegmentCount: 0,\n totalSegments: 0,\n downloadSpeed: 0,\n currentTime: 0,\n duration: 0,\n playbackRate: 1\n })\n\n // 创建回调\n const callbacks: EcPlayerCallbacks = {\n onStateChange: (partial) => {\n Object.assign(state, partial)\n\n // 派发 play/pause 事件\n if (partial.isPlaying === true) {\n emit('play')\n } else if (partial.isPlaying === false && state.isPlaying) {\n emit('pause')\n }\n },\n onError: (error) => {\n console.error('[EcPlayer] Error:', error)\n },\n onReady: () => {\n // 第一帧已准备好,取消 loading 状态\n isLoading.value = false\n console.log('[EcPlayer] First frame ready, loading finished')\n }\n }\n\n // 播放(加载并播放)\n async function play(options: { url: string; isLive?: boolean }): Promise<void> {\n const { url, isLive: isLiveParam = false } = options\n if (!url) {\n console.error('[EcPlayer] URL is required')\n return\n }\n\n // 递增请求 ID,用于追踪这次调用\n const currentRequestId = ++playRequestId\n console.log('[EcPlayer] play() called, requestId:', currentRequestId)\n\n // 如果正在加载中,先销毁当前播放器\n if (isLoading.value && player.value) {\n console.log('[EcPlayer] Aborting current load to start new one...')\n player.value.destroy()\n player.value = null\n }\n\n // 等待 canvas 准备好\n let retries = 10\n while (!canvasRef.value && retries > 0) {\n await new Promise(resolve => setTimeout(resolve, 100))\n retries--\n }\n\n // 检查是否有更新的请求\n if (currentRequestId !== playRequestId) {\n console.log('[EcPlayer] Request obsolete after waiting for canvas, aborting')\n return\n }\n\n if (!canvasRef.value) {\n console.error('[EcPlayer] Canvas element not found')\n return\n }\n\n isLoading.value = true\n isLive.value = isLiveParam\n\n try {\n // 销毁旧播放器\n if (player.value) {\n player.value.destroy()\n player.value = null\n }\n\n // 重置状态\n state.isPlaying = false\n state.isLoaded = false\n state.fps = 0\n state.resolution = '-'\n state.decoded = 0\n state.downloaded = 0\n state.droppedFrames = 0\n state.segmentIndex = 0\n state.totalSegments = 0\n state.downloadSpeed = 0\n state.currentTime = 0\n state.duration = 0\n detectedFormat.value = ''\n\n // 创建配置\n const config: EcPlayerCoreConfig & { canvas: HTMLCanvasElement } = {\n ...createConfig(currentOptions),\n canvas: canvasRef.value,\n isLive: isLiveParam\n }\n\n // 创建播放器\n player.value = new EcPlayerCore(config, callbacks)\n\n // 加载视频\n await player.value.load(url, isLiveParam)\n\n // 检查是否有更新的请求\n if (currentRequestId !== playRequestId) {\n console.log('[EcPlayer] Request obsolete after load, aborting')\n // 销毁刚创建的播放器\n if (player.value) {\n player.value.destroy()\n player.value = null\n }\n return\n }\n\n // 获取检测到的格式\n detectedFormat.value = player.value.getDetectedFormat()\n\n // 标记加载完成\n state.isLoaded = true\n\n // 开始播放\n await player.value.play()\n\n console.log('[EcPlayer] Playing stream, format:', detectedFormat.value)\n } catch (error: any) {\n console.error('[EcPlayer] Failed to play:', error?.message || error)\n // 发生错误时也要取消 loading 状态\n if (currentRequestId === playRequestId) {\n isLoading.value = false\n }\n }\n // 注意:isLoading 不在 finally 中重置,而是等待 onReady 事件\n // 这样可以确保转圈动画持续到第一帧准备好为止\n }\n\n // 设置配置\n function setOptions(options: PlayerOptions): void {\n if (options.targetBufferSize !== undefined) {\n currentOptions.targetBufferSize = options.targetBufferSize\n }\n if (options.decodeBatchSize !== undefined) {\n currentOptions.decodeBatchSize = options.decodeBatchSize\n }\n if (options.maxQueueSize !== undefined) {\n currentOptions.maxQueueSize = options.maxQueueSize\n }\n console.log('[EcPlayer] Options updated:', currentOptions)\n }\n\n // 设置日志级别\n function setLogLevel(level: number): void {\n coreSetLogLevel(level)\n }\n\n // 暂停\n function pause(): void {\n player.value?.pause()\n }\n\n // 恢复播放\n async function resume(): Promise<void> {\n if (!player.value) return\n await player.value.play()\n }\n\n // 跳转\n async function seek(time: number): Promise<void> {\n if (!player.value) return\n await player.value.seek(time)\n }\n\n // 设置倍速\n function setPlaybackRate(rate: number): void {\n if (!player.value) return\n player.value.setPlaybackRate(rate)\n }\n\n // 获取播放器实例\n function getPlayer(): EcPlayerCore | null {\n return player.value\n }\n\n // 获取状态\n function getState(): EcPlayerState {\n return player.value?.getState() ?? { ...state }\n }\n\n // 获取当前时间\n function getCurrentTime(): number {\n return player.value?.getCurrentTime() ?? 0\n }\n\n // 获取总时长\n function getDuration(): number {\n return player.value?.getDuration() ?? 0\n }\n\n // 销毁播放器\n function destroy(): void {\n if (player.value) {\n player.value.destroy()\n player.value = null\n }\n }\n\n // 组件卸载时销毁\n onUnmounted(() => {\n destroy()\n })\n\n return {\n canvasRef,\n player,\n state,\n isLoading,\n detectedFormat,\n isLive,\n play,\n setOptions,\n setLogLevel,\n pause,\n resume,\n seek,\n setPlaybackRate,\n getPlayer,\n getState,\n getCurrentTime,\n getDuration,\n destroy\n }\n}\n","/**\n * 播放器控制条逻辑\n */\n\nimport { ref, computed, type Ref } from 'vue'\n\n/**\n * 控制条逻辑参数\n */\nexport interface UseControlsParams {\n /** 是否正在播放 */\n isPlaying: Ref<boolean>\n /** 是否已加载 */\n isLoaded: Ref<boolean>\n /** 当前时间(毫秒) */\n currentTime: Ref<number>\n /** 总时长(毫秒) */\n duration: Ref<number>\n /** 已解析的分片索引 */\n segmentIndex: Ref<number>\n /** 已下载的分片总数 */\n fetchedSegmentCount: Ref<number>\n /** 总分片数 */\n totalSegments: Ref<number>\n /** 是否为直播流 */\n isLive: Ref<boolean>\n /** 跳转方法 */\n seek: (time: number) => Promise<void>\n}\n\n/**\n * 控制条逻辑返回值\n */\nexport interface UseControlsReturn {\n /** 是否显示控制条 */\n showControls: Ref<boolean>\n /** 进度条 hover 时间 */\n hoverTime: Ref<number | null>\n /** 进度条 hover 位置 */\n hoverPosition: Ref<number>\n /** 播放进度百分比 */\n playProgress: Ref<number>\n /** 缓冲进度百分比 */\n bufferProgress: Ref<number>\n /** 显示控制条 */\n showControlsBar: () => void\n /** 隐藏控制条 */\n hideControlsBar: () => void\n /** 处理进度条点击 */\n handleProgressClick: (event: MouseEvent) => Promise<void>\n /** 处理进度条悬停 */\n handleProgressHover: (event: MouseEvent) => void\n /** 格式化时间 */\n formatTime: (ms: number) => string\n}\n\n/**\n * 控制条逻辑 Hook\n */\nexport function useControls(params: UseControlsParams): UseControlsReturn {\n let hideControlsTimer: number | null = null\n const {\n isPlaying,\n isLoaded,\n currentTime,\n duration,\n segmentIndex,\n fetchedSegmentCount,\n totalSegments,\n isLive,\n seek\n } = params\n\n const showControls = ref(true)\n const hoverTime = ref<number | null>(null)\n const hoverPosition = ref(0)\n\n // 计算播放进度\n const playProgress = computed(() => {\n if (duration.value === 0) return 0\n return (currentTime.value / duration.value) * 100\n })\n\n // 计算缓冲进度(已下载的分段数)\n const bufferProgress = computed(() => {\n if (totalSegments.value === 0) return 0\n return (fetchedSegmentCount.value / totalSegments.value) * 100\n })\n\n // 显示控制条\n function showControlsBar(): void {\n showControls.value = true\n if (hideControlsTimer) {\n clearTimeout(hideControlsTimer)\n }\n hideControlsTimer = window.setTimeout(() => {\n if (isPlaying.value) {\n showControls.value = false\n }\n }, 3000)\n }\n\n // 隐藏控制条\n function hideControlsBar(): void {\n if (isPlaying.value) {\n showControls.value = false\n }\n }\n\n // 处理进度条点击\n async function handleProgressClick(event: MouseEvent): Promise<void> {\n if (duration.value === 0) return\n\n const target = event.currentTarget as HTMLElement\n const rect = target.getBoundingClientRect()\n const clickX = event.clientX - rect.left\n const percentage = clickX / rect.width\n const targetTime = percentage * duration.value\n\n await seek(targetTime)\n }\n\n // 处理进度条悬停\n function handleProgressHover(event: MouseEvent): void {\n if (duration.value === 0) return\n\n const target = event.currentTarget as HTMLElement\n const rect = target.getBoundingClientRect()\n const hoverX = event.clientX - rect.left\n const percentage = Math.max(0, Math.min(1, hoverX / rect.width))\n\n hoverTime.value = percentage * duration.value\n hoverPosition.value = percentage * 100\n }\n\n // 格式化时间\n function formatTime(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000)\n const hours = Math.floor(totalSeconds / 3600)\n const minutes = Math.floor((totalSeconds % 3600) / 60)\n const seconds = totalSeconds % 60\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`\n }\n return `${minutes}:${seconds.toString().padStart(2, '0')}`\n }\n\n return {\n showControls,\n hoverTime,\n hoverPosition,\n playProgress,\n bufferProgress,\n showControlsBar,\n hideControlsBar,\n handleProgressClick,\n handleProgressHover,\n formatTime\n }\n}\n","/**\n * 环境信息逻辑\n */\n\nimport { ref, computed, onMounted, type Ref } from 'vue'\nimport { EnvDetector, type EnvInfo } from '@give-tech/ec-player'\n\n/**\n * 环境信息逻辑返回值\n */\nexport interface UseEnvInfoReturn {\n /** 环境信息 */\n envInfo: Ref<EnvInfo | null>\n /** 是否显示环境面板 */\n showEnvPanel: Ref<boolean>\n /** 环境类型文本 */\n envTypeText: Ref<string>\n /** 切换环境面板显示 */\n toggleEnvPanel: () => void\n /** 检测环境 */\n detectEnv: () => void\n}\n\n/**\n * 环境信息逻辑 Hook\n */\nexport function useEnvInfo(\n initialShowPanel: boolean = false\n): UseEnvInfoReturn {\n const envInfo = ref<EnvInfo | null>(null)\n const showEnvPanel = ref(initialShowPanel)\n\n // 环境类型文本\n const envTypeText = computed(() => {\n if (!envInfo.value) return '未知'\n const typeMap: Record<string, string> = {\n 'pc-browser': 'PC 浏览器',\n 'mobile-browser': '移动端浏览器',\n 'wechat-miniprogram': '微信小程序',\n 'alipay-miniprogram': '支付宝小程序',\n 'other-miniprogram': '其他小程序',\n 'unknown': '未知',\n }\n return typeMap[envInfo.value.platform] || envInfo.value.platform\n })\n\n // 切换环境面板显示\n function toggleEnvPanel(): void {\n showEnvPanel.value = !showEnvPanel.value\n }\n\n // 检测环境\n function detectEnv(): void {\n envInfo.value = EnvDetector.detect()\n console.log('[EcPlayer] 环境检测结果:', envInfo.value)\n }\n\n // 组件挂载时检测环境\n onMounted(() => {\n detectEnv()\n })\n\n return {\n envInfo,\n showEnvPanel,\n envTypeText,\n toggleEnvPanel,\n detectEnv\n }\n}\n","<template>\n <div class=\"gt-player-container\" ref=\"containerRef\">\n <div\n class=\"gt-video-wrapper\"\n ref=\"videoWrapperRef\"\n @mouseenter=\"controls.showControlsBar\"\n @mousemove=\"controls.showControlsBar\"\n @mouseleave=\"controls.hideControlsBar\"\n >\n <!-- Canvas 视频渲染 -->\n <canvas ref=\"canvasRef\" class=\"gt-player-canvas\"></canvas>\n\n <!-- 封面/占位内容(未加载时显示) -->\n <div v-if=\"!player.state.isLoaded\" class=\"gt-placeholder\">\n <slot name=\"placeholder\"></slot>\n </div>\n\n <!-- 环境信息面板 -->\n <div v-if=\"showEnvPanel && envInfo\" class=\"gt-env-panel\">\n <div class=\"gt-env-row\">\n <span>platform</span>\n <span :class=\"envInfo.isMiniProgram ? 'warn' : ''\">{{ envTypeText }}</span>\n </div>\n <div class=\"gt-env-divider\"></div>\n <div class=\"gt-env-row\">\n <span>SIMD</span>\n <span :class=\"envInfo.capabilities.wasmSimd ? 'ok' : 'err'\">\n {{ envInfo.capabilities.wasmSimd ? 'Yes' : 'No' }}\n </span>\n </div>\n <div class=\"gt-env-row\">\n <span>WebGL</span>\n <span :class=\"envInfo.capabilities.webGL ? 'ok' : 'err'\">\n {{ envInfo.capabilities.webGL ? 'Yes' : 'No' }}\n </span>\n </div>\n <div class=\"gt-env-row\">\n <span>WebGL2</span>\n <span :class=\"envInfo.capabilities.webGL2 ? 'ok' : 'err'\">\n {{ envInfo.capabilities.webGL2 ? 'Yes' : 'No' }}\n </span>\n </div>\n <div class=\"gt-env-row\">\n <span>SAB</span>\n <span :class=\"envInfo.capabilities.sharedArrayBuffer ? 'ok' : 'err'\">\n {{ envInfo.capabilities.sharedArrayBuffer ? 'Yes' : 'No' }}\n </span>\n </div>\n <div class=\"gt-env-row\">\n <span>Threads</span>\n <span :class=\"envInfo.capabilities.wasmThreads ? 'ok' : 'err'\">\n {{ envInfo.capabilities.wasmThreads ? 'Yes' : 'No' }}\n </span>\n </div>\n <div class=\"gt-env-row\">\n <span>WebAudio</span>\n <span :class=\"envInfo.capabilities.webAudio ? 'ok' : 'err'\">\n {{ envInfo.capabilities.webAudio ? 'Yes' : 'No' }}\n </span>\n </div>\n <div class=\"gt-env-row\">\n <span>Stream</span>\n <span :class=\"envInfo.capabilities.readableStream ? 'ok' : 'err'\">\n {{ envInfo.capabilities.readableStream ? 'Yes' : 'No' }}\n </span>\n </div>\n <template v-if=\"player.state.isLoaded\">\n <div class=\"gt-env-divider\"></div>\n <div class=\"gt-env-row\" v-if=\"player.detectedFormat.value\"><span>Format</span><span>{{ player.detectedFormat.value }}</span></div>\n <div class=\"gt-env-row\"><span>FPS</span><span>{{ player.state.fps }}</span></div>\n <div class=\"gt-env-row\"><span>Resolution</span><span>{{ player.state.resolution }}</span></div>\n <div class=\"gt-env-row\"><span>downloaded</span><span>{{ player.state.downloaded }}</span></div>\n <div class=\"gt-env-row\"><span>decoded</span><span>{{ player.state.decoded }}</span></div>\n <div class=\"gt-env-row\"><span>Dropped</span><span>{{ player.state.droppedFrames }}</span></div>\n <div class=\"gt-env-row\"><span>Speed</span><span>{{ player.state.downloadSpeed || 0 }} KB/s</span></div>\n </template>\n </div>\n\n <!-- 加载中动画 -->\n <div class=\"gt-loading-spinner\" v-if=\"player.isLoading.value\">\n <slot name=\"loading\">\n <div class=\"gt-spinner\"></div>\n </slot>\n </div>\n\n <!-- 视频控制条 -->\n <div\n v-if=\"controlOption.show\"\n class=\"gt-video-controls\"\n :class=\"{ visible: controls.showControls.value || !player.state.isPlaying }\"\n >\n <button class=\"gt-control-btn\" @click=\"togglePlayback\">\n <svg v-if=\"player.state.isPlaying\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n </svg>\n <svg v-else viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\"/>\n </svg>\n </button>\n\n <!-- 直播标识 -->\n <span class=\"gt-live-indicator\" v-if=\"isLive\">\n <span class=\"gt-live-dot\"></span>\n <span class=\"gt-live-text\">实时</span>\n </span>\n\n <!-- 点播时间显示 -->\n <span class=\"gt-time-display\" v-else>\n <span class=\"gt-time-current\">{{ controls.formatTime(player.state.currentTime) }}</span>\n <span class=\"gt-time-separator\">/</span>\n <span class=\"gt-time-duration\">{{ controls.formatTime(player.state.duration) }}</span>\n </span>\n\n <!-- 进度条 (仅点播) -->\n <div\n v-if=\"!isLive\"\n class=\"gt-progress-container\"\n @click=\"controls.handleProgressClick\"\n @mousemove=\"controls.handleProgressHover\"\n @mouseleave=\"controls.hoverTime.value = null\"\n >\n <div class=\"gt-progress-bar\">\n <div class=\"gt-progress-buffered\" :style=\"{ width: controls.bufferProgress.value + '%' }\"></div>\n <div class=\"gt-progress-played\" :style=\"{ width: controls.playProgress.value + '%' }\">\n <div class=\"gt-progress-handle\"></div>\n </div>\n </div>\n <div\n class=\"gt-progress-tooltip\"\n v-if=\"controls.hoverTime.value !== null\"\n :style=\"{ left: controls.hoverPosition.value + '%' }\"\n >\n {{ controls.formatTime(controls.hoverTime.value) }}\n </div>\n </div>\n\n <!-- 直播流占位符 -->\n <div class=\"gt-flex-spacer\" v-else></div>\n\n <!-- 倍速按钮(仅点播) -->\n <div v-if=\"controlOption.playbackRate && !isLive\" class=\"gt-playback-rate-container\">\n <button class=\"gt-control-btn gt-playback-rate-btn\" @click=\"togglePlaybackRateMenu\" :title=\"'倍速: ' + currentPlaybackRate + 'x'\">\n <span class=\"gt-playback-rate-text\">{{ currentPlaybackRate }}x</span>\n </button>\n <div v-if=\"showPlaybackRateMenu\" class=\"gt-playback-rate-menu\">\n <button\n v-for=\"rate in playbackRates\"\n :key=\"rate\"\n class=\"gt-playback-rate-option\"\n :class=\"{ active: currentPlaybackRate === rate }\"\n @click=\"setPlaybackRate(rate)\"\n >\n {{ rate }}x\n </button>\n </div>\n </div>\n\n <!-- 环境信息按钮 -->\n <button v-if=\"controlOption.info\" class=\"gt-control-btn gt-env-info-btn\" @click=\"toggleEnvPanel\" :title=\"showEnvPanel ? '隐藏信息' : '显示信息'\">\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z\"/>\n </svg>\n </button>\n\n <!-- 全屏按钮 -->\n <button v-if=\"controlOption.fullscreen\" class=\"gt-control-btn gt-fullscreen-btn\" @click=\"toggleFullscreen\" :title=\"isFullscreen ? '退出全屏' : '全屏'\">\n <!-- 退出全屏图标 -->\n <svg v-if=\"isFullscreen\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z\"/>\n </svg>\n <!-- 全屏图标 -->\n <svg v-else viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"/>\n </svg>\n </button>\n </div>\n\n <!-- 大播放按钮(居中) -->\n <div\n class=\"gt-center-play-btn\"\n v-if=\"player.state.isLoaded && !player.state.isPlaying && !player.isLoading.value\"\n @click=\"togglePlayback\"\n >\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\"/>\n </svg>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch, onMounted, onUnmounted } from 'vue'\nimport { usePlayer } from '../composables/usePlayer'\nimport { useControls } from '../composables/useControls'\nimport { useEnvInfo } from '../composables/useEnvInfo'\nimport type { EcPlayerProps, EcPlayerExpose, EcPlayerSource, EcPlayerControlOption } from '../types'\nimport { DEFAULT_EC_PLAYER_PROPS } from '../types'\n\n// Props\nconst props = withDefaults(defineProps<EcPlayerProps>(), DEFAULT_EC_PLAYER_PROPS)\n\n// Emits\nconst emit = defineEmits<{\n (e: 'play'): void\n (e: 'pause'): void\n}>()\n\n// Canvas ref(本地)\nconst canvasRef = ref<HTMLCanvasElement | null>(null)\n\n// 容器引用(用于全屏)\nconst containerRef = ref<HTMLElement | null>(null)\n\n// 全屏状态\nconst isFullscreen = ref(false)\n\n// 倍速播放状态\nconst playbackRates = [1, 2, 4]\nconst currentPlaybackRate = ref(1)\nconst showPlaybackRateMenu = ref(false)\n\n// 解析 controlOption\nconst controlOption = computed<Required<EcPlayerControlOption>>(() => ({\n show: props.controlOption?.show ?? DEFAULT_EC_PLAYER_PROPS.controlOption.show,\n fullscreen: props.controlOption?.fullscreen ?? DEFAULT_EC_PLAYER_PROPS.controlOption.fullscreen,\n info: props.controlOption?.info ?? DEFAULT_EC_PLAYER_PROPS.controlOption.info,\n playbackRate: props.controlOption?.playbackRate ?? DEFAULT_EC_PLAYER_PROPS.controlOption.playbackRate\n}))\n\n// 环境信息逻辑\nconst { envInfo, showEnvPanel, envTypeText, toggleEnvPanel } = useEnvInfo(false)\n\n// 播放器逻辑\nconst player = usePlayer(emit)\n\n// 同步 canvas ref 到 player\nwatch(canvasRef, (el) => {\n player.canvasRef.value = el\n}, { immediate: true })\n\n// isLive 计算属性(用于模板)\nconst isLive = computed(() => player.isLive.value)\n\n// 控制条逻辑\nconst isPlayingRef = computed(() => player.state.isPlaying)\nconst isLoadedRef = computed(() => player.state.isLoaded)\nconst currentTimeRef = computed(() => player.state.currentTime)\nconst durationRef = computed(() => player.state.duration)\nconst segmentIndexRef = computed(() => player.state.segmentIndex)\nconst fetchedSegmentCountRef = computed(() => player.state.fetchedSegmentCount)\nconst totalSegmentsRef = computed(() => player.state.totalSegments)\n\nconst controls = useControls({\n isPlaying: isPlayingRef,\n isLoaded: isLoadedRef,\n currentTime: currentTimeRef,\n duration: durationRef,\n segmentIndex: segmentIndexRef,\n fetchedSegmentCount: fetchedSegmentCountRef,\n totalSegments: totalSegmentsRef,\n isLive,\n seek: player.seek\n})\n\n// 视频包装器引用\nconst videoWrapperRef = ref<HTMLElement | null>(null)\n\n// 解析 src\nfunction parseSrc(src: EcPlayerSource | undefined): { url: string; isLive: boolean } | null {\n if (!src || !src.url) return null\n return { url: src.url, isLive: src.isLive ?? false }\n}\n\n// 切换播放/暂停\nfunction togglePlayback(): void {\n if (player.state.isPlaying) {\n player.pause()\n } else {\n player.resume()\n }\n}\n\n// 切换全屏\nfunction toggleFullscreen(): void {\n if (!containerRef.value) return\n\n if (!isFullscreen.value) {\n if (containerRef.value.requestFullscreen) {\n containerRef.value.requestFullscreen()\n }\n } else {\n if (document.exitFullscreen) {\n document.exitFullscreen()\n }\n }\n}\n\n// 设置倍速\nfunction setPlaybackRate(rate: number): void {\n currentPlaybackRate.value = rate\n showPlaybackRateMenu.value = false\n player.setPlaybackRate(rate)\n}\n\n// 切换倍速菜单\nfunction togglePlaybackRateMenu(): void {\n showPlaybackRateMenu.value = !showPlaybackRateMenu.value\n}\n\n// 监听全屏变化\nfunction handleFullscreenChange(): void {\n isFullscreen.value = !!document.fullscreenElement\n}\n\n// 暴露的 play 方法(简化版)\nfunction play(): void {\n const parsed = parseSrc(props.src)\n if (parsed) {\n player.play(parsed)\n }\n}\n\n// 监听 src 变化,自动播放\nwatch(() => props.src, (newSrc) => {\n const parsed = parseSrc(newSrc)\n if (parsed && parsed.url) {\n player.play(parsed)\n }\n}, { immediate: true, deep: true })\n\n// 挂载时监听全屏事件\nonMounted(() => {\n document.addEventListener('fullscreenchange', handleFullscreenChange)\n})\n\n// 卸载时移除监听\nonUnmounted(() => {\n document.removeEventListener('fullscreenchange', handleFullscreenChange)\n})\n\n// Expose 方法\ndefineExpose<EcPlayerExpose>({\n play,\n pause: player.pause,\n seek: player.seek\n})\n</script>\n\n<style scoped>\n.gt-player-container {\n width: 100%;\n height: 100%;\n}\n\n.gt-video-wrapper {\n position: relative;\n width: 100%;\n height: 100%;\n background: #000;\n overflow: hidden;\n}\n\n.gt-player-canvas {\n width: 100%;\n height: 100%;\n object-fit: contain;\n}\n\n.gt-placeholder {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #000;\n}\n\n/* 加载中动画 */\n.gt-loading-spinner {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.5);\n z-index: 10;\n}\n\n.gt-spinner {\n width: 10%;\n max-width: 48px;\n min-width: 20px;\n aspect-ratio: 1/1;\n border: 0.3em solid rgba(255, 255, 255, 0.3);\n border-top-color: #fff;\n border-radius: 50%;\n animation: gt-spin 1s linear infinite;\n}\n\n@keyframes gt-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* 视频控制条 */\n.gt-video-controls {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n padding: 10px 16px;\n background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));\n opacity: 0;\n transition: opacity 0.3s ease;\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.gt-flex-spacer {\n flex: 1;\n}\n\n.gt-video-controls.visible {\n opacity: 1;\n}\n\n.gt-control-btn {\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n\n.gt-control-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n}\n\n.gt-control-btn svg {\n width: 14px;\n height: 14px;\n}\n\n.gt-progress-container {\n flex: 1;\n position: relative;\n cursor: pointer;\n height: 20px;\n display: flex;\n align-items: center;\n}\n\n.gt-progress-bar {\n width: 100%;\n height: 4px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 2px;\n position: relative;\n overflow: hidden;\n transition: height 0.2s ease;\n}\n\n.gt-progress-container:hover .gt-progress-bar {\n height: 6px;\n}\n\n.gt-progress-buffered {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: rgba(255, 255, 255, 0.4);\n border-radius: 2px;\n transition: width 0.1s;\n}\n\n.gt-progress-played {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: #ff2d55;\n border-radius: 2px;\n transition: width 0.1s;\n}\n\n.gt-progress-handle {\n position: absolute;\n right: -6px;\n top: 50%;\n transform: translateY(-50%);\n width: 14px;\n height: 14px;\n background: #ff2d55;\n border-radius: 50%;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n opacity: 0;\n transition: opacity 0.2s, transform 0.2s;\n}\n\n.gt-progress-container:hover .gt-progress-handle {\n opacity: 1;\n transform: translateY(-50%) scale(1.2);\n}\n\n.gt-progress-tooltip {\n position: absolute;\n bottom: calc(100% + 8px);\n transform: translateX(-50%);\n background: rgba(0, 0, 0, 0.85);\n color: white;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 11px;\n white-space: nowrap;\n pointer-events: none;\n}\n\n.gt-time-display {\n color: white;\n font-size: 12px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.gt-time-separator {\n margin: 0 4px;\n opacity: 0.6;\n}\n\n/* 直播指示器 */\n.gt-live-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n color: white;\n font-size: 12px;\n font-weight: 500;\n}\n\n.gt-live-dot {\n width: 8px;\n height: 8px;\n background: #ff2d55;\n border-radius: 50%;\n animation: gt-live-pulse 1.5s ease-in-out infinite;\n}\n\n.gt-live-text {\n color: #ff2d55;\n}\n\n@keyframes gt-live-pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.4;\n }\n}\n\n/* 倍速按钮 */\n.gt-playback-rate-container {\n position: relative;\n flex-shrink: 0;\n}\n\n.gt-playback-rate-btn {\n width: auto !important;\n min-width: 28px;\n padding: 0 8px;\n font-size: 12px;\n font-weight: 500;\n}\n\n.gt-playback-rate-text {\n color: white;\n}\n\n.gt-playback-rate-menu {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n background: rgba(0, 0, 0, 0.85);\n border-radius: 6px;\n padding: 4px 0;\n min-width: 60px;\n z-index: 20;\n animation: gt-rate-menu-fade-in 0.15s ease;\n}\n\n@keyframes gt-rate-menu-fade-in {\n from { opacity: 0; transform: translateX(-50%) translateY(4px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n}\n\n.gt-playback-rate-option {\n display: block;\n width: 100%;\n padding: 6px 12px;\n border: none;\n background: transparent;\n color: rgba(255, 255, 255, 0.8);\n font-size: 12px;\n cursor: pointer;\n text-align: center;\n transition: all 0.15s ease;\n}\n\n.gt-playback-rate-option:hover {\n background: rgba(255, 255, 255, 0.1);\n color: white;\n}\n\n.gt-playback-rate-option.active {\n color: #ff2d55;\n font-weight: 500;\n}\n\n/* 居中播放按钮 */\n.gt-center-play-btn {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 56px;\n height: 56px;\n background: rgba(0, 0, 0, 0.5);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.gt-center-play-btn:hover {\n background: rgba(0, 0, 0, 0.7);\n transform: translate(-50%, -50%) scale(1.05);\n}\n\n.gt-center-play-btn svg {\n width: 24px;\n height: 24px;\n color: white;\n margin-left: 3px;\n}\n\n/* 环境信息面板 */\n.gt-env-panel {\n position: absolute;\n top: 12px;\n left: 12px;\n background: rgba(0, 0, 0, 0.8);\n border-radius: 6px;\n padding: 8px 10px;\n font-size: 11px;\n font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n min-width: 160px;\n max-width: 200px;\n max-height: calc(100% - 24px);\n overflow-y: auto;\n backdrop-filter: blur(10px);\n animation: gt-env-fade-in 0.15s ease;\n z-index: 15;\n}\n\n.gt-env-panel::-webkit-scrollbar {\n width: 4px;\n}\n\n.gt-env-panel::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.gt-env-panel::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 2px;\n}\n\n@keyframes gt-env-fade-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.gt-env-panel .gt-env-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 2px 0;\n color: rgba(255, 255, 255, 0.7);\n}\n\n.gt-env-panel .gt-env-row span:first-child {\n color: rgba(255, 255, 255, 0.5);\n margin-right: 16px;\n}\n\n.gt-env-panel .gt-env-row span:last-child {\n font-variant-numeric: tabular-nums;\n}\n\n.gt-env-panel .gt-env-row .ok { color: #4caf50; }\n.gt-env-panel .gt-env-row .warn { color: #ff9800; }\n.gt-env-panel .gt-env-row .err { color: #f44336; }\n\n.gt-env-divider {\n height: 1px;\n background: rgba(255, 255, 255, 0.1);\n margin: 4px 0;\n}\n</style>\n"],"names":["WASMLoader","globalConfig","setLogLevel","coreSetLogLevel","_createElementBlock","_createElementVNode","_unref","_openBlock","_renderSlot","_normalizeClass","_Fragment","_toDisplayString","_normalizeStyle","_renderList"],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -92,6 +92,8 @@ export interface EcPlayerControlOption {
|
|
|
92
92
|
fullscreen?: boolean;
|
|
93
93
|
/** 是否显示环境信息按钮 */
|
|
94
94
|
info?: boolean;
|
|
95
|
+
/** 是否显示倍速按钮(仅点播) */
|
|
96
|
+
playbackRate?: boolean;
|
|
95
97
|
}
|
|
96
98
|
/**
|
|
97
99
|
* EcPlayer 组件 Props
|
|
@@ -147,6 +149,7 @@ export declare const DEFAULT_EC_PLAYER_PROPS: {
|
|
|
147
149
|
show: boolean;
|
|
148
150
|
fullscreen: boolean;
|
|
149
151
|
info: boolean;
|
|
152
|
+
playbackRate: boolean;
|
|
150
153
|
};
|
|
151
154
|
};
|
|
152
155
|
/**
|
|
@@ -200,6 +203,7 @@ export declare function getMergedConfig(props: EcPlayerProps): {
|
|
|
200
203
|
show: boolean;
|
|
201
204
|
fullscreen: boolean;
|
|
202
205
|
info: boolean;
|
|
206
|
+
playbackRate: boolean;
|
|
203
207
|
};
|
|
204
208
|
};
|
|
205
209
|
/**
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACtF,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAE/C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,gBAAgB;IAChB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,eAAe;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,eAAe;IACf,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,aAAa;IACb,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,eAAe;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,aAAa;IACb,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,sBAAsB;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,aAAa;IACb,GAAG,EAAE,MAAM,CAAA;IACX,aAAa;IACb,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,mBAAmB;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,cAAc;IACd,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,eAAe;IACf,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,iBAAiB;IACjB,IAAI,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@give-tech/ec-player-vue",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.42",
|
|
4
4
|
"description": "EcPlayer Vue 3 Component - HLS/FLV Streaming Video Player",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"typecheck": "tsc --noEmit"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@give-tech/ec-player": "^0.0.1-beta.
|
|
25
|
+
"@give-tech/ec-player": "^0.0.1-beta.42"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"vue": "^3.3.0"
|