@spatialwalk/avatarkit 1.0.0-beta.43 → 1.0.0-beta.45
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 +24 -0
- package/README.md +3 -1
- package/dist/{StreamingAudioPlayer-Dy3rj-Pp.js → StreamingAudioPlayer-BDQE99ro.js} +1 -1
- package/dist/avatar_core_wasm.wasm +0 -0
- package/dist/core/AvatarController.d.ts +1 -0
- package/dist/core/AvatarView.d.ts +2 -1
- package/dist/{index-DiAM42qy.js → index-Bz4J6yf6.js} +57 -28
- package/dist/index.js +1 -1
- package/package.json +13 -12
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.0.0-beta.45] - 2025-12-29
|
|
9
|
+
|
|
10
|
+
### ✨ New Features
|
|
11
|
+
- **Immediate Rendering on Pause** - When playback is paused, updating post-processing parameters or camera configuration will immediately re-render the current frame:
|
|
12
|
+
- Post-processing parameters (rotation, neck pose, jaw pose, eye blink, etc.) now apply immediately when updated during pause
|
|
13
|
+
- Camera configuration (position, target, FOV, etc.) now applies immediately when updated during pause
|
|
14
|
+
- During normal playback, these updates still apply on the next frame as before
|
|
15
|
+
|
|
16
|
+
### 🔄 API Changes
|
|
17
|
+
|
|
18
|
+
### 🔄 API Changes
|
|
19
|
+
- **AvatarView Ready Promise Replaced with Callback** - Replaced `ready: Promise<void>` property with `onFirstRendering?: () => void` callback for better async handling:
|
|
20
|
+
- Removed `ready` Promise property
|
|
21
|
+
- Added `onFirstRendering` optional callback that is called when the first frame is rendered
|
|
22
|
+
- Callback-based approach is more idiomatic and easier to use than Promise-based approach
|
|
23
|
+
|
|
24
|
+
### 🗑️ Removed
|
|
25
|
+
- **Removed unused `seek()` method** - Removed unused and buggy `seek()` method from `StreamingAudioPlayer`
|
|
26
|
+
|
|
27
|
+
## [1.0.0-beta.44] - 2025-12-29
|
|
28
|
+
|
|
29
|
+
### 🔧 Performance Improvements
|
|
30
|
+
- **Removed unnecessary headers from static resource requests** - Removed `X-App-Id` and `Authorization` headers from static resource downloads (shape.pb, point_cloud.ply, camera.json, etc.) to avoid CORS preflight requests and improve loading performance
|
|
31
|
+
|
|
8
32
|
## [1.0.0-beta.43] - 2025-12-29
|
|
9
33
|
|
|
10
34
|
### 🔧 Improvements
|
package/README.md
CHANGED
|
@@ -309,7 +309,9 @@ const container = document.getElementById('avatar-container')
|
|
|
309
309
|
const avatarView = new AvatarView(avatar, container)
|
|
310
310
|
|
|
311
311
|
// Wait for first frame to render
|
|
312
|
-
|
|
312
|
+
avatarView.onFirstRendering = () => {
|
|
313
|
+
// First frame rendered
|
|
314
|
+
}
|
|
313
315
|
|
|
314
316
|
// Get or set avatar transform (position and scale)
|
|
315
317
|
// Get current transform
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import { A as APP_CONFIG, e as errorToMessage, l as logEvent, a as logger } from "./index-
|
|
4
|
+
import { A as APP_CONFIG, e as errorToMessage, l as logEvent, a as logger } from "./index-Bz4J6yf6.js";
|
|
5
5
|
class StreamingAudioPlayer {
|
|
6
6
|
constructor(options) {
|
|
7
7
|
__publicField(this, "audioContext", null);
|
|
File without changes
|
|
@@ -53,6 +53,7 @@ export declare class AvatarController {
|
|
|
53
53
|
private resetConversationIdState;
|
|
54
54
|
private getEffectiveConversationId;
|
|
55
55
|
setPostProcessingConfig(config: PostProcessingConfig | null): void;
|
|
56
|
+
private rerenderCurrentFrame;
|
|
56
57
|
setVolume(volume: number): void;
|
|
57
58
|
getVolume(): number;
|
|
58
59
|
private startStreamingPlaybackInternal;
|
|
@@ -3,7 +3,7 @@ import { AvatarController } from './AvatarController';
|
|
|
3
3
|
export declare class AvatarView {
|
|
4
4
|
private readonly avatarController;
|
|
5
5
|
private readonly avatar;
|
|
6
|
-
|
|
6
|
+
onFirstRendering?: () => void;
|
|
7
7
|
private canvas;
|
|
8
8
|
private renderSystem;
|
|
9
9
|
private isInitialized;
|
|
@@ -56,6 +56,7 @@ export declare class AvatarView {
|
|
|
56
56
|
private startRealtimeRendering;
|
|
57
57
|
private stopRealtimeRendering;
|
|
58
58
|
dispose(): void;
|
|
59
|
+
private rerenderCurrentFrameWithNewCamera;
|
|
59
60
|
private handleResize;
|
|
60
61
|
get transform(): {
|
|
61
62
|
x: number;
|
|
@@ -7573,7 +7573,7 @@ const _AnimationPlayer = class _AnimationPlayer {
|
|
|
7573
7573
|
if (this.streamingPlayer) {
|
|
7574
7574
|
return;
|
|
7575
7575
|
}
|
|
7576
|
-
const { StreamingAudioPlayer } = await import("./StreamingAudioPlayer-
|
|
7576
|
+
const { StreamingAudioPlayer } = await import("./StreamingAudioPlayer-BDQE99ro.js");
|
|
7577
7577
|
const { AvatarSDK: AvatarSDK2 } = await Promise.resolve().then(() => AvatarSDK$1);
|
|
7578
7578
|
const audioFormat = AvatarSDK2.getAudioFormat();
|
|
7579
7579
|
this.streamingPlayer = new StreamingAudioPlayer({
|
|
@@ -8963,7 +8963,7 @@ class AvatarSDK {
|
|
|
8963
8963
|
}
|
|
8964
8964
|
__publicField(AvatarSDK, "_isInitialized", false);
|
|
8965
8965
|
__publicField(AvatarSDK, "_configuration", null);
|
|
8966
|
-
__publicField(AvatarSDK, "_version", "1.0.0-beta.
|
|
8966
|
+
__publicField(AvatarSDK, "_version", "1.0.0-beta.45");
|
|
8967
8967
|
__publicField(AvatarSDK, "_avatarCore", null);
|
|
8968
8968
|
__publicField(AvatarSDK, "_dynamicSdkConfig", null);
|
|
8969
8969
|
const AvatarSDK$1 = Object.freeze(Object.defineProperty({
|
|
@@ -11091,6 +11091,44 @@ class AvatarController {
|
|
|
11091
11091
|
}
|
|
11092
11092
|
setPostProcessingConfig(config) {
|
|
11093
11093
|
this.postProcessingConfig = config;
|
|
11094
|
+
if (this.currentState === AvatarState.paused && this.isPlaying) {
|
|
11095
|
+
this.rerenderCurrentFrame();
|
|
11096
|
+
}
|
|
11097
|
+
}
|
|
11098
|
+
async rerenderCurrentFrameIfPaused() {
|
|
11099
|
+
if (this.currentState !== AvatarState.paused || !this.renderCallback) {
|
|
11100
|
+
return;
|
|
11101
|
+
}
|
|
11102
|
+
const frameIndex = this.lastRenderedFrameIndex;
|
|
11103
|
+
if (frameIndex < 0) {
|
|
11104
|
+
return;
|
|
11105
|
+
}
|
|
11106
|
+
let arrayIndex = frameIndex - this.keyframesOffset;
|
|
11107
|
+
if (arrayIndex < 0 || arrayIndex >= this.currentKeyframes.length) {
|
|
11108
|
+
if (this.currentKeyframes.length === 0) {
|
|
11109
|
+
return;
|
|
11110
|
+
}
|
|
11111
|
+
arrayIndex = Math.max(0, Math.min(this.currentKeyframes.length - 1, arrayIndex));
|
|
11112
|
+
}
|
|
11113
|
+
try {
|
|
11114
|
+
const currentFrame = this.currentKeyframes[arrayIndex];
|
|
11115
|
+
let wasmParams = convertProtoFlameToWasmParams(currentFrame);
|
|
11116
|
+
if (this.postProcessingConfig) {
|
|
11117
|
+
wasmParams = this.applyPostProcessingToParams(wasmParams);
|
|
11118
|
+
}
|
|
11119
|
+
const avatarCore = AvatarSDK.getAvatarCore();
|
|
11120
|
+
if (avatarCore) {
|
|
11121
|
+
const splatData = await avatarCore.computeFrameFlatFromParams(wasmParams, this.characterHandle ?? void 0);
|
|
11122
|
+
if (splatData) {
|
|
11123
|
+
this.renderCallback(splatData, frameIndex);
|
|
11124
|
+
}
|
|
11125
|
+
}
|
|
11126
|
+
} catch (error) {
|
|
11127
|
+
logger.error("[AvatarController] Failed to rerender current frame:", error instanceof Error ? error.message : String(error));
|
|
11128
|
+
}
|
|
11129
|
+
}
|
|
11130
|
+
async rerenderCurrentFrame() {
|
|
11131
|
+
await this.rerenderCurrentFrameIfPaused();
|
|
11094
11132
|
}
|
|
11095
11133
|
onTransitionComplete() {
|
|
11096
11134
|
var _a;
|
|
@@ -11519,18 +11557,7 @@ function errorToMessage(err) {
|
|
|
11519
11557
|
}
|
|
11520
11558
|
async function downloadResource(url) {
|
|
11521
11559
|
try {
|
|
11522
|
-
const
|
|
11523
|
-
const appId = AvatarSDK.appId;
|
|
11524
|
-
const token = AvatarSDK.sessionToken;
|
|
11525
|
-
if (appId) {
|
|
11526
|
-
headers["X-App-Id"] = appId;
|
|
11527
|
-
}
|
|
11528
|
-
if (token) {
|
|
11529
|
-
headers["Authorization"] = `Bearer ${token}`;
|
|
11530
|
-
}
|
|
11531
|
-
const response = await fetch(url, {
|
|
11532
|
-
headers: Object.keys(headers).length > 0 ? headers : void 0
|
|
11533
|
-
});
|
|
11560
|
+
const response = await fetch(url);
|
|
11534
11561
|
if (!response.ok) {
|
|
11535
11562
|
throw new Error(`HTTP ${response.status} ${response.statusText}`);
|
|
11536
11563
|
}
|
|
@@ -11667,18 +11694,7 @@ class AvatarDownloader {
|
|
|
11667
11694
|
}
|
|
11668
11695
|
try {
|
|
11669
11696
|
logger.log(`📥 Loading camera info from: ${cameraUrl}`);
|
|
11670
|
-
const
|
|
11671
|
-
const appId = AvatarSDK.appId;
|
|
11672
|
-
const token = AvatarSDK.sessionToken;
|
|
11673
|
-
if (appId) {
|
|
11674
|
-
headers["X-App-Id"] = appId;
|
|
11675
|
-
}
|
|
11676
|
-
if (token) {
|
|
11677
|
-
headers["Authorization"] = `Bearer ${token}`;
|
|
11678
|
-
}
|
|
11679
|
-
const response = await fetch(cameraUrl, {
|
|
11680
|
-
headers: Object.keys(headers).length > 0 ? headers : void 0
|
|
11681
|
-
});
|
|
11697
|
+
const response = await fetch(cameraUrl);
|
|
11682
11698
|
if (!response.ok) {
|
|
11683
11699
|
throw new Error(`Failed to fetch camera info: ${response.statusText}`);
|
|
11684
11700
|
}
|
|
@@ -13499,7 +13515,7 @@ class AvatarView {
|
|
|
13499
13515
|
constructor(avatar, container) {
|
|
13500
13516
|
__publicField(this, "avatarController");
|
|
13501
13517
|
__publicField(this, "avatar");
|
|
13502
|
-
__publicField(this, "
|
|
13518
|
+
__publicField(this, "onFirstRendering");
|
|
13503
13519
|
__publicField(this, "canvas");
|
|
13504
13520
|
__publicField(this, "renderSystem", null);
|
|
13505
13521
|
__publicField(this, "isInitialized", false);
|
|
@@ -13535,7 +13551,9 @@ class AvatarView {
|
|
|
13535
13551
|
this.renderRealtimeFrame(splatData, frameIndex);
|
|
13536
13552
|
});
|
|
13537
13553
|
this.canvas = this.createCanvas(container);
|
|
13538
|
-
this.
|
|
13554
|
+
this.initializeView(avatar).catch((error) => {
|
|
13555
|
+
logger.error("[AvatarView] Initialization failed:", error instanceof Error ? error.message : String(error));
|
|
13556
|
+
});
|
|
13539
13557
|
this.setupControllerEventListeners();
|
|
13540
13558
|
}
|
|
13541
13559
|
alignFlamePair(from, to2) {
|
|
@@ -13771,6 +13789,7 @@ class AvatarView {
|
|
|
13771
13789
|
return derivedCamera;
|
|
13772
13790
|
}
|
|
13773
13791
|
async renderFirstFrame() {
|
|
13792
|
+
var _a;
|
|
13774
13793
|
if (!this.renderSystem) {
|
|
13775
13794
|
throw new Error("Render system not initialized");
|
|
13776
13795
|
}
|
|
@@ -13793,6 +13812,7 @@ class AvatarView {
|
|
|
13793
13812
|
this.renderSystem.renderFrame();
|
|
13794
13813
|
if (APP_CONFIG.debug)
|
|
13795
13814
|
logger.log("[AvatarView] First frame rendered successfully");
|
|
13815
|
+
(_a = this.onFirstRendering) == null ? void 0 : _a.call(this);
|
|
13796
13816
|
} else {
|
|
13797
13817
|
throw new Error("Failed to compute first frame splat data");
|
|
13798
13818
|
}
|
|
@@ -14165,7 +14185,16 @@ class AvatarView {
|
|
|
14165
14185
|
this.renderSystem.updateCamera(cameraConfig);
|
|
14166
14186
|
if (APP_CONFIG.debug)
|
|
14167
14187
|
logger.log("[AvatarView] Applied new camera config to render system");
|
|
14188
|
+
if (this.avatarController.state === AvatarState.paused && this.renderingState === "speaking") {
|
|
14189
|
+
this.rerenderCurrentFrameWithNewCamera();
|
|
14190
|
+
}
|
|
14191
|
+
}
|
|
14192
|
+
}
|
|
14193
|
+
async rerenderCurrentFrameWithNewCamera() {
|
|
14194
|
+
if (this.avatarController.state !== AvatarState.paused || this.renderingState !== "speaking" || !this.renderSystem) {
|
|
14195
|
+
return;
|
|
14168
14196
|
}
|
|
14197
|
+
await this.avatarController.rerenderCurrentFrameIfPaused();
|
|
14169
14198
|
}
|
|
14170
14199
|
handleResize() {
|
|
14171
14200
|
if (this.renderSystem) {
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spatialwalk/avatarkit",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-beta.
|
|
4
|
+
"version": "1.0.0-beta.45",
|
|
5
|
+
"packageManager": "pnpm@10.18.2",
|
|
5
6
|
"description": "SPAvatar SDK - 3D Gaussian Splatting Avatar Rendering SDK",
|
|
6
7
|
"author": "SPAvatar Team",
|
|
7
8
|
"license": "MIT",
|
|
@@ -31,6 +32,16 @@
|
|
|
31
32
|
"CHANGELOG.md",
|
|
32
33
|
"dist"
|
|
33
34
|
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "SDK_BUILD=true vite build --mode library",
|
|
37
|
+
"dev": "vite build --mode library --watch",
|
|
38
|
+
"clean": "rm -rf dist",
|
|
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"
|
|
44
|
+
},
|
|
34
45
|
"peerDependencies": {
|
|
35
46
|
"@webgpu/types": "*"
|
|
36
47
|
},
|
|
@@ -47,15 +58,5 @@
|
|
|
47
58
|
"typescript": "^5.0.0",
|
|
48
59
|
"vite": "^5.0.0",
|
|
49
60
|
"vite-plugin-dts": "^4.5.4"
|
|
50
|
-
},
|
|
51
|
-
"scripts": {
|
|
52
|
-
"build": "SDK_BUILD=true vite build --mode library",
|
|
53
|
-
"dev": "vite build --mode library --watch",
|
|
54
|
-
"clean": "rm -rf dist",
|
|
55
|
-
"typecheck": "tsc --noEmit",
|
|
56
|
-
"test": "cd tests && pnpm test",
|
|
57
|
-
"test:watch": "cd tests && pnpm run test:watch",
|
|
58
|
-
"test:e2e": "cd tests && pnpm run test:e2e",
|
|
59
|
-
"test:perf": "cd tests && pnpm run test:perf"
|
|
60
61
|
}
|
|
61
|
-
}
|
|
62
|
+
}
|