@spatialwalk/avatarkit 1.0.0-beta.83 → 1.0.0-beta.85

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,20 @@ 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.85] - 2026-03-03
9
+
10
+ ### 🐛 Bugfixes
11
+ - **Startup Transition Continuity** - Fixed first-round playback jump by generating start transition from the currently displayed idle frame instead of fixed idle frame 0
12
+ - **Startup Rendering Order** - Emit `startRendering` only after startup transition frames are injected to avoid first-frame state mismatch
13
+
14
+ ### ✅ Tests
15
+ - Added regression tests for startup transition continuity and startup ordering to prevent reintroduction
16
+
17
+ ## [1.0.0-beta.84] - 2026-03-03
18
+
19
+ ### 🐛 Bugfixes
20
+ - **End-Transition Continuity** - Fixed the visual jump after conversation end transition by resetting idle frame cursor when returning to `Idle` state
21
+
8
22
  ## [1.0.0-beta.83] - 2026-03-03
9
23
 
10
24
  ### 🐛 Bugfixes
@@ -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, l as logger, e as errorToMessage, a as logEvent } from "./index-CQqZD1OY.js";
4
+ import { A as APP_CONFIG, l as logger, e as errorToMessage, a as logEvent } from "./index-vzFN-bug.js";
5
5
  class StreamingAudioPlayer {
6
6
  // Mark if AudioContext is being resumed, avoid concurrent resume requests
7
7
  constructor(options) {
@@ -11,6 +11,7 @@ export declare class AvatarController {
11
11
  onError: ((error: Error) => void) | null;
12
12
  private eventListeners;
13
13
  private renderCallback?;
14
+ private getCurrentIdleFrameCallback?;
14
15
  private characterHandle;
15
16
  private characterId;
16
17
  private postProcessingConfig;
@@ -9491,7 +9491,7 @@ const _AnimationPlayer = class _AnimationPlayer {
9491
9491
  if (this.streamingPlayer) {
9492
9492
  return;
9493
9493
  }
9494
- const { StreamingAudioPlayer } = await import("./StreamingAudioPlayer-yvKtEWGz.js");
9494
+ const { StreamingAudioPlayer } = await import("./StreamingAudioPlayer-By5EueKJ.js");
9495
9495
  const { AvatarSDK: AvatarSDK2 } = await Promise.resolve().then(() => AvatarSDK$1);
9496
9496
  const audioFormat = AvatarSDK2.getAudioFormat();
9497
9497
  this.streamingPlayer = new StreamingAudioPlayer({
@@ -11220,7 +11220,7 @@ class AvatarSDK {
11220
11220
  }
11221
11221
  __publicField(AvatarSDK, "_isInitialized", false);
11222
11222
  __publicField(AvatarSDK, "_configuration", null);
11223
- __publicField(AvatarSDK, "_version", "1.0.0-beta.83");
11223
+ __publicField(AvatarSDK, "_version", "1.0.0-beta.85");
11224
11224
  __publicField(AvatarSDK, "_avatarCore", null);
11225
11225
  __publicField(AvatarSDK, "_dynamicSdkConfig", null);
11226
11226
  const AvatarSDK$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -12217,6 +12217,7 @@ class AvatarController {
12217
12217
  __publicField(this, "eventListeners", /* @__PURE__ */ new Map());
12218
12218
  // ========== Callbacks ==========
12219
12219
  __publicField(this, "renderCallback");
12220
+ __publicField(this, "getCurrentIdleFrameCallback");
12220
12221
  __publicField(this, "characterHandle", null);
12221
12222
  // Character handle for multi-character support
12222
12223
  __publicField(this, "characterId", null);
@@ -13003,6 +13004,7 @@ class AvatarController {
13003
13004
  * @internal
13004
13005
  */
13005
13006
  setupInternalEventListeners(callbacks) {
13007
+ this.getCurrentIdleFrameCallback = callbacks.getCurrentIdleFrame;
13006
13008
  if (callbacks.onKeyframesUpdate) {
13007
13009
  this.registerEventListener("keyframesUpdate", callbacks.onKeyframesUpdate);
13008
13010
  }
@@ -13061,11 +13063,11 @@ class AvatarController {
13061
13063
  conversationId: ((_b2 = this.networkLayer) == null ? void 0 : _b2.getCurrentConversationId()) || void 0
13062
13064
  });
13063
13065
  });
13064
- this.emit("startRendering");
13065
13066
  const transitionFrames = await this.generateStartTransitionFrames();
13066
13067
  if (transitionFrames.length > 0) {
13067
13068
  this.currentKeyframes.unshift(...transitionFrames);
13068
13069
  }
13070
+ this.emit("startRendering");
13069
13071
  const silenceDurationS = START_TRANSITION_DURATION_MS / 1e3;
13070
13072
  const silenceChunk = this.createSilencePCMChunk(silenceDurationS);
13071
13073
  const audioChunksWithSilence = [
@@ -13114,8 +13116,11 @@ class AvatarController {
13114
13116
  if (!toFrame) return [];
13115
13117
  const toFrameWithPP = this.applyPostProcessingToFlame(toFrame);
13116
13118
  let fromFrame = null;
13119
+ if (this.getCurrentIdleFrameCallback) {
13120
+ fromFrame = await this.getCurrentIdleFrameCallback();
13121
+ }
13117
13122
  const avatarCore = AvatarSDK.getAvatarCore();
13118
- if (avatarCore && this.characterId) {
13123
+ if (!fromFrame && avatarCore && this.characterId) {
13119
13124
  const idleParams = await avatarCore.getCurrentFrameParams(0, this.characterId);
13120
13125
  fromFrame = convertWasmParamsToProtoFlame(idleParams);
13121
13126
  }
@@ -16393,6 +16398,28 @@ class AvatarView {
16393
16398
  }
16394
16399
  return this.cachedIdleFirstFrame;
16395
16400
  }
16401
+ /**
16402
+ * Get the currently displayed idle frame.
16403
+ * Used as the start frame for idle -> speaking transition to avoid startup jump.
16404
+ * @internal
16405
+ */
16406
+ async getCurrentDisplayedIdleFrame() {
16407
+ if (this.renderingState !== "idle") {
16408
+ return null;
16409
+ }
16410
+ const avatarCore = AvatarSDK.getAvatarCore();
16411
+ if (!avatarCore) {
16412
+ return null;
16413
+ }
16414
+ try {
16415
+ const displayedIndex = Math.max(0, this.idleCurrentFrameIndex - 1);
16416
+ const idleParams = await avatarCore.getCurrentFrameParams(displayedIndex, this.characterId);
16417
+ return convertWasmParamsToProtoFlame(idleParams);
16418
+ } catch (e2) {
16419
+ logger.warn("[AvatarView] Failed to get current idle frame:", e2 instanceof Error ? e2.message : String(e2));
16420
+ return null;
16421
+ }
16422
+ }
16396
16423
  /**
16397
16424
  * Get controller (public interface)
16398
16425
  */
@@ -16806,6 +16833,7 @@ class AvatarView {
16806
16833
  this.endTransitionFrames = [];
16807
16834
  this.isConversationActive = false;
16808
16835
  this.currentPlayingFrame = null;
16836
+ this.idleCurrentFrameIndex = 0;
16809
16837
  }
16810
16838
  }
16811
16839
  /**
@@ -16851,6 +16879,9 @@ class AvatarView {
16851
16879
  },
16852
16880
  onInterrupt: () => {
16853
16881
  this.handleInterrupt();
16882
+ },
16883
+ getCurrentIdleFrame: async () => {
16884
+ return this.getCurrentDisplayedIdleFrame();
16854
16885
  }
16855
16886
  });
16856
16887
  }
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { b, c, m, f, d, j, g, C, i, D, E, k, h, L, R, n } from "./index-CQqZD1OY.js";
1
+ import { b, c, m, f, d, j, g, C, i, D, E, k, h, L, R, n } from "./index-vzFN-bug.js";
2
2
  export {
3
3
  b as Avatar,
4
4
  c as AvatarController,
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.83",
4
+ "version": "1.0.0-beta.85",
5
5
  "packageManager": "pnpm@10.18.2",
6
6
  "description": "AvatarKit SDK - 3D Gaussian Splatting Avatar Rendering SDK",
7
7
  "author": "AvatarKit Team",
@@ -62,8 +62,12 @@
62
62
  "next": ">=13.0.0"
63
63
  },
64
64
  "peerDependenciesMeta": {
65
- "vite": { "optional": true },
66
- "next": { "optional": true }
65
+ "vite": {
66
+ "optional": true
67
+ },
68
+ "next": {
69
+ "optional": true
70
+ }
67
71
  },
68
72
  "dependencies": {
69
73
  "@bufbuild/protobuf": "^2.10.0",