@taole/giftstage 0.1.4

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/README.md ADDED
@@ -0,0 +1,458 @@
1
+ # GiftStage
2
+
3
+ 统一的 Web 礼物播放框架,支持:
4
+
5
+ - `SVGA`
6
+ - `VAP / VAPX`
7
+ - 透明视频 `AlphaVideo`
8
+
9
+ 底层支持:
10
+
11
+ - `WebGPU`
12
+ - `WebGL2`
13
+ - `WebGL1` 兼容兜底
14
+
15
+ 适用场景:
16
+
17
+ - 直播间礼物
18
+ - 大批同屏动画
19
+ - 需要统一接入 `SVGA / VAP / 透明视频` 的业务场景
20
+
21
+ ## npm 包信息
22
+
23
+ - 包名:`@taole/giftstage`
24
+ - npm:`npm i @taole/giftstage`
25
+ - ESM 导入:
26
+
27
+ ```ts
28
+ import { GiftStage } from '@taole/giftstage';
29
+ ```
30
+
31
+ - CommonJS 导入:
32
+
33
+ ```js
34
+ const { GiftStage } = require('@taole/giftstage');
35
+ ```
36
+
37
+ ## 特性
38
+
39
+ - 统一 API:`addGift()` 即可播放三类礼物
40
+ - `SVGA` 支持 Worker 解析、atlas 缓存、slot 替换
41
+ - `VAP / AlphaVideo` 支持实验性的 `WebCodecs` 和稳定的 `HTMLVideoElement` 双路径
42
+ - 同源视频播放实例、纹理、资源复用
43
+ - 内存 LRU 缓存,默认 `128MB`
44
+ - `IndexedDB` 磁盘 LRU 缓存,默认 `2048MB`
45
+ - `x / y` 支持百分比定位
46
+ - `width / height` 支持按礼物原始尺寸自动补全
47
+
48
+ ## 安装
49
+
50
+ ```bash
51
+ npm install
52
+ ```
53
+
54
+ 安装发布包:
55
+
56
+ ```bash
57
+ npm i @taole/giftstage
58
+ ```
59
+
60
+ ## 开发
61
+
62
+ ```bash
63
+ npm run dev
64
+ ```
65
+
66
+ ## 构建
67
+
68
+ ```bash
69
+ npm run build
70
+ ```
71
+
72
+ Demo 构建:
73
+
74
+ ```bash
75
+ npm run build:demo
76
+ ```
77
+
78
+ ## 快速开始
79
+
80
+ ```ts
81
+ import { GiftStage } from '@taole/giftstage';
82
+
83
+ const container = document.getElementById('app')!;
84
+
85
+ const stage = new GiftStage({
86
+ container,
87
+ preferWebGPU: true,
88
+ });
89
+
90
+ await stage.ready;
91
+
92
+ await stage.addGift({
93
+ type: 'svga',
94
+ source: 'https://example.com/demo.svga',
95
+ x: 100,
96
+ y: 100,
97
+ loop: 0,
98
+ });
99
+ ```
100
+
101
+ ## 核心 API
102
+
103
+ ### `new GiftStage(options)`
104
+
105
+ 创建礼物舞台。
106
+
107
+ 常用配置:
108
+
109
+ - `container: HTMLElement`
110
+ 挂载容器。
111
+
112
+ - `resolution?: number`
113
+ 指定 canvas backing store 分辨率倍率。默认跟随 `devicePixelRatio`。
114
+
115
+ - `antialias?: boolean`
116
+ 是否开启抗锯齿。
117
+
118
+ - `preferWebGPU?: boolean`
119
+ 是否优先使用 `WebGPU`。
120
+
121
+ - `forceWebGL1?: boolean`
122
+ 强制走 `WebGL1`,用于兼容性验证。
123
+
124
+ - `preferWebCodecs?: boolean`
125
+ 实验性特性。默认关闭;显式传 `true` 时才会尝试用 `WebCodecs` 播放 `VAP / AlphaVideo`。
126
+
127
+ - `shareIdenticalVideoPlayback?: boolean`
128
+ 是否复用近同时起播的同源视频播放实例。默认开启。
129
+
130
+ - `sharedVideoPlaybackWindowMs?: number`
131
+ 同源视频共享播放窗口,默认 `100ms`。
132
+
133
+ - `webCodecsVideoAtlas?: { width: number; height: number }`
134
+ 实验性 `WebCodecs` 视频共享 atlas 配置。
135
+
136
+ - `webCodecsDecodeInWorker?: boolean`
137
+ 实验性 `WebCodecs` 选项,控制是否在 Worker 中执行解码。
138
+
139
+ - `webCodecsMaxDecodedFrames?: number`
140
+ 实验性 `WebCodecs` 选项,控制保留的最大解码帧数。
141
+
142
+ - `webCodecsDecodeAheadFrames?: number`
143
+ 实验性 `WebCodecs` 选项,控制前向解码帧数。
144
+
145
+ - `svgaParseInWorker?: boolean`
146
+ 是否在 Worker 中解析 SVGA。
147
+
148
+ - `maxConcurrentParse?: number`
149
+ 资源下载 / 解析 / 图像解码的并发数。
150
+ 不传时自动跟随 `navigator.hardwareConcurrency`。
151
+
152
+ - `onError?: (error: Error) => void`
153
+ 统一错误回调。
154
+
155
+ ### `await stage.ready`
156
+
157
+ 等待底层后端和运行环境初始化完成。建议在第一次 `addGift()` 前等待。
158
+
159
+ ### `stage.addGift(options)`
160
+
161
+ 插入一个礼物,返回:
162
+
163
+ ```ts
164
+ Promise<GiftHandle>
165
+ ```
166
+
167
+ ### `stage.removeGift(id)`
168
+
169
+ 按 ID 移除礼物。
170
+
171
+ ### `stage.removeAll()`
172
+
173
+ 移除全部礼物。
174
+
175
+ ### `stage.pause()`
176
+
177
+ 暂停舞台。
178
+
179
+ ### `stage.resume()`
180
+
181
+ 恢复舞台。
182
+
183
+ ### `stage.destroy()`
184
+
185
+ 销毁舞台并释放资源。
186
+
187
+ ## `addGift()` 参数
188
+
189
+ ### 通用参数
190
+
191
+ - `type: 'svga' | 'vap' | 'alphaVideo'`
192
+ - `source: string | ArrayBuffer`
193
+ - `x: number | \`${number}%\``
194
+ - `y: number | \`${number}%\``
195
+ - `width?: number`
196
+ - `height?: number`
197
+ - `objectFit?: 'contain' | 'fill'`
198
+ - `loop?: number`
199
+ - `0` 表示无限循环
200
+ - `mute?: boolean`
201
+ - `onComplete?: (gift) => void`
202
+
203
+ 飞行动画相关:
204
+
205
+ - `flyTo?: { x: number; y: number }`
206
+ - `scaleTo?: number`
207
+ - `flyDuration?: number`
208
+ - `easing?: (t: number) => number`
209
+ - `onFlyComplete?: (gift) => void`
210
+
211
+ ### 宽高默认行为
212
+
213
+ `width / height` 现在是可选参数,规则如下:
214
+
215
+ - 两个都传:按传入值显示
216
+ - 只传 `width`:`height` 按礼物原始宽高比自动补全
217
+ - 只传 `height`:`width` 按礼物原始宽高比自动补全
218
+ - 两个都不传:默认使用礼物原始宽高
219
+ - 如果两个都不传,且礼物原始宽高大于当前画布,则会按画布尺寸等比缩小后再显示
220
+
221
+ 例如:
222
+
223
+ ```ts
224
+ await stage.addGift({
225
+ type: 'svga',
226
+ source: 'https://example.com/demo.svga',
227
+ x: '50%',
228
+ y: '50%',
229
+ loop: 0,
230
+ });
231
+ ```
232
+
233
+ 这时会使用该礼物的原始尺寸;如果原始尺寸超出舞台,则自动缩放到舞台内。
234
+
235
+ ### 百分比坐标
236
+
237
+ `x / y` 支持百分比,例如:
238
+
239
+ ```ts
240
+ await stage.addGift({
241
+ type: 'svga',
242
+ source: 'https://example.com/demo.svga',
243
+ x: '50%',
244
+ y: '50%',
245
+ width: 300,
246
+ height: 300,
247
+ loop: 0,
248
+ });
249
+ ```
250
+
251
+ 语义是:
252
+
253
+ - `x: '50%'` 按容器宽度的 `50%` 定位,并减去自身一半宽度
254
+ - `y: '50%'` 按容器高度的 `50%` 定位,并减去自身一半高度
255
+
256
+ 也就是接近:
257
+
258
+ ```css
259
+ left: 50%;
260
+ top: 50%;
261
+ transform: translate(-50%, -50%);
262
+ ```
263
+
264
+ 如果是数值,则继续按原来的像素坐标语义处理。
265
+
266
+ ## 三类礼物示例
267
+
268
+ ### 播放 SVGA
269
+
270
+ ```ts
271
+ await stage.addGift({
272
+ type: 'svga',
273
+ source: 'https://example.com/demo.svga',
274
+ x: 20,
275
+ y: 20,
276
+ width: 300,
277
+ height: 300,
278
+ loop: 1,
279
+ });
280
+ ```
281
+
282
+ ### 播放 VAP
283
+
284
+ ```ts
285
+ await stage.addGift({
286
+ type: 'vap',
287
+ source: 'https://example.com/demo.mp4',
288
+ config: 'https://example.com/demo.json',
289
+ x: 20,
290
+ y: 20,
291
+ width: 400,
292
+ height: 220,
293
+ loop: 0,
294
+ });
295
+ ```
296
+
297
+ ### 播放透明视频
298
+
299
+ ```ts
300
+ await stage.addGift({
301
+ type: 'alphaVideo',
302
+ source: 'https://example.com/demo.mp4',
303
+ x: 20,
304
+ y: 20,
305
+ width: 400,
306
+ height: 220,
307
+ loop: 0,
308
+ });
309
+ ```
310
+
311
+ ## Slot 替换
312
+
313
+ ### SVGA
314
+
315
+ 使用 `svgaSlots`:
316
+
317
+ ```ts
318
+ await stage.addGift({
319
+ type: 'svga',
320
+ source: 'https://example.com/demo.svga',
321
+ x: 0,
322
+ y: 0,
323
+ width: 400,
324
+ height: 400,
325
+ svgaSlots: {
326
+ avatar: { image: avatarImage },
327
+ title: {
328
+ text: 'Hello',
329
+ color: '#ff0000',
330
+ mode: 'dynamic',
331
+ },
332
+ },
333
+ });
334
+ ```
335
+
336
+ 支持:
337
+
338
+ - `TexImageSource`
339
+ - 文本配置
340
+ - 图片配置
341
+
342
+ ### VAP / VAPX
343
+
344
+ 使用 `vapSlots`:
345
+
346
+ ```ts
347
+ await stage.addGift({
348
+ type: 'vap',
349
+ source: 'https://example.com/demo.mp4',
350
+ config: 'https://example.com/demo.json',
351
+ x: 0,
352
+ y: 0,
353
+ width: 400,
354
+ height: 400,
355
+ vapSlots: {
356
+ welcome01: '欢迎进入房间',
357
+ avatar_left: 'https://example.com/avatar.png',
358
+ },
359
+ });
360
+ ```
361
+
362
+ 支持:
363
+
364
+ - 文本字符串
365
+ - 图片 URL
366
+ - `TexImageSource`
367
+ - 结构化文本 / 图片对象
368
+
369
+ ## 后端策略
370
+
371
+ 默认回退顺序:
372
+
373
+ 1. `WebGPU`
374
+ 2. `WebGL2`
375
+ 3. `WebGL1`
376
+
377
+ 说明:
378
+
379
+ - `WebGPU` 仅在浏览器支持相关必要能力时启用
380
+ - `WebGL1` 主要用于兼容兜底,不以性能最优为目标
381
+ - demo 中可手动强制切换到 `WebGL1`
382
+
383
+ ## 缓存策略
384
+
385
+ ### 内存缓存
386
+
387
+ - 默认 `128MB`
388
+ - LRU 淘汰
389
+
390
+ 缓存内容包括:
391
+
392
+ - 原始资源字节
393
+ - 文本 / JSON
394
+ - `SVGA` worker payload
395
+ - `SVGA` atlas 资产
396
+
397
+ ### `IndexedDB` 磁盘缓存
398
+
399
+ - 默认 `2048MB`
400
+ - LRU 淘汰
401
+ - 读取命中会刷新最近访问时间
402
+ - 超出预算时按最久未使用记录淘汰
403
+
404
+ 异常情况处理:
405
+
406
+ - `IndexedDB` 不可用、事务失败、写入失败、容量不足时,会自动降级
407
+ - 损坏的 `SVGA` 磁盘缓存会自动删除并重新生成
408
+
409
+ ## 项目结构
410
+
411
+ 主要目录:
412
+
413
+ - `src/`
414
+ 核心源码
415
+ - `docs/`
416
+ 设计与汇总文档
417
+ - `publish/`
418
+ 发布脚本
419
+ - `static/`
420
+ demo 依赖资源
421
+ - `tests/`
422
+ 测试
423
+
424
+ ## 对外导出
425
+
426
+ 入口文件:
427
+
428
+ - [src/index.ts](</D:/MyDocuments/UnityProjects/SVGAPlayer-Unity/gift-stage/src/index.ts>)
429
+
430
+ 主要导出:
431
+
432
+ - `GiftStage`
433
+ - `createBackend`
434
+ - `WebGPUBackend`
435
+ - `WebGL2Backend`
436
+ - `WebGL1Backend`
437
+ - `parseSVGA`
438
+ - `buildAtlas`
439
+ - `parseVAPConfig`
440
+ - 相关类型定义
441
+
442
+ ## Demo
443
+
444
+ Demo 入口:
445
+
446
+ - [index.html](</D:/MyDocuments/UnityProjects/SVGAPlayer-Unity/gift-stage/index.html>)
447
+
448
+ 可用于验证:
449
+
450
+ - `SVGA / VAP / AlphaVideo` 播放
451
+ - slot 替换
452
+ - `WebGPU / WebGL2 / WebGL1` 切换
453
+ - 大批同屏压测
454
+
455
+ ## 相关文档
456
+
457
+ - 优化汇总:
458
+ [docs/giftstage-optimization-summary.md](</D:/MyDocuments/UnityProjects/SVGAPlayer-Unity/gift-stage/docs/giftstage-optimization-summary.md>)