@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 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
- await avatarView.ready // Promise that resolves when the first frame is rendered
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-DiAM42qy.js";
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
- readonly ready: Promise<void>;
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-Dy3rj-Pp.js");
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.43");
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 headers = {};
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 headers = {};
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, "ready");
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.ready = this.initializeView(avatar);
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
@@ -1,4 +1,4 @@
1
- import { b, c, f, d, j, g, C, i, D, E, k, h, L, R, S, m } from "./index-DiAM42qy.js";
1
+ import { b, c, f, d, j, g, C, i, D, E, k, h, L, R, S, m } from "./index-Bz4J6yf6.js";
2
2
  export {
3
3
  b as Avatar,
4
4
  c as AvatarController,
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.43",
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
+ }