@spatialwalk/avatarkit 1.0.0-beta.3 → 1.0.0-beta.31
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/CHANGELOG.md +441 -0
- package/README.md +328 -138
- package/dist/StreamingAudioPlayer-B07iPxK4.js +398 -0
- package/dist/animation/AnimationWebSocketClient.d.ts +6 -24
- package/dist/animation/utils/eventEmitter.d.ts +0 -4
- package/dist/animation/utils/flameConverter.d.ts +3 -11
- package/dist/audio/AnimationPlayer.d.ts +5 -29
- package/dist/audio/StreamingAudioPlayer.d.ts +8 -66
- package/dist/avatar_core_wasm-i0Ocpx6q.js +2693 -0
- package/dist/avatar_core_wasm.wasm +0 -0
- package/dist/config/app-config.d.ts +4 -13
- package/dist/config/constants.d.ts +18 -11
- package/dist/config/sdk-config-loader.d.ts +2 -9
- package/dist/core/Avatar.d.ts +0 -15
- package/dist/core/AvatarController.d.ts +49 -109
- package/dist/core/AvatarDownloader.d.ts +0 -95
- package/dist/core/AvatarManager.d.ts +7 -18
- package/dist/core/AvatarSDK.d.ts +21 -0
- package/dist/core/AvatarView.d.ts +25 -119
- package/dist/core/NetworkLayer.d.ts +1 -0
- package/dist/generated/driveningress/v1/driveningress.d.ts +1 -12
- package/dist/generated/driveningress/v2/driveningress.d.ts +0 -3
- package/dist/generated/google/protobuf/struct.d.ts +5 -39
- package/dist/generated/google/protobuf/timestamp.d.ts +1 -103
- package/dist/index-CCBBCJi2.js +7915 -0
- package/dist/index.d.ts +1 -6
- package/dist/index.js +17 -17
- package/dist/renderer/RenderSystem.d.ts +1 -77
- package/dist/renderer/covariance.d.ts +0 -12
- package/dist/renderer/renderer.d.ts +0 -1
- package/dist/renderer/sortSplats.d.ts +0 -11
- package/dist/renderer/webgl/reorderData.d.ts +0 -13
- package/dist/renderer/webgl/webglRenderer.d.ts +3 -40
- package/dist/renderer/webgpu/webgpuRenderer.d.ts +3 -28
- package/dist/types/character-settings.d.ts +0 -5
- package/dist/types/character.d.ts +3 -21
- package/dist/types/index.d.ts +38 -18
- package/dist/utils/animation-interpolation.d.ts +3 -13
- package/dist/utils/client-id.d.ts +1 -0
- package/dist/utils/cls-tracker.d.ts +11 -0
- package/dist/utils/conversationId.d.ts +1 -0
- package/dist/utils/error-utils.d.ts +1 -25
- package/dist/utils/heartbeat-manager.d.ts +18 -0
- package/dist/utils/id-manager.d.ts +37 -0
- package/dist/utils/logger.d.ts +5 -11
- package/dist/utils/usage-tracker.d.ts +5 -0
- package/dist/vanilla/vite.config.d.ts +2 -0
- package/dist/wasm/avatarCoreAdapter.d.ts +11 -97
- package/dist/wasm/avatarCoreMemory.d.ts +5 -54
- package/package.json +10 -4
- package/dist/StreamingAudioPlayer-BeLlDiwE.js +0 -288
- package/dist/StreamingAudioPlayer-BeLlDiwE.js.map +0 -1
- package/dist/animation/AnimationWebSocketClient.d.ts.map +0 -1
- package/dist/animation/utils/eventEmitter.d.ts.map +0 -1
- package/dist/animation/utils/flameConverter.d.ts.map +0 -1
- package/dist/audio/AnimationPlayer.d.ts.map +0 -1
- package/dist/audio/StreamingAudioPlayer.d.ts.map +0 -1
- package/dist/avatar_core_wasm-DmkU6dYn.js +0 -1666
- package/dist/avatar_core_wasm-DmkU6dYn.js.map +0 -1
- package/dist/config/app-config.d.ts.map +0 -1
- package/dist/config/constants.d.ts.map +0 -1
- package/dist/config/sdk-config-loader.d.ts.map +0 -1
- package/dist/core/Avatar.d.ts.map +0 -1
- package/dist/core/AvatarController.d.ts.map +0 -1
- package/dist/core/AvatarDownloader.d.ts.map +0 -1
- package/dist/core/AvatarKit.d.ts +0 -60
- package/dist/core/AvatarKit.d.ts.map +0 -1
- package/dist/core/AvatarManager.d.ts.map +0 -1
- package/dist/core/AvatarView.d.ts.map +0 -1
- package/dist/generated/driveningress/v1/driveningress.d.ts.map +0 -1
- package/dist/generated/driveningress/v2/driveningress.d.ts.map +0 -1
- package/dist/generated/google/protobuf/struct.d.ts.map +0 -1
- package/dist/generated/google/protobuf/timestamp.d.ts.map +0 -1
- package/dist/index-NmYXWJnL.js +0 -9712
- package/dist/index-NmYXWJnL.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/renderer/RenderSystem.d.ts.map +0 -1
- package/dist/renderer/covariance.d.ts.map +0 -1
- package/dist/renderer/renderer.d.ts.map +0 -1
- package/dist/renderer/sortSplats.d.ts.map +0 -1
- package/dist/renderer/webgl/reorderData.d.ts.map +0 -1
- package/dist/renderer/webgl/webglRenderer.d.ts.map +0 -1
- package/dist/renderer/webgpu/webgpuRenderer.d.ts.map +0 -1
- package/dist/types/character-settings.d.ts.map +0 -1
- package/dist/types/character.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/utils/animation-interpolation.d.ts.map +0 -1
- package/dist/utils/error-utils.d.ts.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/posthog-tracker.d.ts +0 -82
- package/dist/utils/posthog-tracker.d.ts.map +0 -1
- package/dist/utils/reqId.d.ts +0 -20
- package/dist/utils/reqId.d.ts.map +0 -1
- package/dist/wasm/avatarCoreAdapter.d.ts.map +0 -1
- package/dist/wasm/avatarCoreMemory.d.ts.map +0 -1
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { AvatarCoreMemoryManager } from './avatarCoreMemory';
|
|
2
1
|
export interface WasmModuleConfig {
|
|
3
2
|
baseUrl?: string;
|
|
4
3
|
[key: string]: unknown;
|
|
@@ -46,6 +45,8 @@ export declare class AvatarCoreAdapter {
|
|
|
46
45
|
private wasmModule;
|
|
47
46
|
private memoryManager;
|
|
48
47
|
private coreHandle;
|
|
48
|
+
private characterHandles;
|
|
49
|
+
private animationHandles;
|
|
49
50
|
private characterHandle;
|
|
50
51
|
private animationHandle;
|
|
51
52
|
private totalFrames;
|
|
@@ -58,131 +59,44 @@ export declare class AvatarCoreAdapter {
|
|
|
58
59
|
private flameInfo?;
|
|
59
60
|
private characterInfo?;
|
|
60
61
|
constructor(options?: AvatarCoreOptions);
|
|
61
|
-
/**
|
|
62
|
-
* 加载 WASM 模块并设置 API
|
|
63
|
-
* 每次都创建全新的 WASM 实例,确保 C++ 内存是干净的
|
|
64
|
-
*
|
|
65
|
-
* 注意:这里使用动态 import() 导入 WASM 模块。
|
|
66
|
-
* Vite 在构建时会自动为 WASM 文件和 JS glue 代码添加 hash(如 avatar_core_wasm-CxWuw7eS.wasm),
|
|
67
|
-
* 确保浏览器缓存与版本一致,不会有缓存问题。
|
|
68
|
-
*
|
|
69
|
-
* Hash 的作用机制:
|
|
70
|
-
* - WASM 文件内容变化 → hash 自动变化 → URL 变化 → 浏览器拉取新版本
|
|
71
|
-
* - WASM 文件内容不变 → hash 保持不变 → URL 不变 → 浏览器使用缓存
|
|
72
|
-
* - Emscripten 生成的 JS 内部会使用 hard-coded 的 hash 路径加载 .wasm 文件
|
|
73
|
-
*/
|
|
74
62
|
loadWASMModule(): Promise<void>;
|
|
75
|
-
/**
|
|
76
|
-
* 验证 WASM 模块功能
|
|
77
|
-
*/
|
|
78
63
|
private validateWASMModule;
|
|
79
|
-
/**
|
|
80
|
-
* 初始化内存视图
|
|
81
|
-
*/
|
|
82
64
|
private initializeMemoryViews;
|
|
83
|
-
/**
|
|
84
|
-
* 设置 C API 函数包装
|
|
85
|
-
*/
|
|
86
65
|
private setupCAPIFunctions;
|
|
87
|
-
|
|
88
|
-
* 读取当前动画帧的 FlameParams(用于过渡或调试)
|
|
89
|
-
*/
|
|
90
|
-
getCurrentFrameParams(frameIndex?: number): Promise<FlameParams>;
|
|
91
|
-
/**
|
|
92
|
-
* 初始化 Avatar Core 核心
|
|
93
|
-
*/
|
|
66
|
+
getCurrentFrameParams(frameIndex?: number, characterId?: string): Promise<FlameParams>;
|
|
94
67
|
private initializeAvatarCore;
|
|
95
|
-
/**
|
|
96
|
-
* 加载模板资源(从预加载的 ArrayBuffers)
|
|
97
|
-
*/
|
|
98
68
|
loadTemplateResourcesFromBuffers(templateResources: Record<string, ArrayBuffer>): Promise<boolean>;
|
|
99
|
-
|
|
100
|
-
* 加载角色数据(从预加载的 ArrayBuffers)
|
|
101
|
-
*/
|
|
102
|
-
loadCharacterFromBuffers(shapeBuffer: ArrayBuffer, pointCloudBuffer: ArrayBuffer): Promise<boolean>;
|
|
69
|
+
loadCharacterFromBuffers(shapeBuffer: ArrayBuffer, pointCloudBuffer: ArrayBuffer, characterId?: string): Promise<number>;
|
|
103
70
|
private loadAnimationFromData;
|
|
104
|
-
|
|
105
|
-
* Load animation from ArrayBuffer (for CDN-based dynamic loading)
|
|
106
|
-
*/
|
|
107
|
-
loadAnimationFromBuffer(animData: ArrayBuffer): Promise<number>;
|
|
71
|
+
loadAnimationFromBuffer(animData: ArrayBuffer, characterId?: string): Promise<number>;
|
|
108
72
|
switchAnimationFile(animationFile: string): Promise<number>;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
*/
|
|
112
|
-
getAnimationTotalFrames(): Promise<number>;
|
|
113
|
-
/**
|
|
114
|
-
* 从动画中获取指定帧的参数
|
|
115
|
-
*/
|
|
116
|
-
getAnimationFrameParams(frameIndex?: number): Promise<number>;
|
|
117
|
-
/**
|
|
118
|
-
* 设置眼部追踪配置(对齐 app 实现)
|
|
119
|
-
*/
|
|
73
|
+
getAnimationTotalFrames(animationHandle?: number): Promise<number>;
|
|
74
|
+
getAnimationFrameParams(frameIndex?: number, characterId?: string): Promise<number>;
|
|
120
75
|
setEyeTrackingConfig(config: {
|
|
121
76
|
enabled: boolean;
|
|
122
77
|
auto_eyelid_adjustment?: boolean;
|
|
123
78
|
eyelid_threshold?: number;
|
|
124
79
|
}): Promise<boolean>;
|
|
125
|
-
/**
|
|
126
|
-
* 设置眼部追踪目标(高级功能)
|
|
127
|
-
*/
|
|
128
80
|
setGazeTarget(x: number, y: number, z: number): Promise<boolean>;
|
|
129
|
-
/**
|
|
130
|
-
* 重置眼部追踪
|
|
131
|
-
*/
|
|
132
81
|
resetEyeTracking(): Promise<boolean>;
|
|
133
|
-
/**
|
|
134
|
-
* 查询 FLAME 模型信息
|
|
135
|
-
*/
|
|
136
82
|
private queryFlameInfo;
|
|
137
|
-
/**
|
|
138
|
-
* 查询角色信息
|
|
139
|
-
*/
|
|
140
83
|
private queryCharacterInfo;
|
|
141
|
-
/**
|
|
142
|
-
* 检查错误码并抛出异常
|
|
143
|
-
*/
|
|
144
84
|
private checkError;
|
|
145
|
-
/**
|
|
146
|
-
* 更新进度回调
|
|
147
|
-
*/
|
|
148
85
|
private updateProgress;
|
|
149
|
-
/**
|
|
150
|
-
* 获取性能指标
|
|
151
|
-
*/
|
|
152
86
|
getPerformanceMetrics(): PerformanceMetrics & {
|
|
153
|
-
memoryStats?: ReturnType<AvatarCoreMemoryManager['getMemoryStats']>;
|
|
154
87
|
flameInfo?: FlameInfo;
|
|
155
88
|
characterInfo?: CharacterInfo;
|
|
156
89
|
version?: string;
|
|
157
90
|
};
|
|
158
|
-
|
|
159
|
-
* 释放当前角色和动画资源(但保留 core)
|
|
160
|
-
*/
|
|
91
|
+
removeCharacter(characterHandle: number, characterId?: string): void;
|
|
161
92
|
releaseCurrentCharacter(): void;
|
|
162
|
-
/**
|
|
163
|
-
* 释放所有资源(包括 core)
|
|
164
|
-
*/
|
|
165
93
|
release(): void;
|
|
166
|
-
/**
|
|
167
|
-
* 兼容性接口:提供与 FlameComplete3DGSManager 相同的接口
|
|
168
|
-
*/
|
|
169
94
|
loadFlameModel(_modelData: any): Promise<boolean>;
|
|
170
95
|
load3DGSData(_original3DGSPoints: any, _binding: any, _flameFaces: any): Promise<boolean>;
|
|
171
|
-
/**
|
|
172
|
-
* 计算帧并返回 GPU 友好的 flat 格式(零拷贝,协方差预计算)
|
|
173
|
-
* 🚀 性能优化版本:
|
|
174
|
-
* - C++ 预计算协方差矩阵
|
|
175
|
-
* - 零拷贝直接访问 WASM 内存http://localhost:3000/us/
|
|
176
|
-
* - 直接输出 GPU 格式 [pos3, color4, cov6]
|
|
177
|
-
*/
|
|
178
96
|
computeCompleteFrameFlat(params?: {
|
|
179
97
|
frameIndex?: number;
|
|
180
|
-
}): Promise<Float32Array | null>;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
* 🔑 用于 Realtime: 接受自定义 FLAME 参数并计算 Splat
|
|
184
|
-
*/
|
|
185
|
-
computeFrameFlatFromParams(flameParams: FlameParams): Promise<Float32Array | null>;
|
|
98
|
+
}, characterHandle?: number): Promise<Float32Array | null>;
|
|
99
|
+
computeFrameFlatFromParams(flameParams: FlameParams, characterHandle?: number): Promise<Float32Array | null>;
|
|
100
|
+
getWASMMemoryMB(): number | null;
|
|
186
101
|
}
|
|
187
102
|
export {};
|
|
188
|
-
//# sourceMappingURL=avatarCoreAdapter.d.ts.map
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Avatar Core WASM 内存管理工具
|
|
3
|
-
*
|
|
4
|
-
* 提供高效的内存分配、数据传递和零拷贝访问功能
|
|
5
|
-
* 专门为 avatar_core_wasm 优化
|
|
6
|
-
*/
|
|
7
1
|
interface WASMModule {
|
|
8
2
|
_malloc: (size: number) => number;
|
|
9
3
|
_free: (ptr: number) => void;
|
|
@@ -47,22 +41,13 @@ export declare class AvatarCoreMemoryManager {
|
|
|
47
41
|
private allocatedPointers;
|
|
48
42
|
private structPointers;
|
|
49
43
|
constructor(wasmModule: WASMModule);
|
|
50
|
-
/**
|
|
51
|
-
* 分配 WASM 内存并复制数据 - 纯 API 方式
|
|
52
|
-
*/
|
|
53
44
|
allocateAndCopy(arrayBuffer: ArrayBuffer): MemoryAllocation;
|
|
54
|
-
/**
|
|
55
|
-
* 创建 AvatarTemplateConfig 结构体
|
|
56
|
-
*/
|
|
57
45
|
createTemplateConfig(resources: TemplateResources): number;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* 读取 AvatarFlameParams 结构体数据
|
|
64
|
-
* Used to extract current animation frame parameters from WASM memory
|
|
65
|
-
*/
|
|
46
|
+
createCharacterData(shapeBuffer: ArrayBuffer, plyBuffer: ArrayBuffer, characterId?: string): {
|
|
47
|
+
dataPtr: number;
|
|
48
|
+
shapePtr: number;
|
|
49
|
+
plyPtr: number;
|
|
50
|
+
};
|
|
66
51
|
readFlameParams(paramsPtr: number): {
|
|
67
52
|
shape_params: number[];
|
|
68
53
|
expr_params: number[];
|
|
@@ -74,9 +59,6 @@ export declare class AvatarCoreMemoryManager {
|
|
|
74
59
|
eyelid: number[];
|
|
75
60
|
has_eyelid: boolean;
|
|
76
61
|
};
|
|
77
|
-
/**
|
|
78
|
-
* 创建 AvatarFlameParams 结构体 - 新版 Emscripten 方式
|
|
79
|
-
*/
|
|
80
62
|
createFlameParams(params: {
|
|
81
63
|
shape_params?: number[];
|
|
82
64
|
expr_params?: number[];
|
|
@@ -88,25 +70,7 @@ export declare class AvatarCoreMemoryManager {
|
|
|
88
70
|
eyelid?: number[];
|
|
89
71
|
has_eyelid?: boolean;
|
|
90
72
|
}): number;
|
|
91
|
-
/**
|
|
92
|
-
* 读取 AvatarSplatPointFlatArray 结构体数据(预计算协方差)
|
|
93
|
-
*
|
|
94
|
-
* 结构体布局:
|
|
95
|
-
* - AvatarSplatPointFlat* points (0-3, 32位指针)
|
|
96
|
-
* - uint32_t point_count (4-7)
|
|
97
|
-
* - float compute_time_ms (8-11)
|
|
98
|
-
*
|
|
99
|
-
* 每个点布局 (52 bytes):
|
|
100
|
-
* - position[3] (12 bytes)
|
|
101
|
-
* - color[4] (16 bytes, RGBA)
|
|
102
|
-
* - covariance[6] (24 bytes, 预计算好的协方差矩阵上三角)
|
|
103
|
-
*
|
|
104
|
-
* ⚠️ 使用 getValue 逐个读取,避免动态内存的 HEAPF32 detachment 问题
|
|
105
|
-
*/
|
|
106
73
|
readSplatPointFlatArray(arrayPtr: number): Float32Array | null;
|
|
107
|
-
/**
|
|
108
|
-
* 读取AvatarMeshData结构体数据
|
|
109
|
-
*/
|
|
110
74
|
readMeshData(outputPtr: number): {
|
|
111
75
|
vertices: Float32Array;
|
|
112
76
|
vertexCount: number;
|
|
@@ -116,21 +80,9 @@ export declare class AvatarCoreMemoryManager {
|
|
|
116
80
|
landmarkCount: number;
|
|
117
81
|
computeTime: number;
|
|
118
82
|
};
|
|
119
|
-
/**
|
|
120
|
-
* 释放指定指针的内存
|
|
121
|
-
*/
|
|
122
83
|
free(ptr: number): void;
|
|
123
|
-
/**
|
|
124
|
-
* 释放结构体内存
|
|
125
|
-
*/
|
|
126
84
|
freeStruct(name: string): void;
|
|
127
|
-
/**
|
|
128
|
-
* 清理所有分配的内存
|
|
129
|
-
*/
|
|
130
85
|
cleanup(): void;
|
|
131
|
-
/**
|
|
132
|
-
* 获取内存使用统计
|
|
133
|
-
*/
|
|
134
86
|
getMemoryStats(): {
|
|
135
87
|
allocatedPointers: number;
|
|
136
88
|
structPointers: number;
|
|
@@ -138,4 +90,3 @@ export declare class AvatarCoreMemoryManager {
|
|
|
138
90
|
};
|
|
139
91
|
}
|
|
140
92
|
export {};
|
|
141
|
-
//# sourceMappingURL=avatarCoreMemory.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spatialwalk/avatarkit",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-beta.
|
|
4
|
+
"version": "1.0.0-beta.31",
|
|
5
5
|
"packageManager": "pnpm@10.18.2",
|
|
6
6
|
"description": "SPAvatar SDK - 3D Gaussian Splatting Avatar Rendering SDK",
|
|
7
7
|
"author": "SPAvatar Team",
|
|
@@ -29,13 +29,18 @@
|
|
|
29
29
|
"types": "./dist/index.d.ts",
|
|
30
30
|
"files": [
|
|
31
31
|
"README.md",
|
|
32
|
+
"CHANGELOG.md",
|
|
32
33
|
"dist"
|
|
33
34
|
],
|
|
34
35
|
"scripts": {
|
|
35
36
|
"build": "SDK_BUILD=true vite build --mode library",
|
|
36
37
|
"dev": "vite build --mode library --watch",
|
|
37
38
|
"clean": "rm -rf dist",
|
|
38
|
-
"typecheck": "tsc --noEmit"
|
|
39
|
+
"typecheck": "tsc --noEmit",
|
|
40
|
+
"test": "cd tests && pnpm test",
|
|
41
|
+
"test:watch": "cd tests && pnpm run test:watch",
|
|
42
|
+
"test:e2e": "cd tests && pnpm run test:e2e",
|
|
43
|
+
"test:perf": "cd tests && pnpm run test:perf"
|
|
39
44
|
},
|
|
40
45
|
"peerDependencies": {
|
|
41
46
|
"@webgpu/types": "*"
|
|
@@ -43,11 +48,12 @@
|
|
|
43
48
|
"dependencies": {
|
|
44
49
|
"@bufbuild/protobuf": "^2.10.0",
|
|
45
50
|
"@guiiai/logg": "^1.2.4",
|
|
46
|
-
"nanoid": "^5.1.6"
|
|
47
|
-
"posthog-js": "^1.275.3"
|
|
51
|
+
"nanoid": "^5.1.6"
|
|
48
52
|
},
|
|
49
53
|
"devDependencies": {
|
|
54
|
+
"@types/node": "^20.11.30",
|
|
50
55
|
"@webgpu/types": "^0.1.65",
|
|
56
|
+
"tsx": "^4.20.6",
|
|
51
57
|
"typescript": "^5.0.0",
|
|
52
58
|
"vite": "^5.0.0",
|
|
53
59
|
"vite-plugin-dts": "^4.5.4"
|
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
var c = Object.defineProperty;
|
|
2
|
-
var g = (h, t, e) => t in h ? c(h, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : h[t] = e;
|
|
3
|
-
var s = (h, t, e) => g(h, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
-
import { l } from "./index-NmYXWJnL.js";
|
|
5
|
-
class k {
|
|
6
|
-
constructor(t) {
|
|
7
|
-
// AudioContext is managed internally
|
|
8
|
-
s(this, "audioContext", null);
|
|
9
|
-
s(this, "sampleRate");
|
|
10
|
-
s(this, "channelCount");
|
|
11
|
-
s(this, "debug");
|
|
12
|
-
// Session-level state
|
|
13
|
-
s(this, "sessionId");
|
|
14
|
-
s(this, "sessionStartTime", 0);
|
|
15
|
-
// AudioContext time when session started
|
|
16
|
-
s(this, "pausedTimeOffset", 0);
|
|
17
|
-
// Accumulated paused time
|
|
18
|
-
s(this, "pausedAt", 0);
|
|
19
|
-
// Time when paused
|
|
20
|
-
s(this, "scheduledTime", 0);
|
|
21
|
-
// Next chunk schedule time in AudioContext time
|
|
22
|
-
// Playback state
|
|
23
|
-
s(this, "isPlaying", !1);
|
|
24
|
-
s(this, "isPaused", !1);
|
|
25
|
-
// Audio buffer queue
|
|
26
|
-
s(this, "audioChunks", []);
|
|
27
|
-
s(this, "scheduledChunks", 0);
|
|
28
|
-
// Number of chunks already scheduled
|
|
29
|
-
s(this, "activeSources", []);
|
|
30
|
-
// Event callbacks
|
|
31
|
-
s(this, "onEndedCallback");
|
|
32
|
-
this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, this.sampleRate = (t == null ? void 0 : t.sampleRate) ?? 24e3, this.channelCount = (t == null ? void 0 : t.channelCount) ?? 1, this.debug = (t == null ? void 0 : t.debug) ?? !1;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Initialize audio context (create and ensure it's ready)
|
|
36
|
-
*/
|
|
37
|
-
async initialize() {
|
|
38
|
-
this.audioContext || (this.audioContext = new AudioContext({
|
|
39
|
-
sampleRate: this.sampleRate
|
|
40
|
-
}), this.audioContext.state === "suspended" && await this.audioContext.resume(), this.log("AudioContext initialized", {
|
|
41
|
-
sessionId: this.sessionId,
|
|
42
|
-
sampleRate: this.audioContext.sampleRate,
|
|
43
|
-
state: this.audioContext.state
|
|
44
|
-
}));
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Add audio chunk (16-bit PCM)
|
|
48
|
-
*/
|
|
49
|
-
addChunk(t, e = !1) {
|
|
50
|
-
if (!this.audioContext) {
|
|
51
|
-
l.error("AudioContext not initialized");
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
this.audioChunks.push({ data: t, isLast: e }), this.log(`Added chunk ${this.audioChunks.length}`, {
|
|
55
|
-
size: t.length,
|
|
56
|
-
totalChunks: this.audioChunks.length,
|
|
57
|
-
isLast: e,
|
|
58
|
-
isPlaying: this.isPlaying,
|
|
59
|
-
scheduledChunks: this.scheduledChunks
|
|
60
|
-
}), !this.isPlaying && this.audioChunks.length > 0 ? (this.log("[StreamingAudioPlayer] Auto-starting playback from addChunk"), this.startPlayback()) : this.isPlaying ? (this.log("[StreamingAudioPlayer] Already playing, scheduling next chunk"), this.scheduleNextChunk()) : this.log("[StreamingAudioPlayer] Not playing and no chunks, waiting for more chunks");
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Start new session (stop current and start fresh)
|
|
64
|
-
*/
|
|
65
|
-
async startNewSession(t) {
|
|
66
|
-
this.stop(), this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, this.audioChunks = [], this.scheduledChunks = 0, this.pausedTimeOffset = 0, this.pausedAt = 0, this.log("Starting new session", {
|
|
67
|
-
chunks: t.length
|
|
68
|
-
});
|
|
69
|
-
for (const e of t)
|
|
70
|
-
this.addChunk(e.data, e.isLast);
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Start playback
|
|
74
|
-
*/
|
|
75
|
-
startPlayback() {
|
|
76
|
-
if (!this.audioContext) {
|
|
77
|
-
this.log("[StreamingAudioPlayer] Cannot start playback: AudioContext not initialized");
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
if (this.isPlaying) {
|
|
81
|
-
this.log("[StreamingAudioPlayer] Cannot start playback: Already playing");
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
this.isPlaying = !0, this.sessionStartTime = this.audioContext.currentTime, this.scheduledTime = this.sessionStartTime, this.log("[StreamingAudioPlayer] Starting playback", {
|
|
85
|
-
sessionStartTime: this.sessionStartTime,
|
|
86
|
-
bufferedChunks: this.audioChunks.length,
|
|
87
|
-
scheduledChunks: this.scheduledChunks,
|
|
88
|
-
activeSources: this.activeSources.length
|
|
89
|
-
}), this.scheduleAllChunks();
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Schedule all pending chunks
|
|
93
|
-
*/
|
|
94
|
-
scheduleAllChunks() {
|
|
95
|
-
for (; this.scheduledChunks < this.audioChunks.length; )
|
|
96
|
-
this.scheduleNextChunk();
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Schedule next audio chunk
|
|
100
|
-
*/
|
|
101
|
-
scheduleNextChunk() {
|
|
102
|
-
if (!this.audioContext) {
|
|
103
|
-
this.log("[StreamingAudioPlayer] Cannot schedule chunk: AudioContext not initialized");
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
if (!this.isPlaying) {
|
|
107
|
-
this.log("[StreamingAudioPlayer] Cannot schedule chunk: Not playing");
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
const t = this.scheduledChunks;
|
|
111
|
-
if (t >= this.audioChunks.length) {
|
|
112
|
-
this.log(`[StreamingAudioPlayer] No more chunks to schedule (chunkIndex: ${t}, totalChunks: ${this.audioChunks.length})`);
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
const e = this.audioChunks[t];
|
|
116
|
-
if (e.data.length === 0 && !e.isLast) {
|
|
117
|
-
this.scheduledChunks++;
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
const r = e.data, d = e.isLast, n = this.pcmToAudioBuffer(r);
|
|
121
|
-
if (!n) {
|
|
122
|
-
l.error("Failed to create AudioBuffer from PCM data");
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
try {
|
|
126
|
-
const i = this.audioContext.createBufferSource();
|
|
127
|
-
i.buffer = n, i.connect(this.audioContext.destination), i.start(this.scheduledTime), this.activeSources.push(i), i.onended = () => {
|
|
128
|
-
const u = this.activeSources.indexOf(i);
|
|
129
|
-
u >= 0 && this.activeSources.splice(u, 1), d && this.activeSources.length === 0 && (this.log("Last audio chunk ended, marking playback as ended"), this.markEnded());
|
|
130
|
-
}, this.scheduledTime += n.duration, this.scheduledChunks++, this.log(`[StreamingAudioPlayer] Scheduled chunk ${t + 1}/${this.audioChunks.length}`, {
|
|
131
|
-
startTime: this.scheduledTime - n.duration,
|
|
132
|
-
duration: n.duration,
|
|
133
|
-
nextScheduleTime: this.scheduledTime,
|
|
134
|
-
isLast: d,
|
|
135
|
-
activeSources: this.activeSources.length
|
|
136
|
-
});
|
|
137
|
-
} catch (i) {
|
|
138
|
-
l.errorWithError("Failed to schedule audio chunk:", i);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Convert PCM data to AudioBuffer
|
|
143
|
-
* Input: 16-bit PCM (int16), Output: AudioBuffer (float32 [-1, 1])
|
|
144
|
-
*/
|
|
145
|
-
pcmToAudioBuffer(t) {
|
|
146
|
-
if (!this.audioContext)
|
|
147
|
-
return null;
|
|
148
|
-
if (t.length === 0) {
|
|
149
|
-
const u = Math.floor(this.sampleRate * 0.01), a = this.audioContext.createBuffer(
|
|
150
|
-
this.channelCount,
|
|
151
|
-
u,
|
|
152
|
-
this.sampleRate
|
|
153
|
-
);
|
|
154
|
-
for (let o = 0; o < this.channelCount; o++)
|
|
155
|
-
a.getChannelData(o).fill(0);
|
|
156
|
-
return a;
|
|
157
|
-
}
|
|
158
|
-
const e = new Uint8Array(t), r = new Int16Array(e.buffer, 0, e.length / 2), d = r.length / this.channelCount, n = this.audioContext.createBuffer(
|
|
159
|
-
this.channelCount,
|
|
160
|
-
d,
|
|
161
|
-
this.sampleRate
|
|
162
|
-
);
|
|
163
|
-
for (let i = 0; i < this.channelCount; i++) {
|
|
164
|
-
const u = n.getChannelData(i);
|
|
165
|
-
for (let a = 0; a < d; a++) {
|
|
166
|
-
const o = a * this.channelCount + i;
|
|
167
|
-
u[a] = r[o] / 32768;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return n;
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Get current playback time (seconds)
|
|
174
|
-
*/
|
|
175
|
-
getCurrentTime() {
|
|
176
|
-
if (!this.audioContext || !this.isPlaying)
|
|
177
|
-
return 0;
|
|
178
|
-
if (this.isPaused)
|
|
179
|
-
return this.pausedAt;
|
|
180
|
-
const e = this.audioContext.currentTime - this.sessionStartTime - this.pausedTimeOffset;
|
|
181
|
-
return Math.max(0, e);
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Pause playback
|
|
185
|
-
*/
|
|
186
|
-
pause() {
|
|
187
|
-
!this.isPlaying || this.isPaused || (this.isPaused = !0, this.pausedAt = this.getCurrentTime(), this.log("Playback paused", {
|
|
188
|
-
pausedAt: this.pausedAt
|
|
189
|
-
}));
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Resume playback
|
|
193
|
-
*/
|
|
194
|
-
async resume() {
|
|
195
|
-
if (!this.isPaused || !this.audioContext)
|
|
196
|
-
return;
|
|
197
|
-
const t = this.audioContext.currentTime - (this.sessionStartTime + this.pausedAt);
|
|
198
|
-
this.pausedTimeOffset += t, this.isPaused = !1, this.log("Playback resumed", {
|
|
199
|
-
pauseDuration: t,
|
|
200
|
-
totalPausedOffset: this.pausedTimeOffset
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Stop playback
|
|
205
|
-
*/
|
|
206
|
-
stop() {
|
|
207
|
-
if (this.audioContext) {
|
|
208
|
-
this.isPlaying = !1, this.isPaused = !1, this.sessionStartTime = 0, this.scheduledTime = 0;
|
|
209
|
-
for (const t of this.activeSources) {
|
|
210
|
-
t.onended = null;
|
|
211
|
-
try {
|
|
212
|
-
t.stop(0);
|
|
213
|
-
} catch {
|
|
214
|
-
}
|
|
215
|
-
try {
|
|
216
|
-
t.disconnect();
|
|
217
|
-
} catch {
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
this.activeSources = [], this.audioChunks = [], this.scheduledChunks = 0, this.log("[StreamingAudioPlayer] Playback stopped, state reset");
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Mark playback as ended
|
|
225
|
-
*/
|
|
226
|
-
markEnded() {
|
|
227
|
-
var t;
|
|
228
|
-
this.log("Playback ended"), this.isPlaying = !1, (t = this.onEndedCallback) == null || t.call(this);
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Set ended callback
|
|
232
|
-
*/
|
|
233
|
-
onEnded(t) {
|
|
234
|
-
this.onEndedCallback = t;
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Check if playing
|
|
238
|
-
*/
|
|
239
|
-
isPlayingNow() {
|
|
240
|
-
return this.isPlaying && !this.isPaused;
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Get total duration of buffered audio
|
|
244
|
-
*/
|
|
245
|
-
getBufferedDuration() {
|
|
246
|
-
if (!this.audioContext)
|
|
247
|
-
return 0;
|
|
248
|
-
let t = 0;
|
|
249
|
-
for (const e of this.audioChunks)
|
|
250
|
-
t += e.data.length / 2 / this.channelCount;
|
|
251
|
-
return t / this.sampleRate;
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* Get remaining duration (buffered - played) in seconds
|
|
255
|
-
*/
|
|
256
|
-
getRemainingDuration() {
|
|
257
|
-
const t = this.getBufferedDuration(), e = this.getCurrentTime();
|
|
258
|
-
return Math.max(0, t - e);
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Dispose and cleanup
|
|
262
|
-
*/
|
|
263
|
-
dispose() {
|
|
264
|
-
this.stop(), this.audioContext && (this.audioContext.close(), this.audioContext = null), this.audioChunks = [], this.scheduledChunks = 0, this.sessionStartTime = 0, this.pausedTimeOffset = 0, this.pausedAt = 0, this.scheduledTime = 0, this.onEndedCallback = void 0, this.log("StreamingAudioPlayer disposed");
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Flush buffered audio
|
|
268
|
-
* - hard: stops all playing sources and clears all chunks
|
|
269
|
-
* - soft (default): clears UNSCHEDULED chunks only
|
|
270
|
-
*/
|
|
271
|
-
flush(t) {
|
|
272
|
-
if ((t == null ? void 0 : t.hard) === !0) {
|
|
273
|
-
this.stop(), this.audioChunks = [], this.scheduledChunks = 0, this.sessionStartTime = 0, this.pausedAt = 0, this.scheduledTime = 0, this.log("Flushed (hard)");
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
this.scheduledChunks < this.audioChunks.length && this.audioChunks.splice(this.scheduledChunks), this.log("Flushed (soft)", { remainingScheduled: this.scheduledChunks });
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* Debug logging
|
|
280
|
-
*/
|
|
281
|
-
log(t, e) {
|
|
282
|
-
this.debug && l.log(`[StreamingAudioPlayer] ${t}`, e || "");
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
export {
|
|
286
|
-
k as StreamingAudioPlayer
|
|
287
|
-
};
|
|
288
|
-
//# sourceMappingURL=StreamingAudioPlayer-BeLlDiwE.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"StreamingAudioPlayer-BeLlDiwE.js","sources":["../audio/StreamingAudioPlayer.ts"],"sourcesContent":["/**\n * Streaming Audio Player\n * Implements real-time audio playback using Web Audio API\n * Supports dynamic PCM chunk addition without Workers\n */\n\nimport { logger } from '../utils/logger'\n\nexport interface StreamingAudioPlayerOptions {\n sampleRate?: number // PCM sample rate (default: 24000, backend returns 24kHz)\n channelCount?: number // Number of channels (default: 1)\n debug?: boolean\n}\n\nexport class StreamingAudioPlayer {\n // AudioContext is managed internally\n private audioContext: AudioContext | null = null\n private sampleRate: number\n private channelCount: number\n private debug: boolean\n\n // Session-level state\n private sessionId: string\n private sessionStartTime = 0 // AudioContext time when session started\n private pausedTimeOffset = 0 // Accumulated paused time\n private pausedAt = 0 // Time when paused\n private scheduledTime = 0 // Next chunk schedule time in AudioContext time\n\n // Playback state\n private isPlaying = false\n private isPaused = false\n\n // Audio buffer queue\n private audioChunks: Array<{ data: Uint8Array, isLast: boolean }> = []\n private scheduledChunks = 0 // Number of chunks already scheduled\n private activeSources: AudioBufferSourceNode[] = []\n\n // Event callbacks\n private onEndedCallback?: () => void\n\n constructor(options?: StreamingAudioPlayerOptions) {\n this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`\n this.sampleRate = options?.sampleRate ?? 24000 // Backend returns 24kHz by default\n this.channelCount = options?.channelCount ?? 1\n this.debug = options?.debug ?? false\n }\n\n /**\n * Initialize audio context (create and ensure it's ready)\n */\n async initialize(): Promise<void> {\n if (this.audioContext) {\n return\n }\n\n // Create AudioContext\n this.audioContext = new AudioContext({\n sampleRate: this.sampleRate,\n })\n\n // Resume context (required for some browsers)\n if (this.audioContext.state === 'suspended') {\n await this.audioContext.resume()\n }\n\n this.log('AudioContext initialized', {\n sessionId: this.sessionId,\n sampleRate: this.audioContext.sampleRate,\n state: this.audioContext.state,\n })\n }\n\n /**\n * Add audio chunk (16-bit PCM)\n */\n addChunk(pcmData: Uint8Array, isLast: boolean = false): void {\n if (!this.audioContext) {\n logger.error('AudioContext not initialized')\n return\n }\n\n // Store chunk with metadata\n this.audioChunks.push({ data: pcmData, isLast })\n\n // Track buffer underrun warning\n if (this.isPlaying && this.audioChunks.length === this.scheduledChunks) {\n // Buffer underrun detected - chunks consumed faster than added\n }\n\n this.log(`Added chunk ${this.audioChunks.length}`, {\n size: pcmData.length,\n totalChunks: this.audioChunks.length,\n isLast,\n isPlaying: this.isPlaying,\n scheduledChunks: this.scheduledChunks,\n })\n\n // Auto-start if we have any audio chunks\n if (!this.isPlaying && this.audioChunks.length > 0) {\n this.log('[StreamingAudioPlayer] Auto-starting playback from addChunk')\n this.startPlayback()\n }\n // Schedule next chunk if already playing\n else if (this.isPlaying) {\n this.log('[StreamingAudioPlayer] Already playing, scheduling next chunk')\n this.scheduleNextChunk()\n } else {\n this.log('[StreamingAudioPlayer] Not playing and no chunks, waiting for more chunks')\n }\n }\n\n /**\n * Start new session (stop current and start fresh)\n */\n async startNewSession(audioChunks: Array<{ data: Uint8Array, isLast: boolean }>): Promise<void> {\n // Stop current session if playing\n this.stop()\n\n // Generate new session ID to prevent data mixing\n this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`\n\n // Reset session state\n this.audioChunks = []\n this.scheduledChunks = 0\n this.pausedTimeOffset = 0\n this.pausedAt = 0\n // Don't set sessionStartTime or scheduledTime here - let startPlayback() set them\n this.log('Starting new session', {\n chunks: audioChunks.length,\n })\n\n // Add audio chunks with their metadata\n for (const chunk of audioChunks) {\n this.addChunk(chunk.data, chunk.isLast)\n }\n }\n\n /**\n * Start playback\n */\n private startPlayback(): void {\n if (!this.audioContext) {\n this.log('[StreamingAudioPlayer] Cannot start playback: AudioContext not initialized')\n return\n }\n if (this.isPlaying) {\n this.log('[StreamingAudioPlayer] Cannot start playback: Already playing')\n return\n }\n\n this.isPlaying = true\n this.sessionStartTime = this.audioContext.currentTime\n this.scheduledTime = this.sessionStartTime\n\n this.log('[StreamingAudioPlayer] Starting playback', {\n sessionStartTime: this.sessionStartTime,\n bufferedChunks: this.audioChunks.length,\n scheduledChunks: this.scheduledChunks,\n activeSources: this.activeSources.length,\n })\n\n // Schedule all available chunks\n this.scheduleAllChunks()\n }\n\n /**\n * Schedule all pending chunks\n */\n private scheduleAllChunks(): void {\n while (this.scheduledChunks < this.audioChunks.length) {\n this.scheduleNextChunk()\n }\n }\n\n /**\n * Schedule next audio chunk\n */\n private scheduleNextChunk(): void {\n if (!this.audioContext) {\n this.log('[StreamingAudioPlayer] Cannot schedule chunk: AudioContext not initialized')\n return\n }\n if (!this.isPlaying) {\n this.log('[StreamingAudioPlayer] Cannot schedule chunk: Not playing')\n return\n }\n\n const chunkIndex = this.scheduledChunks\n if (chunkIndex >= this.audioChunks.length) {\n this.log(`[StreamingAudioPlayer] No more chunks to schedule (chunkIndex: ${chunkIndex}, totalChunks: ${this.audioChunks.length})`)\n return\n }\n\n const chunk = this.audioChunks[chunkIndex]\n\n // 当音频块为空且不是最后一个块时,跳过调度\n if (chunk.data.length === 0 && !chunk.isLast) {\n this.scheduledChunks++\n return\n }\n\n const pcmData = chunk.data\n const isLast = chunk.isLast\n const audioBuffer = this.pcmToAudioBuffer(pcmData)\n\n if (!audioBuffer) {\n const errorMessage = 'Failed to create AudioBuffer from PCM data'\n logger.error(errorMessage)\n return\n }\n\n try {\n // Create and configure source node\n const source = this.audioContext.createBufferSource()\n source.buffer = audioBuffer\n source.connect(this.audioContext.destination)\n\n // Schedule playback\n source.start(this.scheduledTime)\n\n // Track active source for hard-cancel\n this.activeSources.push(source)\n source.onended = () => {\n // Remove from active list when it ends\n const idx = this.activeSources.indexOf(source)\n if (idx >= 0)\n this.activeSources.splice(idx, 1)\n\n // Check if this was the last chunk and all sources have ended\n if (isLast && this.activeSources.length === 0) {\n this.log('Last audio chunk ended, marking playback as ended')\n this.markEnded()\n }\n }\n\n // Update scheduled time for next chunk\n this.scheduledTime += audioBuffer.duration\n\n this.scheduledChunks++\n\n this.log(`[StreamingAudioPlayer] Scheduled chunk ${chunkIndex + 1}/${this.audioChunks.length}`, {\n startTime: this.scheduledTime - audioBuffer.duration,\n duration: audioBuffer.duration,\n nextScheduleTime: this.scheduledTime,\n isLast,\n activeSources: this.activeSources.length,\n })\n }\n catch (err) {\n logger.errorWithError('Failed to schedule audio chunk:', err)\n }\n }\n\n /**\n * Convert PCM data to AudioBuffer\n * Input: 16-bit PCM (int16), Output: AudioBuffer (float32 [-1, 1])\n */\n private pcmToAudioBuffer(pcmData: Uint8Array): AudioBuffer | null {\n if (!this.audioContext) {\n return null\n }\n\n // Handle empty PCM data (e.g., when isLast is true)\n if (pcmData.length === 0) {\n // For empty chunks (typically the last chunk), create minimal silence\n // Use a very short duration to avoid playback stuttering\n const silenceDuration = 0.01 // 1ms - minimal silence to maintain timing\n const numSamples = Math.floor(this.sampleRate * silenceDuration)\n\n const audioBuffer = this.audioContext.createBuffer(\n this.channelCount,\n numSamples,\n this.sampleRate,\n )\n\n // Fill with silence (all zeros)\n for (let channel = 0; channel < this.channelCount; channel++) {\n const channelData = audioBuffer.getChannelData(channel)\n channelData.fill(0) // Fill with silence\n }\n\n return audioBuffer\n }\n\n // Create aligned copy to avoid byte offset issues\n // Int16Array requires byteOffset to be a multiple of 2\n const alignedData = new Uint8Array(pcmData)\n const int16Array = new Int16Array(alignedData.buffer, 0, alignedData.length / 2)\n\n // Calculate number of samples\n const numSamples = int16Array.length / this.channelCount\n\n // Create AudioBuffer\n const audioBuffer = this.audioContext.createBuffer(\n this.channelCount,\n numSamples,\n this.sampleRate,\n )\n\n // Convert int16 to float32 [-1, 1]\n for (let channel = 0; channel < this.channelCount; channel++) {\n const channelData = audioBuffer.getChannelData(channel)\n\n for (let i = 0; i < numSamples; i++) {\n const sampleIndex = i * this.channelCount + channel\n // Normalize int16 (-32768 to 32767) to float32 (-1 to 1)\n channelData[i] = int16Array[sampleIndex] / 32768.0\n }\n }\n\n return audioBuffer\n }\n\n /**\n * Get current playback time (seconds)\n */\n getCurrentTime(): number {\n if (!this.audioContext || !this.isPlaying) {\n return 0\n }\n\n if (this.isPaused) {\n return this.pausedAt\n }\n\n // Calculate elapsed time using session start time and paused offset\n const currentAudioTime = this.audioContext.currentTime\n const elapsed = currentAudioTime - this.sessionStartTime - this.pausedTimeOffset\n\n return Math.max(0, elapsed)\n }\n\n /**\n * Pause playback\n */\n pause(): void {\n if (!this.isPlaying || this.isPaused) {\n return\n }\n\n this.isPaused = true\n this.pausedAt = this.getCurrentTime()\n\n // Don't suspend AudioContext to maintain time continuity\n // Just mark as paused and stop scheduling new chunks\n this.log('Playback paused', {\n pausedAt: this.pausedAt,\n })\n }\n\n /**\n * Resume playback\n */\n async resume(): Promise<void> {\n if (!this.isPaused || !this.audioContext) {\n return\n }\n\n // Calculate paused duration and add to offset\n const pauseDuration = this.audioContext.currentTime - (this.sessionStartTime + this.pausedAt)\n this.pausedTimeOffset += pauseDuration\n\n this.isPaused = false\n\n this.log('Playback resumed', {\n pauseDuration,\n totalPausedOffset: this.pausedTimeOffset,\n })\n }\n\n /**\n * Stop playback\n */\n stop(): void {\n if (!this.audioContext) {\n return\n }\n\n this.isPlaying = false\n this.isPaused = false\n this.sessionStartTime = 0 // Reset session start time\n this.scheduledTime = 0 // Reset scheduled time for next session\n\n // Hard stop all scheduled sources immediately\n for (const source of this.activeSources) {\n source.onended = null\n try {\n source.stop(0)\n }\n catch {}\n try {\n source.disconnect()\n }\n catch {}\n }\n this.activeSources = []\n\n // 清理音频块和调度状态,确保下次播放时状态干净\n this.audioChunks = []\n this.scheduledChunks = 0\n\n this.log('[StreamingAudioPlayer] Playback stopped, state reset')\n\n // Note: Individual source nodes will stop automatically\n // We just reset our state\n }\n\n /**\n * Mark playback as ended\n */\n markEnded(): void {\n this.log('Playback ended')\n this.isPlaying = false\n this.onEndedCallback?.()\n }\n\n /**\n * Set ended callback\n */\n onEnded(callback: () => void): void {\n this.onEndedCallback = callback\n }\n\n /**\n * Check if playing\n */\n isPlayingNow(): boolean {\n return this.isPlaying && !this.isPaused\n }\n\n /**\n * Get total duration of buffered audio\n */\n getBufferedDuration(): number {\n if (!this.audioContext) {\n return 0\n }\n\n let totalSamples = 0\n for (const chunk of this.audioChunks) {\n totalSamples += chunk.data.length / 2 / this.channelCount // 16-bit = 2 bytes per sample\n }\n\n return totalSamples / this.sampleRate\n }\n\n /**\n * Get remaining duration (buffered - played) in seconds\n */\n getRemainingDuration(): number {\n const total = this.getBufferedDuration()\n const played = this.getCurrentTime()\n return Math.max(0, total - played)\n }\n\n\n /**\n * Dispose and cleanup\n */\n dispose(): void {\n this.stop()\n\n // Close AudioContext\n if (this.audioContext) {\n this.audioContext.close()\n this.audioContext = null\n }\n\n // Clear session state\n this.audioChunks = []\n this.scheduledChunks = 0\n this.sessionStartTime = 0\n this.pausedTimeOffset = 0\n this.pausedAt = 0\n this.scheduledTime = 0\n this.onEndedCallback = undefined\n\n this.log('StreamingAudioPlayer disposed')\n }\n\n /**\n * Flush buffered audio\n * - hard: stops all playing sources and clears all chunks\n * - soft (default): clears UNSCHEDULED chunks only\n */\n flush(options?: { hard?: boolean }): void {\n const hard = options?.hard === true\n if (hard) {\n this.stop()\n this.audioChunks = []\n this.scheduledChunks = 0\n this.sessionStartTime = 0\n this.pausedAt = 0\n this.scheduledTime = 0\n this.log('Flushed (hard)')\n return\n }\n\n // Soft flush: drop unscheduled region\n if (this.scheduledChunks < this.audioChunks.length) {\n this.audioChunks.splice(this.scheduledChunks)\n }\n this.log('Flushed (soft)', { remainingScheduled: this.scheduledChunks })\n }\n\n /**\n * Debug logging\n */\n private log(message: string, data?: unknown): void {\n if (this.debug) {\n logger.log(`[StreamingAudioPlayer] ${message}`, data || '')\n }\n }\n}\n"],"names":["StreamingAudioPlayer","options","__publicField","pcmData","isLast","logger","audioChunks","chunk","chunkIndex","audioBuffer","source","idx","err","numSamples","channel","alignedData","int16Array","channelData","i","sampleIndex","elapsed","pauseDuration","_a","callback","totalSamples","total","played","message","data"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AnimationWebSocketClient.d.ts","sourceRoot":"","sources":["../../animation/AnimationWebSocketClient.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEnD,MAAM,WAAW,+BAA+B;IAC9C,KAAK,EAAE,MAAM,CAAA;IACb,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,qBAAa,wBAAyB,SAAQ,YAAY;IACxD,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,iBAAiB,CAAQ;IACjC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAC,CAAQ;IAEzB,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,iBAAiB,CAAY;IACrC,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,sBAAsB,CAAiB;IAC/C,OAAO,CAAC,cAAc,CAAsB;gBAEhC,OAAO,EAAE,+BAA+B;IAQpD;;OAEG;IACG,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BjD;;OAEG;IACH,UAAU,IAAI,IAAI;IAgBlB;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO;IA+B3E;;;OAGG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,qBAAqB,IAAI,MAAM;IAM/B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,gBAAgB;IAoDxB,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,iBAAiB;CAmB1B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"eventEmitter.d.ts","sourceRoot":"","sources":["../../../animation/utils/eventEmitter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,KAAK,YAAY,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;AAE5C,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA4C;IAE1D,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAO9C,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAW/C,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAOzC,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;CAQzC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"flameConverter.d.ts","sourceRoot":"","sources":["../../../animation/utils/flameConverter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gDAAgD,CAAA;AAE3E,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,KAAK,GAAG,WAAW,CAY5E;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,WAAW,GAAG,KAAK,CAU5E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,KAAK,CAU/C"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AnimationPlayer.d.ts","sourceRoot":"","sources":["../../audio/AnimationPlayer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAKlE,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,eAAe,CAAoC;IAC3D,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,eAAe,CAAC,CAAY;IACpC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAQ;IACpC,OAAO,CAAC,YAAY,CAAQ;IAE5B;;;OAGG;WACU,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IA2BhD;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBvE;;;OAGG;IACG,mBAAmB,CAAC,eAAe,EAAE,oBAAoB,EAAE,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAYrG;;OAEG;IACH,gBAAgB,IAAI,OAAO;IAI3B;;;OAGG;IACG,kCAAkC,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBzD;;;OAGG;IACG,sBAAsB,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBjE,OAAO,CAAC,mBAAmB;IAerB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAc3B,IAAI,IAAI,IAAI;IAcZ,SAAS,IAAI,OAAO;IAOpB,oBAAoB,IAAI,MAAM;IAK9B;;OAEG;IACH,cAAc,IAAI,MAAM;IAOxB;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,GAAE,OAAe,GAAG,IAAI;IAQ/D,OAAO,IAAI,IAAI;CAehB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"StreamingAudioPlayer.d.ts","sourceRoot":"","sources":["../../audio/StreamingAudioPlayer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,WAAW,2BAA2B;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,qBAAa,oBAAoB;IAE/B,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,KAAK,CAAS;IAGtB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,aAAa,CAAI;IAGzB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAAQ;IAGxB,OAAO,CAAC,WAAW,CAAmD;IACtE,OAAO,CAAC,eAAe,CAAI;IAC3B,OAAO,CAAC,aAAa,CAA8B;IAGnD,OAAO,CAAC,eAAe,CAAC,CAAY;gBAExB,OAAO,CAAC,EAAE,2BAA2B;IAOjD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBjC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,GAAE,OAAe,GAAG,IAAI;IAoC5D;;OAEG;IACG,eAAe,CAAC,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB/F;;OAEG;IACH,OAAO,CAAC,aAAa;IAyBrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA4EzB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAwDxB;;OAEG;IACH,cAAc,IAAI,MAAM;IAgBxB;;OAEG;IACH,KAAK,IAAI,IAAI;IAeb;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB7B;;OAEG;IACH,IAAI,IAAI,IAAI;IAkCZ;;OAEG;IACH,SAAS,IAAI,IAAI;IAMjB;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAInC;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACH,mBAAmB,IAAI,MAAM;IAa7B;;OAEG;IACH,oBAAoB,IAAI,MAAM;IAO9B;;OAEG;IACH,OAAO,IAAI,IAAI;IAqBf;;;;OAIG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAoBzC;;OAEG;IACH,OAAO,CAAC,GAAG;CAKZ"}
|