@spatialwalk/avatarkit 1.0.0-beta.1 → 1.0.0-beta.100
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 +938 -0
- package/README.md +821 -208
- package/dist/StreamingAudioPlayer-CY6WeP2p.js +643 -0
- package/dist/avatar_core_wasm-6656456a.wasm +0 -0
- package/dist/avatar_core_wasm-Dci9E9jF.js +2696 -0
- package/dist/core/Avatar.d.ts +4 -14
- package/dist/core/AvatarController.d.ts +108 -93
- package/dist/core/AvatarManager.d.ts +32 -12
- package/dist/core/AvatarSDK.d.ts +58 -0
- package/dist/core/AvatarView.d.ts +132 -123
- package/dist/index-DADGbRoo.js +18392 -0
- package/dist/index.d.ts +2 -5
- package/dist/index.js +17 -17
- package/dist/next.d.ts +2 -0
- package/dist/performance/FrameRateMonitor.d.ts +85 -0
- package/dist/types/character-settings.d.ts +7 -1
- package/dist/types/character.d.ts +42 -16
- package/dist/types/index.d.ts +170 -32
- package/dist/vite.d.ts +19 -0
- package/next.d.ts +3 -0
- package/next.js +187 -0
- package/package.json +42 -15
- package/vite.d.ts +20 -0
- package/vite.js +126 -0
- package/dist/StreamingAudioPlayer-C2TfYsO8.js +0 -293
- package/dist/StreamingAudioPlayer-C2TfYsO8.js.map +0 -1
- package/dist/animation/AnimationWebSocketClient.d.ts +0 -50
- package/dist/animation/AnimationWebSocketClient.d.ts.map +0 -1
- package/dist/animation/utils/eventEmitter.d.ts +0 -13
- package/dist/animation/utils/eventEmitter.d.ts.map +0 -1
- package/dist/animation/utils/flameConverter.d.ts +0 -26
- package/dist/animation/utils/flameConverter.d.ts.map +0 -1
- package/dist/audio/AnimationPlayer.d.ts +0 -53
- package/dist/audio/AnimationPlayer.d.ts.map +0 -1
- package/dist/audio/StreamingAudioPlayer.d.ts +0 -113
- 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/avatar_core_wasm.wasm +0 -0
- package/dist/config/app-config.d.ts +0 -48
- package/dist/config/app-config.d.ts.map +0 -1
- package/dist/config/constants.d.ts +0 -13
- package/dist/config/constants.d.ts.map +0 -1
- package/dist/config/region-config.d.ts +0 -17
- package/dist/config/region-config.d.ts.map +0 -1
- package/dist/config/sdk-config-loader.d.ts +0 -12
- 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 +0 -100
- 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 +0 -80
- package/dist/generated/driveningress/v1/driveningress.d.ts.map +0 -1
- package/dist/generated/driveningress/v2/driveningress.d.ts +0 -81
- package/dist/generated/driveningress/v2/driveningress.d.ts.map +0 -1
- package/dist/generated/google/protobuf/any.d.ts +0 -145
- package/dist/generated/google/protobuf/any.d.ts.map +0 -1
- package/dist/generated/google/protobuf/struct.d.ts +0 -108
- package/dist/generated/google/protobuf/struct.d.ts.map +0 -1
- package/dist/generated/google/protobuf/timestamp.d.ts +0 -129
- package/dist/generated/google/protobuf/timestamp.d.ts.map +0 -1
- package/dist/generated/jsonapi/v1/base.d.ts +0 -140
- package/dist/generated/jsonapi/v1/base.d.ts.map +0 -1
- package/dist/generated/platform/v1/asset_groups.d.ts +0 -225
- package/dist/generated/platform/v1/asset_groups.d.ts.map +0 -1
- package/dist/generated/platform/v1/assets.d.ts +0 -149
- package/dist/generated/platform/v1/assets.d.ts.map +0 -1
- package/dist/generated/platform/v1/character.d.ts +0 -395
- package/dist/generated/platform/v1/character.d.ts.map +0 -1
- package/dist/generated/platform/v1/redeem.d.ts +0 -22
- package/dist/generated/platform/v1/redeem.d.ts.map +0 -1
- package/dist/index-DwhR9l52.js +0 -9712
- package/dist/index-DwhR9l52.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 +0 -77
- package/dist/renderer/RenderSystem.d.ts.map +0 -1
- package/dist/renderer/covariance.d.ts +0 -13
- package/dist/renderer/covariance.d.ts.map +0 -1
- package/dist/renderer/renderer.d.ts +0 -8
- package/dist/renderer/renderer.d.ts.map +0 -1
- package/dist/renderer/sortSplats.d.ts +0 -12
- package/dist/renderer/sortSplats.d.ts.map +0 -1
- package/dist/renderer/webgl/reorderData.d.ts +0 -14
- package/dist/renderer/webgl/reorderData.d.ts.map +0 -1
- package/dist/renderer/webgl/webglRenderer.d.ts +0 -66
- package/dist/renderer/webgl/webglRenderer.d.ts.map +0 -1
- package/dist/renderer/webgpu/webgpuRenderer.d.ts +0 -54
- 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 +0 -17
- package/dist/utils/animation-interpolation.d.ts.map +0 -1
- package/dist/utils/error-utils.d.ts +0 -27
- package/dist/utils/error-utils.d.ts.map +0 -1
- package/dist/utils/logger.d.ts +0 -35
- 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/utils/toast.d.ts +0 -74
- package/dist/utils/toast.d.ts.map +0 -1
- package/dist/wasm/avatarCoreAdapter.d.ts +0 -188
- package/dist/wasm/avatarCoreAdapter.d.ts.map +0 -1
- package/dist/wasm/avatarCoreMemory.d.ts +0 -141
- package/dist/wasm/avatarCoreMemory.d.ts.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* AvatarKit SDK - Unified Public API
|
|
3
3
|
*/
|
|
4
|
-
export { APP_CONFIG } from './config/app-config';
|
|
5
4
|
export { Avatar } from './core/Avatar';
|
|
6
5
|
export { AvatarController } from './core/AvatarController';
|
|
7
|
-
export {
|
|
6
|
+
export { AvatarSDK } from './core/AvatarSDK';
|
|
8
7
|
export { AvatarManager } from './core/AvatarManager';
|
|
9
8
|
export { AvatarView } from './core/AvatarView';
|
|
10
9
|
export * from './types';
|
|
11
|
-
export type { CharacterInfo, FlameInfo } from './wasm/avatarCoreAdapter';
|
|
12
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b, c, m, f, d, j, g, C, i, D, E, k, h, L, R, n } from "./index-DADGbRoo.js";
|
|
2
2
|
export {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
3
|
+
b as Avatar,
|
|
4
|
+
c as AvatarController,
|
|
5
|
+
m as AvatarError,
|
|
6
|
+
f as AvatarManager,
|
|
7
|
+
d as AvatarSDK,
|
|
8
|
+
j as AvatarState,
|
|
9
|
+
g as AvatarView,
|
|
10
|
+
C as ConnectionState,
|
|
11
|
+
i as ConversationState,
|
|
12
|
+
D as DrivingServiceMode,
|
|
13
|
+
E as Environment,
|
|
14
|
+
k as ErrorCode,
|
|
15
|
+
h as LoadProgress,
|
|
16
|
+
L as LogLevel,
|
|
17
|
+
R as ResourceType,
|
|
18
|
+
n as extractResourceUrls
|
|
18
19
|
};
|
|
19
|
-
//# sourceMappingURL=index.js.map
|
package/dist/next.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-frame render timing — Web platform.
|
|
3
|
+
* Aligned with Android FrameRenderInfo / iOS FrameRenderInfo.
|
|
4
|
+
*/
|
|
5
|
+
export interface FrameRenderInfo {
|
|
6
|
+
/** Frame start timestamp (performance.now ms). */
|
|
7
|
+
startTimeMs: number;
|
|
8
|
+
/** Frame end timestamp (performance.now ms). */
|
|
9
|
+
endTimeMs: number;
|
|
10
|
+
/** Sort stage time (ms). */
|
|
11
|
+
sortTimeMs: number;
|
|
12
|
+
/** GPU render time (ms). */
|
|
13
|
+
renderTimeMs: number;
|
|
14
|
+
/** Reorder time (ms, WebGL path only; 0 for WebGPU). */
|
|
15
|
+
reorderTimeMs: number;
|
|
16
|
+
/** CPU render-submit time (ms, loadSplats + render call). */
|
|
17
|
+
renderSubmitTimeMs: number;
|
|
18
|
+
/** Production frame serial (incremented on actual render). */
|
|
19
|
+
frameSerial: number;
|
|
20
|
+
/** Presentation frame serial (incremented on display submit). */
|
|
21
|
+
presentFrameSerial: number;
|
|
22
|
+
/** Idle time: gap between previous frame end and this frame start (ms). */
|
|
23
|
+
idleTimeMs: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Frame rate monitoring info — unified public API across platforms.
|
|
27
|
+
* Contains pre-computed high-level performance metrics.
|
|
28
|
+
*/
|
|
29
|
+
export interface FrameRateInfo {
|
|
30
|
+
/** Production FPS (actual frames rendered per second). */
|
|
31
|
+
fps: number;
|
|
32
|
+
/** Presentation FPS (display refresh rate including reused frames). */
|
|
33
|
+
presentationFps: number;
|
|
34
|
+
/** 95th percentile frame interval (ms). */
|
|
35
|
+
frameIntervalP95Ms: number;
|
|
36
|
+
/** 99th percentile frame interval (ms). */
|
|
37
|
+
frameIntervalP99Ms: number;
|
|
38
|
+
/** Percentage of frames with interval > 50ms (jank ratio). */
|
|
39
|
+
jankRatioPercent: number;
|
|
40
|
+
/** Average total frame time (ms). */
|
|
41
|
+
averageFrameTimeMs: number;
|
|
42
|
+
/** Estimated CPU busy ratio (%). Browser approximation based on frame active time vs interval. */
|
|
43
|
+
cpuUsagePercent: number;
|
|
44
|
+
/** Per-frame details within the sliding window (aligned with Android/iOS). */
|
|
45
|
+
frames: FrameRenderInfo[];
|
|
46
|
+
}
|
|
47
|
+
export interface PlaybackStats {
|
|
48
|
+
avgFps: number;
|
|
49
|
+
frameCount: number;
|
|
50
|
+
durationMs: number;
|
|
51
|
+
/** Percentage of frame intervals > 50ms */
|
|
52
|
+
jankRatio: number;
|
|
53
|
+
/** Coefficient of variation of frame intervals (stddev / mean) */
|
|
54
|
+
fpsCv: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Frame rate monitor with 2-second sliding window.
|
|
58
|
+
* Aligned with Android/iOS FrameRateMonitor.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* controller.frameRateMonitorEnabled = true
|
|
63
|
+
* controller.onFrameRateInfo = (info) => {
|
|
64
|
+
* console.log('FPS:', info.fps, 'Jank:', info.jankRatioPercent)
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare class FrameRateMonitor {
|
|
69
|
+
enabled: boolean;
|
|
70
|
+
onFrameRateInfo: ((info: FrameRateInfo) => void) | null;
|
|
71
|
+
private lwFrameCount;
|
|
72
|
+
private lwStartTimeMs;
|
|
73
|
+
private lwLastEndTimeMs;
|
|
74
|
+
private lwJankCount;
|
|
75
|
+
private lwSumInterval;
|
|
76
|
+
private lwSumIntervalSq;
|
|
77
|
+
/** Reset the lightweight counter. Call at playback start. */
|
|
78
|
+
resetPlaybackStats(): void;
|
|
79
|
+
/** Get lightweight playback stats. Call at playback end. */
|
|
80
|
+
getPlaybackStats(): PlaybackStats;
|
|
81
|
+
private frames;
|
|
82
|
+
private computeFrameRateInfo;
|
|
83
|
+
private percentileInterval;
|
|
84
|
+
private jankRatio;
|
|
85
|
+
}
|
|
@@ -16,8 +16,14 @@ export interface CameraSettings {
|
|
|
16
16
|
translationY: number;
|
|
17
17
|
translationZ: number;
|
|
18
18
|
}
|
|
19
|
+
export interface TransformSettings {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
scale: number;
|
|
23
|
+
}
|
|
19
24
|
export interface CharacterSettings {
|
|
20
25
|
eyelid: EyelidSettings;
|
|
26
|
+
eyefocus?: EyelidSettings;
|
|
21
27
|
camera: CameraSettings;
|
|
28
|
+
transform?: TransformSettings;
|
|
22
29
|
}
|
|
23
|
-
//# sourceMappingURL=character-settings.d.ts.map
|
|
@@ -1,7 +1,45 @@
|
|
|
1
|
-
import { CharacterAsset } from '../generated/driveningress/v2/driveningress';
|
|
2
1
|
import { CameraSettings, CharacterSettings } from './character-settings';
|
|
2
|
+
export interface Resource {
|
|
3
|
+
type: string;
|
|
4
|
+
local: string;
|
|
5
|
+
remote: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ResourceHolder {
|
|
8
|
+
resource?: Resource;
|
|
9
|
+
/** Compressed model resource (~30% of original size, with minor quality degradation). */
|
|
10
|
+
xrResource?: Resource;
|
|
11
|
+
}
|
|
12
|
+
export interface Models {
|
|
13
|
+
shape?: ResourceHolder;
|
|
14
|
+
gsStandard?: ResourceHolder;
|
|
15
|
+
gsHigh?: ResourceHolder;
|
|
16
|
+
gsUltra?: ResourceHolder;
|
|
17
|
+
}
|
|
18
|
+
export interface Animations {
|
|
19
|
+
frameIdle?: ResourceHolder;
|
|
20
|
+
frameMono?: ResourceHolder;
|
|
21
|
+
audioMono?: ResourceHolder;
|
|
22
|
+
}
|
|
23
|
+
export interface CustomAnimation {
|
|
24
|
+
key: string;
|
|
25
|
+
pbUrl: string;
|
|
26
|
+
wavUrl: string;
|
|
27
|
+
remark: string;
|
|
28
|
+
}
|
|
29
|
+
export interface CharacterAsset {
|
|
30
|
+
characterId: string;
|
|
31
|
+
version: string;
|
|
32
|
+
camera?: ResourceHolder;
|
|
33
|
+
models?: Models;
|
|
34
|
+
animations?: Animations;
|
|
35
|
+
background?: ResourceHolder;
|
|
36
|
+
characterSettings?: {
|
|
37
|
+
[key: string]: any;
|
|
38
|
+
};
|
|
39
|
+
customAnimations: CustomAnimation[];
|
|
40
|
+
}
|
|
3
41
|
/**
|
|
4
|
-
*
|
|
42
|
+
* Character metadata
|
|
5
43
|
*/
|
|
6
44
|
export type CharacterMeta = CharacterAsset & {
|
|
7
45
|
characterSettings?: CharacterSettings;
|
|
@@ -13,27 +51,15 @@ export type PreloadCameraSettings = PreloadResources<{
|
|
|
13
51
|
camera: CameraSettings;
|
|
14
52
|
}>;
|
|
15
53
|
/**
|
|
16
|
-
*
|
|
54
|
+
* Resource type enumeration
|
|
17
55
|
*/
|
|
18
56
|
export declare enum ResourceType {
|
|
19
57
|
CAMERA = "camera",
|
|
20
58
|
ANIMATION_IDLE = "frameIdle",
|
|
21
|
-
ANIMATION_MONO = "frameMono",
|
|
22
|
-
AUDIO_MONO = "audioMono",
|
|
23
59
|
MODEL_SHAPE = "shape",
|
|
24
60
|
MODEL_GS = "gsStandard"
|
|
25
61
|
}
|
|
26
62
|
/**
|
|
27
|
-
*
|
|
63
|
+
* Extract all resource URLs
|
|
28
64
|
*/
|
|
29
65
|
export declare function extractResourceUrls(meta: CharacterMeta): Record<ResourceType, string | null>;
|
|
30
|
-
/**
|
|
31
|
-
* 检查角色是否有完整的独白资源
|
|
32
|
-
*/
|
|
33
|
-
export declare function hasMonologue(meta: CharacterMeta): boolean;
|
|
34
|
-
/**
|
|
35
|
-
* 从 RealtimeCharacter 的 modelInfo JSON 中解析是否有独白
|
|
36
|
-
* modelInfo 是一个 JSON 字符串,包含角色的模型信息
|
|
37
|
-
*/
|
|
38
|
-
export declare function hasMonologueFromModelInfo(modelInfo: string): boolean;
|
|
39
|
-
//# sourceMappingURL=character.d.ts.map
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,20 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Unified public types & interfaces
|
|
3
3
|
*/
|
|
4
4
|
export declare enum Environment {
|
|
5
5
|
cn = "cn",
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
intl = "intl"
|
|
7
|
+
}
|
|
8
|
+
export declare enum DrivingServiceMode {
|
|
9
|
+
/** Driven by SDK directly */
|
|
10
|
+
sdk = "sdk",
|
|
11
|
+
/** Driven by host application */
|
|
12
|
+
host = "host"
|
|
13
|
+
}
|
|
14
|
+
export declare enum LogLevel {
|
|
15
|
+
/** Disable all logs */
|
|
16
|
+
off = "off",
|
|
17
|
+
/** Error logs only */
|
|
18
|
+
error = "error",
|
|
19
|
+
/** Warning and error logs */
|
|
20
|
+
warning = "warning",
|
|
21
|
+
/** All logs (info, warning, error), default value */
|
|
22
|
+
all = "all"
|
|
23
|
+
}
|
|
24
|
+
export interface AudioFormat {
|
|
25
|
+
/** Channel count, fixed to 1 (mono) */
|
|
26
|
+
readonly channelCount: 1;
|
|
27
|
+
/** Sample rate, supported: 8000, 16000, 22050, 24000, 32000, 44100, 48000, default: 16000 */
|
|
28
|
+
readonly sampleRate: number;
|
|
8
29
|
}
|
|
9
30
|
export interface Configuration {
|
|
10
31
|
readonly environment: Environment;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
32
|
+
/** Driving service mode, default is sdk */
|
|
33
|
+
readonly drivingServiceMode?: DrivingServiceMode;
|
|
34
|
+
/** Log level, default is off */
|
|
35
|
+
readonly logLevel?: LogLevel;
|
|
36
|
+
/** Audio format configuration, default is { channelCount: 1, sampleRate: 16000 } */
|
|
37
|
+
readonly audioFormat?: AudioFormat;
|
|
38
|
+
/** Custom character data API base URL (optional, if provided will be used preferentially, otherwise use environment-configured sdkApiBaseUrl) */
|
|
39
|
+
readonly characterApiBaseUrl?: string;
|
|
18
40
|
}
|
|
19
41
|
export declare enum LoadProgress {
|
|
20
42
|
downloading = "downloading",
|
|
@@ -32,22 +54,61 @@ export declare enum ConnectionState {
|
|
|
32
54
|
connected = "connected",
|
|
33
55
|
failed = "failed"
|
|
34
56
|
}
|
|
35
|
-
export declare enum
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
57
|
+
export declare enum ConversationState {
|
|
58
|
+
/** Idle state (breathing animation) */
|
|
59
|
+
idle = "idle",
|
|
60
|
+
/** Playing state */
|
|
61
|
+
playing = "playing",
|
|
62
|
+
/** Paused state */
|
|
63
|
+
paused = "paused"
|
|
64
|
+
}
|
|
65
|
+
export declare enum ErrorCode {
|
|
66
|
+
/** AppID not recognized (reserved, future appID validation logic) */
|
|
67
|
+
appIDUnrecognized = "appIDUnrecognized",
|
|
68
|
+
/** Session Token invalid (WebSocket close code 4010) */
|
|
69
|
+
sessionTokenInvalid = "sessionTokenInvalid",
|
|
70
|
+
/** Session Token expired (WebSocket close code 4010) */
|
|
71
|
+
sessionTokenExpired = "sessionTokenExpired",
|
|
72
|
+
/** Insufficient balance (WebSocket close code 4001) */
|
|
73
|
+
insufficientBalance = "insufficientBalance",
|
|
74
|
+
/** Concurrent connection limit exceeded (WebSocket close code 4003) */
|
|
75
|
+
concurrentLimitExceeded = "concurrentLimitExceeded",
|
|
76
|
+
/** AvatarID not recognized */
|
|
77
|
+
avatarIDUnrecognized = "avatarIDUnrecognized",
|
|
78
|
+
/** Failed to fetch avatar metadata */
|
|
79
|
+
failedToFetchAvatarMetadata = "failedToFetchAvatarMetadata",
|
|
80
|
+
/** Failed to download avatar assets */
|
|
81
|
+
failedToDownloadAvatarAssets = "failedToDownloadAvatarAssets",
|
|
82
|
+
/** WebSocket connection error (handshake failure, network error) */
|
|
83
|
+
websocketError = "websocketError",
|
|
84
|
+
/** WebSocket connection closed abnormally (close code 1006) */
|
|
85
|
+
websocketClosedAbnormally = "websocketClosedAbnormally",
|
|
86
|
+
/** WebSocket closed with unexpected close code */
|
|
87
|
+
websocketClosedUnexpected = "websocketClosedUnexpected",
|
|
88
|
+
/** Session timeout (WebSocket close code 4002) */
|
|
89
|
+
sessionTimeout = "sessionTimeout",
|
|
90
|
+
/** Connection already in progress */
|
|
91
|
+
connectionInProgress = "connectionInProgress",
|
|
92
|
+
/** Network layer not available (SDK mode required) */
|
|
93
|
+
networkLayerNotAvailable = "networkLayerNotAvailable",
|
|
94
|
+
/** Failed to start playback */
|
|
95
|
+
playbackStartFailed = "playbackStartFailed",
|
|
96
|
+
/** Playback initialization failed */
|
|
97
|
+
playbackInitFailed = "playbackInitFailed",
|
|
98
|
+
/** Audio-only playback initialization failed */
|
|
99
|
+
audioOnlyInitFailed = "audioOnlyInitFailed",
|
|
100
|
+
/** No audio data to play */
|
|
101
|
+
noAudio = "noAudio",
|
|
102
|
+
/** Audio context not initialized */
|
|
103
|
+
audioContextNotInitialized = "audioContextNotInitialized",
|
|
104
|
+
/** Animation player not initialized */
|
|
105
|
+
animationPlayerNotInitialized = "animationPlayerNotInitialized",
|
|
106
|
+
/** Server-side error */
|
|
107
|
+
serverError = "serverError"
|
|
108
|
+
}
|
|
109
|
+
export declare class AvatarError extends Error {
|
|
110
|
+
code: ErrorCode;
|
|
111
|
+
constructor(message: string, code: ErrorCode);
|
|
51
112
|
}
|
|
52
113
|
export interface CameraConfig {
|
|
53
114
|
position: [number, number, number];
|
|
@@ -58,11 +119,88 @@ export interface CameraConfig {
|
|
|
58
119
|
up?: [number, number, number];
|
|
59
120
|
aspect?: number;
|
|
60
121
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
122
|
+
/**
|
|
123
|
+
* Animation keyframe data
|
|
124
|
+
* Used to represent avatar pose and expression parameters
|
|
125
|
+
*/
|
|
126
|
+
export interface KeyframeData {
|
|
127
|
+
/** Translation [x, y, z] */
|
|
128
|
+
translation: number[];
|
|
129
|
+
/** Rotation [x, y, z] (Euler angles, in radians) */
|
|
130
|
+
rotation: number[];
|
|
131
|
+
/** Neck pose [x, y, z] (in radians) */
|
|
132
|
+
neckPose: number[];
|
|
133
|
+
/** Jaw pose [x, y, z] (in radians) */
|
|
134
|
+
jawPose: number[];
|
|
135
|
+
/** Eye pose [x, y, z, x, y, z] (3 parameters for each eye) */
|
|
136
|
+
eyePose: number[];
|
|
137
|
+
/** Eyelid [x, y] */
|
|
138
|
+
eyeLid: number[];
|
|
139
|
+
/** Expression parameters array */
|
|
140
|
+
expression: number[];
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Post-processing parameter configuration
|
|
144
|
+
* Used to overlay in real-time on animation parameters returned by the server
|
|
145
|
+
*/
|
|
146
|
+
export interface PostProcessingConfig {
|
|
147
|
+
/** Rotation (Euler angles, in radians) */
|
|
148
|
+
rotation?: {
|
|
149
|
+
x?: number;
|
|
150
|
+
y?: number;
|
|
151
|
+
z?: number;
|
|
152
|
+
};
|
|
153
|
+
/** Translation (position offset) */
|
|
154
|
+
translation?: {
|
|
155
|
+
x?: number;
|
|
156
|
+
y?: number;
|
|
157
|
+
z?: number;
|
|
158
|
+
};
|
|
159
|
+
/** Neck pose offset (in radians) */
|
|
160
|
+
neckPose?: {
|
|
161
|
+
x?: number;
|
|
162
|
+
y?: number;
|
|
163
|
+
z?: number;
|
|
164
|
+
weightX?: number;
|
|
165
|
+
weightY?: number;
|
|
166
|
+
weightZ?: number;
|
|
167
|
+
};
|
|
168
|
+
/** Jaw pose offset (in radians) */
|
|
169
|
+
jawPose?: {
|
|
170
|
+
x?: number;
|
|
171
|
+
y?: number;
|
|
172
|
+
z?: number;
|
|
173
|
+
weight?: number;
|
|
174
|
+
};
|
|
175
|
+
/** Eye pose offset (in radians) */
|
|
176
|
+
eyePose?: {
|
|
177
|
+
x?: number;
|
|
178
|
+
y?: number;
|
|
179
|
+
z?: number;
|
|
180
|
+
weightX?: number;
|
|
181
|
+
weightY?: number;
|
|
182
|
+
weightZ?: number;
|
|
183
|
+
};
|
|
184
|
+
/** Eye blink value (-1.0 to 1.0, larger value means more closed) */
|
|
185
|
+
eyeBlink?: number;
|
|
186
|
+
/** Expression weight (0.0-2.0, 0=no expression, 1=normal, >1=enhanced) */
|
|
187
|
+
expressionWeight?: number;
|
|
188
|
+
/** Eye tracking complete configuration (real-time control of eye_focus, must provide complete configuration) */
|
|
189
|
+
eyefocus?: {
|
|
190
|
+
enabled: boolean;
|
|
191
|
+
auto_eyelid_adjustment?: boolean;
|
|
192
|
+
eyelid_threshold?: number;
|
|
193
|
+
targets?: number[];
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
export interface FlameInfo {
|
|
197
|
+
vertexCount: number;
|
|
198
|
+
faceCount: number;
|
|
199
|
+
jointCount: number;
|
|
200
|
+
}
|
|
201
|
+
export interface CharacterInfo {
|
|
202
|
+
pointCount: number;
|
|
203
|
+
hasAnimation: boolean;
|
|
66
204
|
}
|
|
67
205
|
export * from './character';
|
|
68
|
-
|
|
206
|
+
export type { FrameRateInfo, FrameRenderInfo } from '../performance/FrameRateMonitor';
|
package/dist/vite.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* Vite plugin for @spatialwalk/avatarkit
|
|
4
|
+
* Automatically handles WASM file configuration for development and production builds
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { defineConfig } from 'vite'
|
|
9
|
+
* import { avatarkitVitePlugin } from '@spatialwalk/avatarkit/vite'
|
|
10
|
+
*
|
|
11
|
+
* export default defineConfig({
|
|
12
|
+
* plugins: [
|
|
13
|
+
* avatarkitVitePlugin()
|
|
14
|
+
* ]
|
|
15
|
+
* })
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function avatarkitVitePlugin(): Plugin;
|
|
19
|
+
export default avatarkitVitePlugin;
|
package/next.d.ts
ADDED
package/next.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js plugin for @spatialwalk/avatarkit
|
|
3
|
+
* Handles WASM file configuration for both webpack and Turbopack (Next.js 15+/16+)
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* import { withAvatarkit } from '@spatialwalk/avatarkit/next'
|
|
7
|
+
* export default withAvatarkit({ ...your next config... })
|
|
8
|
+
*/
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import { dirname, join } from 'path';
|
|
11
|
+
import { writeFileSync, readFileSync, readdirSync, mkdirSync, copyFileSync, existsSync, } from 'fs';
|
|
12
|
+
// ── Locate SDK directory ──────────────────────────────────────────────
|
|
13
|
+
// Walk up from this file (inside the SDK package) to find the package root.
|
|
14
|
+
// This is reliable regardless of process.cwd(), monorepos, or hoisted deps.
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = dirname(__filename);
|
|
17
|
+
// Since this file IS inside the SDK package (at package root), __dirname is the SDK dir.
|
|
18
|
+
const sdkDir = __dirname;
|
|
19
|
+
const sdkDistDir = join(sdkDir, 'dist');
|
|
20
|
+
// ── Embedded webpack loader ───────────────────────────────────────────
|
|
21
|
+
// Fixes Emscripten's scriptDirectory: bundlers replace import.meta.url with
|
|
22
|
+
// a build-time path that browsers can't use to locate WASM files.
|
|
23
|
+
// This loader replaces it with the correct public path.
|
|
24
|
+
function createLoaderCode(wasmPublicPath) {
|
|
25
|
+
return `module.exports = function(source) {
|
|
26
|
+
// Strategy 1: Replace assignment only (simpler, more robust)
|
|
27
|
+
var pattern1 = /scriptDirectory\\s*=\\s*new\\s+URL\\(\\s*"\\."\\s*,\\s*_scriptName\\s*\\)\\.href\\s*;/;
|
|
28
|
+
var result = source.replace(pattern1, 'scriptDirectory = "${wasmPublicPath}";');
|
|
29
|
+
if (result !== source) return result;
|
|
30
|
+
|
|
31
|
+
// Strategy 2: Full try/catch block (handles different catch syntax)
|
|
32
|
+
var pattern2 = /try\\s*\\{\\s*scriptDirectory\\s*=\\s*new\\s+URL\\(\\s*"\\."\\s*,\\s*_scriptName\\s*\\)\\.href\\s*;?\\s*\\}\\s*catch\\s*(\\([^)]*\\))?\\s*\\{\\s*\\}/;
|
|
33
|
+
result = source.replace(pattern2, 'scriptDirectory = "${wasmPublicPath}";');
|
|
34
|
+
if (result !== source) return result;
|
|
35
|
+
|
|
36
|
+
console.warn('[avatarkit] WARNING: scriptDirectory pattern not matched in', this.resourcePath);
|
|
37
|
+
return source;
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
40
|
+
}
|
|
41
|
+
function ensureLoader(wasmPublicPath) {
|
|
42
|
+
const cacheDir = join(sdkDir, '.cache');
|
|
43
|
+
const loaderPath = join(cacheDir, 'wasm-script-dir-loader.cjs');
|
|
44
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
45
|
+
writeFileSync(loaderPath, createLoaderCode(wasmPublicPath));
|
|
46
|
+
return loaderPath;
|
|
47
|
+
}
|
|
48
|
+
// ── Copy WASM files to public directory ───────────────────────────────
|
|
49
|
+
// Works for both webpack and Turbopack: public/ files are served by Next.js
|
|
50
|
+
function copyWasmToPublic(projectDir) {
|
|
51
|
+
const publicWasmDir = join(projectDir, 'public', '_avatarkit');
|
|
52
|
+
mkdirSync(publicWasmDir, { recursive: true });
|
|
53
|
+
try {
|
|
54
|
+
const files = readdirSync(sdkDistDir);
|
|
55
|
+
for (const file of files) {
|
|
56
|
+
if (file.startsWith('avatar_core_wasm') && file.endsWith('.wasm')) {
|
|
57
|
+
const src = join(sdkDistDir, file);
|
|
58
|
+
const dest = join(publicWasmDir, file);
|
|
59
|
+
copyFileSync(src, dest);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
console.warn('[avatarkit] Failed to copy WASM files:', err.message);
|
|
65
|
+
console.warn('[avatarkit] SDK dist dir:', sdkDistDir);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// ── Webpack plugin: copy WASM to build output ─────────────────────────
|
|
69
|
+
// Emits WASM files into .next/static/chunks/ during webpack compilation.
|
|
70
|
+
// This is needed in addition to public/ for standalone Docker deployments
|
|
71
|
+
// where .next/static/ is copied but public/ may not be.
|
|
72
|
+
class CopyWasmPlugin {
|
|
73
|
+
apply(compiler) {
|
|
74
|
+
compiler.hooks.thisCompilation.tap('AvatarkitCopyWasm', (compilation) => {
|
|
75
|
+
compilation.hooks.processAssets.tap({
|
|
76
|
+
name: 'AvatarkitCopyWasm',
|
|
77
|
+
stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
|
|
78
|
+
}, () => {
|
|
79
|
+
try {
|
|
80
|
+
const files = readdirSync(sdkDistDir);
|
|
81
|
+
for (const file of files) {
|
|
82
|
+
if (file.startsWith('avatar_core_wasm') && file.endsWith('.wasm')) {
|
|
83
|
+
const content = readFileSync(join(sdkDistDir, file));
|
|
84
|
+
compilation.emitAsset(`static/chunks/${file}`, new compiler.webpack.sources.RawSource(content));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
console.warn('[avatarkit] CopyWasmPlugin error:', err.message);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// ── Detect project root from next.config location ─────────────────────
|
|
96
|
+
// next.config.mjs is always at the project root. Since this module is imported
|
|
97
|
+
// from next.config.mjs, we find the project root by walking up from import.meta.url
|
|
98
|
+
// of the calling module. However, we can't access the caller's import.meta.url,
|
|
99
|
+
// so we search for the nearest next.config.* file from the SDK location upwards.
|
|
100
|
+
function findProjectRoot() {
|
|
101
|
+
let dir = process.cwd(); // fallback, but also check for next.config
|
|
102
|
+
const configNames = [
|
|
103
|
+
'next.config.mjs',
|
|
104
|
+
'next.config.js',
|
|
105
|
+
'next.config.ts',
|
|
106
|
+
'next.config.cjs',
|
|
107
|
+
];
|
|
108
|
+
// Verify cwd has a next.config file
|
|
109
|
+
for (const name of configNames) {
|
|
110
|
+
if (existsSync(join(dir, name))) {
|
|
111
|
+
return dir;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Fallback: search from SDK location upward
|
|
115
|
+
let searchDir = sdkDir;
|
|
116
|
+
while (searchDir !== dirname(searchDir)) {
|
|
117
|
+
for (const name of configNames) {
|
|
118
|
+
if (existsSync(join(searchDir, name))) {
|
|
119
|
+
return searchDir;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
searchDir = dirname(searchDir);
|
|
123
|
+
}
|
|
124
|
+
return process.cwd();
|
|
125
|
+
}
|
|
126
|
+
// ── Main plugin ───────────────────────────────────────────────────────
|
|
127
|
+
export function withAvatarkit(nextConfig = {}) {
|
|
128
|
+
const basePath = nextConfig.basePath || '';
|
|
129
|
+
const wasmPublicPath = `${basePath}/_avatarkit/`;
|
|
130
|
+
const loaderPath = ensureLoader(wasmPublicPath);
|
|
131
|
+
const projectRoot = findProjectRoot();
|
|
132
|
+
// Copy WASM files to public/_avatarkit/ (works for both webpack & Turbopack)
|
|
133
|
+
copyWasmToPublic(projectRoot);
|
|
134
|
+
return {
|
|
135
|
+
...nextConfig,
|
|
136
|
+
// ── Turbopack configuration (Next.js 15+/16+) ──
|
|
137
|
+
turbopack: {
|
|
138
|
+
...nextConfig.turbopack,
|
|
139
|
+
rules: {
|
|
140
|
+
...nextConfig.turbopack?.rules,
|
|
141
|
+
'**/avatar_core_wasm*.js': {
|
|
142
|
+
loaders: [loaderPath],
|
|
143
|
+
as: '*.js',
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
// ── Webpack configuration ──
|
|
148
|
+
webpack: (config, context) => {
|
|
149
|
+
// 1. Fix: Next.js sets module.generator.asset.filename which breaks asset/inline
|
|
150
|
+
if (config.module.generator?.asset?.filename) {
|
|
151
|
+
const filename = config.module.generator.asset.filename;
|
|
152
|
+
delete config.module.generator.asset.filename;
|
|
153
|
+
config.module.generator['asset/resource'] = {
|
|
154
|
+
...config.module.generator['asset/resource'],
|
|
155
|
+
filename,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
// 2. Fix: Emscripten scriptDirectory derived from import.meta.url
|
|
159
|
+
config.module.rules.push({
|
|
160
|
+
test: /avatar_core_wasm.*\.js$/,
|
|
161
|
+
enforce: 'pre',
|
|
162
|
+
use: [{ loader: loaderPath }],
|
|
163
|
+
});
|
|
164
|
+
// 3. Copy WASM files to static/chunks/ (client build only, for standalone)
|
|
165
|
+
if (!context.isServer) {
|
|
166
|
+
config.plugins.push(new CopyWasmPlugin());
|
|
167
|
+
}
|
|
168
|
+
// Chain with user's webpack config
|
|
169
|
+
if (typeof nextConfig.webpack === 'function') {
|
|
170
|
+
return nextConfig.webpack(config, context);
|
|
171
|
+
}
|
|
172
|
+
return config;
|
|
173
|
+
},
|
|
174
|
+
// ── Headers: ensure WASM content-type ──
|
|
175
|
+
async headers() {
|
|
176
|
+
const userHeaders = typeof nextConfig.headers === 'function' ? await nextConfig.headers() : [];
|
|
177
|
+
return [
|
|
178
|
+
...userHeaders,
|
|
179
|
+
{
|
|
180
|
+
source: '/_avatarkit/:path*.wasm',
|
|
181
|
+
headers: [{ key: 'Content-Type', value: 'application/wasm' }],
|
|
182
|
+
},
|
|
183
|
+
];
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
export default withAvatarkit;
|