@give-tech/ec-player-vue 0.0.1-beta.1 → 0.0.1-beta.2

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.
@@ -43,6 +43,8 @@ export interface UsePlayerReturn {
43
43
  getCurrentTime: () => number;
44
44
  /** 获取总时长 */
45
45
  getDuration: () => number;
46
+ /** 容器尺寸变化时调用 */
47
+ resize: () => void;
46
48
  /** 销毁播放器 */
47
49
  destroy: () => void;
48
50
  }
@@ -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,CA4NjB"}
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,gBAAgB;IAChB,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,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,CAkOjB"}
@@ -1,24 +1,22 @@
1
1
 
2
- .gt-player-container[data-v-d2d418df] {
2
+ .gt-player-container[data-v-c1c61728] {
3
3
  width: 100%;
4
4
  height: 100%;
5
5
  }
6
- .gt-video-wrapper[data-v-d2d418df] {
6
+ .gt-video-wrapper[data-v-c1c61728] {
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-d2d418df] {
13
+ .gt-player-canvas[data-v-c1c61728] {
14
14
  position: absolute;
15
15
  top: 50%;
16
16
  left: 50%;
17
17
  transform: translate(-50%, -50%);
18
- max-width: 100%;
19
- max-height: 100%;
20
18
  }
21
- .gt-placeholder[data-v-d2d418df] {
19
+ .gt-placeholder[data-v-c1c61728] {
22
20
  position: absolute;
23
21
  top: 0;
24
22
  left: 0;
@@ -31,7 +29,7 @@
31
29
  }
32
30
 
33
31
  /* 加载中动画 */
34
- .gt-loading-spinner[data-v-d2d418df] {
32
+ .gt-loading-spinner[data-v-c1c61728] {
35
33
  position: absolute;
36
34
  top: 0;
37
35
  left: 0;
@@ -43,22 +41,22 @@
43
41
  background: rgba(0, 0, 0, 0.5);
44
42
  z-index: 10;
45
43
  }
46
- .gt-spinner[data-v-d2d418df] {
44
+ .gt-spinner[data-v-c1c61728] {
47
45
  width: 8vmin;
48
46
  height: 8vmin;
49
47
  border: 0.5vmin solid rgba(255, 255, 255, 0.3);
50
48
  border-top-color: #fff;
51
49
  border-radius: 50%;
52
- animation: gt-spin-d2d418df 1s linear infinite;
50
+ animation: gt-spin-c1c61728 1s linear infinite;
53
51
  }
54
- @keyframes gt-spin-d2d418df {
52
+ @keyframes gt-spin-c1c61728 {
55
53
  to {
56
54
  transform: rotate(360deg);
57
55
  }
58
56
  }
59
57
 
60
58
  /* 视频控制条 */
61
- .gt-video-controls[data-v-d2d418df] {
59
+ .gt-video-controls[data-v-c1c61728] {
62
60
  position: absolute;
63
61
  bottom: 0;
64
62
  left: 0;
@@ -71,13 +69,13 @@ to {
71
69
  align-items: center;
72
70
  gap: 12px;
73
71
  }
74
- .gt-flex-spacer[data-v-d2d418df] {
72
+ .gt-flex-spacer[data-v-c1c61728] {
75
73
  flex: 1;
76
74
  }
77
- .gt-video-controls.visible[data-v-d2d418df] {
75
+ .gt-video-controls.visible[data-v-c1c61728] {
78
76
  opacity: 1;
79
77
  }
80
- .gt-control-btn[data-v-d2d418df] {
78
+ .gt-control-btn[data-v-c1c61728] {
81
79
  width: 28px;
82
80
  height: 28px;
83
81
  border: none;
@@ -91,14 +89,14 @@ to {
91
89
  transition: all 0.2s ease;
92
90
  flex-shrink: 0;
93
91
  }
94
- .gt-control-btn[data-v-d2d418df]:hover {
92
+ .gt-control-btn[data-v-c1c61728]:hover {
95
93
  background: rgba(255, 255, 255, 0.2);
96
94
  }
97
- .gt-control-btn svg[data-v-d2d418df] {
95
+ .gt-control-btn svg[data-v-c1c61728] {
98
96
  width: 14px;
99
97
  height: 14px;
100
98
  }
101
- .gt-progress-container[data-v-d2d418df] {
99
+ .gt-progress-container[data-v-c1c61728] {
102
100
  flex: 1;
103
101
  position: relative;
104
102
  cursor: pointer;
@@ -106,7 +104,7 @@ to {
106
104
  display: flex;
107
105
  align-items: center;
108
106
  }
109
- .gt-progress-bar[data-v-d2d418df] {
107
+ .gt-progress-bar[data-v-c1c61728] {
110
108
  width: 100%;
111
109
  height: 4px;
112
110
  background: rgba(255, 255, 255, 0.2);
@@ -115,10 +113,10 @@ to {
115
113
  overflow: hidden;
116
114
  transition: height 0.2s ease;
117
115
  }
118
- .gt-progress-container:hover .gt-progress-bar[data-v-d2d418df] {
116
+ .gt-progress-container:hover .gt-progress-bar[data-v-c1c61728] {
119
117
  height: 6px;
120
118
  }
121
- .gt-progress-buffered[data-v-d2d418df] {
119
+ .gt-progress-buffered[data-v-c1c61728] {
122
120
  position: absolute;
123
121
  top: 0;
124
122
  left: 0;
@@ -127,7 +125,7 @@ to {
127
125
  border-radius: 2px;
128
126
  transition: width 0.1s;
129
127
  }
130
- .gt-progress-played[data-v-d2d418df] {
128
+ .gt-progress-played[data-v-c1c61728] {
131
129
  position: absolute;
132
130
  top: 0;
133
131
  left: 0;
@@ -136,7 +134,7 @@ to {
136
134
  border-radius: 2px;
137
135
  transition: width 0.1s;
138
136
  }
139
- .gt-progress-handle[data-v-d2d418df] {
137
+ .gt-progress-handle[data-v-c1c61728] {
140
138
  position: absolute;
141
139
  right: -6px;
142
140
  top: 50%;
@@ -149,11 +147,11 @@ to {
149
147
  opacity: 0;
150
148
  transition: opacity 0.2s, transform 0.2s;
151
149
  }
152
- .gt-progress-container:hover .gt-progress-handle[data-v-d2d418df] {
150
+ .gt-progress-container:hover .gt-progress-handle[data-v-c1c61728] {
153
151
  opacity: 1;
154
152
  transform: translateY(-50%) scale(1.2);
155
153
  }
156
- .gt-progress-tooltip[data-v-d2d418df] {
154
+ .gt-progress-tooltip[data-v-c1c61728] {
157
155
  position: absolute;
158
156
  bottom: calc(100% + 8px);
159
157
  transform: translateX(-50%);
@@ -165,20 +163,20 @@ to {
165
163
  white-space: nowrap;
166
164
  pointer-events: none;
167
165
  }
168
- .gt-time-display[data-v-d2d418df] {
166
+ .gt-time-display[data-v-c1c61728] {
169
167
  color: white;
170
168
  font-size: 12px;
171
169
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
172
170
  white-space: nowrap;
173
171
  flex-shrink: 0;
174
172
  }
175
- .gt-time-separator[data-v-d2d418df] {
173
+ .gt-time-separator[data-v-c1c61728] {
176
174
  margin: 0 4px;
177
175
  opacity: 0.6;
178
176
  }
179
177
 
180
178
  /* 直播指示器 */
181
- .gt-live-indicator[data-v-d2d418df] {
179
+ .gt-live-indicator[data-v-c1c61728] {
182
180
  display: flex;
183
181
  align-items: center;
184
182
  gap: 6px;
@@ -186,17 +184,17 @@ to {
186
184
  font-size: 12px;
187
185
  font-weight: 500;
188
186
  }
189
- .gt-live-dot[data-v-d2d418df] {
187
+ .gt-live-dot[data-v-c1c61728] {
190
188
  width: 8px;
191
189
  height: 8px;
192
190
  background: #ff2d55;
193
191
  border-radius: 50%;
194
- animation: gt-live-pulse-d2d418df 1.5s ease-in-out infinite;
192
+ animation: gt-live-pulse-c1c61728 1.5s ease-in-out infinite;
195
193
  }
196
- .gt-live-text[data-v-d2d418df] {
194
+ .gt-live-text[data-v-c1c61728] {
197
195
  color: #ff2d55;
198
196
  }
199
- @keyframes gt-live-pulse-d2d418df {
197
+ @keyframes gt-live-pulse-c1c61728 {
200
198
  0%, 100% {
201
199
  opacity: 1;
202
200
  }
@@ -206,7 +204,7 @@ to {
206
204
  }
207
205
 
208
206
  /* 居中播放按钮 */
209
- .gt-center-play-btn[data-v-d2d418df] {
207
+ .gt-center-play-btn[data-v-c1c61728] {
210
208
  position: absolute;
211
209
  top: 50%;
212
210
  left: 50%;
@@ -221,11 +219,11 @@ to {
221
219
  cursor: pointer;
222
220
  transition: all 0.2s ease;
223
221
  }
224
- .gt-center-play-btn[data-v-d2d418df]:hover {
222
+ .gt-center-play-btn[data-v-c1c61728]:hover {
225
223
  background: rgba(0, 0, 0, 0.7);
226
224
  transform: translate(-50%, -50%) scale(1.05);
227
225
  }
228
- .gt-center-play-btn svg[data-v-d2d418df] {
226
+ .gt-center-play-btn svg[data-v-c1c61728] {
229
227
  width: 24px;
230
228
  height: 24px;
231
229
  color: white;
@@ -233,7 +231,7 @@ to {
233
231
  }
234
232
 
235
233
  /* 环境信息面板 */
236
- .gt-env-panel[data-v-d2d418df] {
234
+ .gt-env-panel[data-v-c1c61728] {
237
235
  position: absolute;
238
236
  top: 12px;
239
237
  left: 12px;
@@ -247,46 +245,46 @@ to {
247
245
  max-height: calc(100% - 24px);
248
246
  overflow-y: auto;
249
247
  backdrop-filter: blur(10px);
250
- animation: gt-env-fade-in-d2d418df 0.15s ease;
248
+ animation: gt-env-fade-in-c1c61728 0.15s ease;
251
249
  z-index: 15;
252
250
  }
253
- .gt-env-panel[data-v-d2d418df]::-webkit-scrollbar {
251
+ .gt-env-panel[data-v-c1c61728]::-webkit-scrollbar {
254
252
  width: 4px;
255
253
  }
256
- .gt-env-panel[data-v-d2d418df]::-webkit-scrollbar-track {
254
+ .gt-env-panel[data-v-c1c61728]::-webkit-scrollbar-track {
257
255
  background: transparent;
258
256
  }
259
- .gt-env-panel[data-v-d2d418df]::-webkit-scrollbar-thumb {
257
+ .gt-env-panel[data-v-c1c61728]::-webkit-scrollbar-thumb {
260
258
  background: rgba(255, 255, 255, 0.3);
261
259
  border-radius: 2px;
262
260
  }
263
- @keyframes gt-env-fade-in-d2d418df {
261
+ @keyframes gt-env-fade-in-c1c61728 {
264
262
  from { opacity: 0; transform: translateY(-4px);
265
263
  }
266
264
  to { opacity: 1; transform: translateY(0);
267
265
  }
268
266
  }
269
- .gt-env-panel .gt-env-row[data-v-d2d418df] {
267
+ .gt-env-panel .gt-env-row[data-v-c1c61728] {
270
268
  display: flex;
271
269
  justify-content: space-between;
272
270
  align-items: center;
273
271
  padding: 2px 0;
274
272
  color: rgba(255, 255, 255, 0.7);
275
273
  }
276
- .gt-env-panel .gt-env-row span[data-v-d2d418df]:first-child {
274
+ .gt-env-panel .gt-env-row span[data-v-c1c61728]:first-child {
277
275
  color: rgba(255, 255, 255, 0.5);
278
276
  margin-right: 16px;
279
277
  }
280
- .gt-env-panel .gt-env-row span[data-v-d2d418df]:last-child {
278
+ .gt-env-panel .gt-env-row span[data-v-c1c61728]:last-child {
281
279
  font-variant-numeric: tabular-nums;
282
280
  }
283
- .gt-env-panel .gt-env-row .ok[data-v-d2d418df] { color: #4caf50;
281
+ .gt-env-panel .gt-env-row .ok[data-v-c1c61728] { color: #4caf50;
284
282
  }
285
- .gt-env-panel .gt-env-row .warn[data-v-d2d418df] { color: #ff9800;
283
+ .gt-env-panel .gt-env-row .warn[data-v-c1c61728] { color: #ff9800;
286
284
  }
287
- .gt-env-panel .gt-env-row .err[data-v-d2d418df] { color: #f44336;
285
+ .gt-env-panel .gt-env-row .err[data-v-c1c61728] { color: #f44336;
288
286
  }
289
- .gt-env-divider[data-v-d2d418df] {
287
+ .gt-env-divider[data-v-c1c61728] {
290
288
  height: 1px;
291
289
  background: rgba(255, 255, 255, 0.1);
292
290
  margin: 4px 0;
package/dist/index.js CHANGED
@@ -213,6 +213,9 @@ function usePlayer(emit) {
213
213
  player.value = null;
214
214
  }
215
215
  }
216
+ function resize() {
217
+ player.value?.resize();
218
+ }
216
219
  onUnmounted(() => {
217
220
  destroy();
218
221
  });
@@ -233,6 +236,7 @@ function usePlayer(emit) {
233
236
  getState,
234
237
  getCurrentTime,
235
238
  getDuration,
239
+ resize,
236
240
  destroy
237
241
  };
238
242
  }
@@ -495,11 +499,20 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
495
499
  player.play(parsed);
496
500
  }
497
501
  }, { immediate: true, deep: true });
502
+ let resizeObserver = null;
498
503
  onMounted(() => {
499
504
  document.addEventListener("fullscreenchange", handleFullscreenChange);
505
+ if (containerRef.value) {
506
+ resizeObserver = new ResizeObserver(() => {
507
+ player.resize();
508
+ });
509
+ resizeObserver.observe(containerRef.value);
510
+ }
500
511
  });
501
512
  onUnmounted(() => {
502
513
  document.removeEventListener("fullscreenchange", handleFullscreenChange);
514
+ resizeObserver?.disconnect();
515
+ resizeObserver = null;
503
516
  });
504
517
  __expose({
505
518
  play,
@@ -731,7 +744,7 @@ const _export_sfc = (sfc, props) => {
731
744
  }
732
745
  return target;
733
746
  };
734
- const EcPlayer = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-d2d418df"]]);
747
+ const EcPlayer = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-c1c61728"]]);
735
748
  export {
736
749
  DEFAULT_EC_PLAYER_PROPS,
737
750
  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 */\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 // 当前播放器配置(初始化时合并全局配置和默认值)\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 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 }\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 // 如果正在加载中,先销毁当前播放器\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 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 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 } finally {\n isLoading.value = false\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 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 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 (segmentIndex.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\"\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 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 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 position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n max-width: 100%;\n max-height: 100%;\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: 8vmin;\n height: 8vmin;\n border: 0.5vmin 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":["globalConfig","setLogLevel","coreSetLogLevel","_createElementBlock","_createElementVNode","_unref","_openBlock","_renderSlot","_normalizeClass","_Fragment","_toDisplayString","_normalizeStyle"],"mappings":"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"}
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 */\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 resize: () => void\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 // 当前播放器配置(初始化时合并全局配置和默认值)\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 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 }\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 // 如果正在加载中,先销毁当前播放器\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 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 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 } finally {\n isLoading.value = false\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 function resize(): void {\n player.value?.resize()\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 resize,\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 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 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 (segmentIndex.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\"\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 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 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// 挂载时监听全屏事件和尺寸变化\nlet resizeObserver: ResizeObserver | null = null\n\nonMounted(() => {\n document.addEventListener('fullscreenchange', handleFullscreenChange)\n\n // 监听容器尺寸变化\n if (containerRef.value) {\n resizeObserver = new ResizeObserver(() => {\n player.resize()\n })\n resizeObserver.observe(containerRef.value)\n }\n})\n\n// 卸载时移除监听\nonUnmounted(() => {\n document.removeEventListener('fullscreenchange', handleFullscreenChange)\n resizeObserver?.disconnect()\n resizeObserver = null\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 position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\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: 8vmin;\n height: 8vmin;\n border: 0.5vmin 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":["globalConfig","setLogLevel","coreSetLogLevel","_createElementBlock","_createElementVNode","_unref","_openBlock","_renderSlot","_normalizeClass","_Fragment","_toDisplayString","_normalizeStyle"],"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.1",
3
+ "version": "0.0.1-beta.2",
4
4
  "description": "EcPlayer Vue 3 Component - HLS/FLV Streaming Video Player",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",