@spatialwalk/avatarkit 1.0.0-beta.102 → 1.0.0-beta.104

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,18 @@ 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.104]
9
+
10
+ ### 🐛 Bugfixes
11
+
12
+ - **Telemetry logging** — Fixed console error logs showing only generic event name with no diagnostic details. Each telemetry event now uses its own event name and includes all properties inline for easier debugging.
13
+
14
+ ## [1.0.0-beta.103]
15
+
16
+ ### 🔧 Internal
17
+
18
+ - Optimize internal type exports
19
+
8
20
  ## [1.0.0-beta.102]
9
21
 
10
22
  ### 🐛 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-DNq7oTVY.js";
4
+ import { A as APP_CONFIG, l as logger, e as errorToMessage, a as logEvent } from "./index-BFNu-mKX.js";
5
5
  class StreamingAudioPlayer {
6
6
  // Mark if AudioContext is being resumed, avoid concurrent resume requests
7
7
  constructor(options) {
@@ -143,9 +143,8 @@ class StreamingAudioPlayer {
143
143
  });
144
144
  } catch (err) {
145
145
  logger.errorWithError("[StreamingAudioPlayer] Failed to resume AudioContext:", err);
146
- logEvent("character_player", "error", {
146
+ logEvent("audio_context_resume_failed", "error", {
147
147
  sessionId: this.sessionId,
148
- event: "audio_context_resume_failed",
149
148
  reason: err instanceof Error ? err.message : String(err)
150
149
  });
151
150
  } finally {
@@ -281,9 +280,8 @@ class StreamingAudioPlayer {
281
280
  if (!audioBuffer) {
282
281
  const errorMessage = "Failed to create AudioBuffer from PCM data";
283
282
  logger.error(errorMessage);
284
- logEvent("character_player", "error", {
285
- sessionId: this.sessionId,
286
- event: "audio_buffer_creation_failed"
283
+ logEvent("audio_buffer_creation_failed", "error", {
284
+ sessionId: this.sessionId
287
285
  });
288
286
  return;
289
287
  }
@@ -305,8 +303,7 @@ class StreamingAudioPlayer {
305
303
  const lastChunk = this.audioChunks[this.scheduledChunks - 1];
306
304
  if (lastChunk && !lastChunk.isLast) {
307
305
  this.log("All audio chunks ended but end=false, pausing and setting autoContinue");
308
- logEvent("character_player", "warning", {
309
- event: "audio_buffer_stall",
306
+ logEvent("audio_buffer_stall", "warning", {
310
307
  scheduled_chunks: this.scheduledChunks,
311
308
  audio_time: this.getCurrentTime()
312
309
  });
@@ -330,9 +327,8 @@ class StreamingAudioPlayer {
330
327
  });
331
328
  } catch (err) {
332
329
  logger.errorWithError("Failed to schedule audio chunk:", err);
333
- logEvent("character_player", "error", {
330
+ logEvent("schedule_chunk_failed", "error", {
334
331
  sessionId: this.sessionId,
335
- event: "schedule_chunk_failed",
336
332
  reason: err instanceof Error ? err.message : String(err)
337
333
  });
338
334
  }
@@ -1,4 +1,4 @@
1
- import { CameraConfig, KeyframeData } from '../types';
1
+ import { CameraConfig } from '../types';
2
2
  import { Avatar } from './Avatar';
3
3
  import { AvatarController } from './AvatarController';
4
4
  export declare class AvatarView {
@@ -57,19 +57,6 @@ export declare class AvatarView {
57
57
  * 更新相机配置
58
58
  */
59
59
  updateCameraConfig(cameraConfig: CameraConfig): void;
60
- /**
61
- * Render specified keyframe (pure rendering mode, no audio-animation synchronization)
62
- * Suitable for scenarios where external application controls audio playback and animation playback
63
- * @param keyframeData - Keyframe data
64
- * @param enableIdleRendering - Whether to enable idle loop rendering. true: Enable idle rendering and return immediately (skip this keyframe); false: Disable idle rendering and process keyframe (default)
65
- */
66
- renderFlame(keyframeData: KeyframeData, enableIdleRendering?: boolean): Promise<void>;
67
- generateTransition(options: {
68
- from?: KeyframeData;
69
- to?: KeyframeData;
70
- frameCount: number;
71
- useLinear?: boolean;
72
- }): Promise<KeyframeData[]>;
73
60
  /**
74
61
  * Render a single animation frame from raw protobuf data.
75
62
  *
@@ -107,6 +94,22 @@ export declare class AvatarView {
107
94
  * Start idle animation (stop pure rendering mode, resume idle loop).
108
95
  */
109
96
  startIdle(): void;
97
+ /**
98
+ * Generate transition frames from protobuf data.
99
+ *
100
+ * Decodes the protobuf, extracts the target keyframe, and generates
101
+ * transition frames from the current idle position to the target.
102
+ * The caller is responsible for playing the returned frames at the desired cadence.
103
+ *
104
+ * @param data - Raw protobuf bytes containing the target frame
105
+ * @param frameCount - Number of transition frames to generate
106
+ * @param options - Additional options
107
+ * @param options.useLinear - Use linear interpolation (default: true)
108
+ * @returns Array of opaque keyframe data for sequential playback
109
+ */
110
+ generateTransitionFromProtobuf(data: ArrayBuffer | Uint8Array, frameCount: number, options?: {
111
+ useLinear?: boolean;
112
+ }): Promise<unknown[]>;
110
113
  /**
111
114
  * Cancel any in-progress frame sequence playback.
112
115
  * Called by renderFromProtobuf when streaming frames arrive during transition.
@@ -9415,7 +9415,8 @@ function logEvent(event, level = "info", contents = {}) {
9415
9415
  error: "error"
9416
9416
  };
9417
9417
  const logMethod = logLevels[level] ?? "log";
9418
- logger[logMethod](`[Telemetry] ${event}`, context);
9418
+ const propsDescription = Object.entries(contents).map(([k2, v2]) => `${k2}=${v2}`).join(", ");
9419
+ logger[logMethod](`[Telemetry] ${event} [${propsDescription}]`);
9419
9420
  trackEvent(event, level, context);
9420
9421
  }
9421
9422
  const _AnimationPlayer = class _AnimationPlayer {
@@ -9508,7 +9509,7 @@ const _AnimationPlayer = class _AnimationPlayer {
9508
9509
  if (this.streamingPlayer) {
9509
9510
  return;
9510
9511
  }
9511
- const { StreamingAudioPlayer } = await import("./StreamingAudioPlayer-tmb18x3O.js");
9512
+ const { StreamingAudioPlayer } = await import("./StreamingAudioPlayer-CCmsLyxv.js");
9512
9513
  const { AvatarSDK: AvatarSDK2 } = await Promise.resolve().then(() => AvatarSDK$1);
9513
9514
  const audioFormat = AvatarSDK2.getAudioFormat();
9514
9515
  this.streamingPlayer = new StreamingAudioPlayer({
@@ -9521,8 +9522,7 @@ const _AnimationPlayer = class _AnimationPlayer {
9521
9522
  } catch (error) {
9522
9523
  const message = error instanceof Error ? error.message : String(error);
9523
9524
  logger.error("[AnimationPlayer] Failed to initialize streaming player:", message);
9524
- logEvent("character_player", "error", {
9525
- event: "streaming_player_initialize_failed",
9525
+ logEvent("streaming_player_initialize_failed", "error", {
9526
9526
  reason: message
9527
9527
  });
9528
9528
  throw error;
@@ -11548,7 +11548,7 @@ class AvatarSDK {
11548
11548
  __publicField(AvatarSDK, "_initializationState", "uninitialized");
11549
11549
  __publicField(AvatarSDK, "_initializingPromise", null);
11550
11550
  __publicField(AvatarSDK, "_configuration", null);
11551
- __publicField(AvatarSDK, "_version", "1.0.0-beta.102");
11551
+ __publicField(AvatarSDK, "_version", "1.0.0-beta.104");
11552
11552
  __publicField(AvatarSDK, "_avatarCore", null);
11553
11553
  __publicField(AvatarSDK, "_dynamicSdkConfig", null);
11554
11554
  __publicField(AvatarSDK, "_cachedDeviceScore", null);
@@ -13450,9 +13450,8 @@ class AvatarController {
13450
13450
  volume = Math.max(0, Math.min(1, volume));
13451
13451
  }
13452
13452
  (_a = this.animationPlayer) == null ? void 0 : _a.setVolume(volume);
13453
- logEvent("character_player", "info", {
13453
+ logEvent("volume_changed", "info", {
13454
13454
  avatar_id: this.avatar.id,
13455
- event: "volume_changed",
13456
13455
  volume
13457
13456
  });
13458
13457
  }
@@ -13515,8 +13514,7 @@ class AvatarController {
13515
13514
  this.emit("stopRendering");
13516
13515
  if (this.frameStarvationEvents.length > 0) {
13517
13516
  const hasReqEnd = this.frameStarvationEvents.some((e2) => e2.reqEnd);
13518
- logEvent("character_player", "warning", {
13519
- event: "frame_starvation",
13517
+ logEvent("frame_starvation", "warning", {
13520
13518
  avatar_id: this.avatar.id,
13521
13519
  conversationId: ((_a2 = this.networkLayer) == null ? void 0 : _a2.getCurrentConversationId()) || void 0,
13522
13520
  starvation_count: this.frameStarvationEvents.length,
@@ -13526,9 +13524,8 @@ class AvatarController {
13526
13524
  }
13527
13525
  this.frameStarvationEvents = [];
13528
13526
  this.isFrameStarved = false;
13529
- logEvent("character_player", "info", {
13527
+ logEvent("playback_ended", "info", {
13530
13528
  avatar_id: this.avatar.id,
13531
- event: "playback_ended",
13532
13529
  conversationId: ((_b2 = this.networkLayer) == null ? void 0 : _b2.getCurrentConversationId()) || void 0
13533
13530
  });
13534
13531
  this.clearPlaybackData();
@@ -13554,9 +13551,8 @@ class AvatarController {
13554
13551
  this.notifyConversationState(AvatarState.playing);
13555
13552
  this.startPlaybackLoop();
13556
13553
  this.isStartingPlayback = false;
13557
- logEvent("character_player", "info", {
13554
+ logEvent("playback_started", "info", {
13558
13555
  avatar_id: this.avatar.id,
13559
- event: "playback_started",
13560
13556
  conversationId: ((_a = this.networkLayer) == null ? void 0 : _a.getCurrentConversationId()) || void 0
13561
13557
  });
13562
13558
  } catch (error) {
@@ -13617,8 +13613,7 @@ class AvatarController {
13617
13613
  const shouldReport = state.audioTimeZeroCount > this.MAX_AUDIO_TIME_ZERO_COUNT || state.audioTimeStuckCount > this.MAX_AUDIO_TIME_STUCK_COUNT || hasScheduledButNoActive && this.isPlaying;
13618
13614
  if (shouldReport && isNotPaused) {
13619
13615
  state.reported = true;
13620
- logEvent("character_player", "error", {
13621
- event: "playback_stuck_after_transition",
13616
+ logEvent("playback_stuck_after_transition", "error", {
13622
13617
  avatar_id: this.avatar.id,
13623
13618
  conversationId: ((_e2 = this.networkLayer) == null ? void 0 : _e2.getCurrentConversationId()) || void 0,
13624
13619
  // 诊断信息(包含 audioContextState 用于诊断,但不作为触发条件)
@@ -13863,9 +13858,8 @@ class AvatarController {
13863
13858
  this.isFallbackMode = false;
13864
13859
  this.clearPlaybackData();
13865
13860
  this.resetConversationIdState();
13866
- logEvent("character_player", "info", {
13861
+ logEvent("audio_only_playback_ended", "info", {
13867
13862
  avatar_id: this.avatar.id,
13868
- event: "audio_only_playback_ended",
13869
13863
  conversationId: this.getEffectiveConversationId() || void 0
13870
13864
  });
13871
13865
  });
@@ -13881,9 +13875,8 @@ class AvatarController {
13881
13875
  this.currentState = AvatarState.playing;
13882
13876
  this.notifyConversationState(AvatarState.playing, true);
13883
13877
  this.startAudioMonitoringLoop();
13884
- logEvent("character_player", "info", {
13878
+ logEvent("audio_only_playback_started", "info", {
13885
13879
  avatar_id: this.avatar.id,
13886
- event: "audio_only_playback_started",
13887
13880
  conversationId: this.getEffectiveConversationId() || void 0
13888
13881
  });
13889
13882
  } catch (error) {
@@ -17954,9 +17947,9 @@ class AvatarView {
17954
17947
  }
17955
17948
  /**
17956
17949
  * Render specified keyframe (pure rendering mode, no audio-animation synchronization)
17957
- * Suitable for scenarios where external application controls audio playback and animation playback
17958
17950
  * @param keyframeData - Keyframe data
17959
- * @param enableIdleRendering - Whether to enable idle loop rendering. true: Enable idle rendering and return immediately (skip this keyframe); false: Disable idle rendering and process keyframe (default)
17951
+ * @param enableIdleRendering - Whether to enable idle loop rendering
17952
+ * @internal
17960
17953
  */
17961
17954
  async renderFlame(keyframeData, enableIdleRendering) {
17962
17955
  if (!this.isInitialized || !this.renderSystem) {
@@ -17987,6 +17980,7 @@ class AvatarView {
17987
17980
  throw error;
17988
17981
  }
17989
17982
  }
17983
+ /** @internal */
17990
17984
  async generateTransition(options) {
17991
17985
  if (!this.isInitialized) {
17992
17986
  throw new Error("AvatarView not initialized");
@@ -18098,6 +18092,30 @@ class AvatarView {
18098
18092
  startIdle() {
18099
18093
  this.renderFlame(void 0, true);
18100
18094
  }
18095
+ /**
18096
+ * Generate transition frames from protobuf data.
18097
+ *
18098
+ * Decodes the protobuf, extracts the target keyframe, and generates
18099
+ * transition frames from the current idle position to the target.
18100
+ * The caller is responsible for playing the returned frames at the desired cadence.
18101
+ *
18102
+ * @param data - Raw protobuf bytes containing the target frame
18103
+ * @param frameCount - Number of transition frames to generate
18104
+ * @param options - Additional options
18105
+ * @param options.useLinear - Use linear interpolation (default: true)
18106
+ * @returns Array of opaque keyframe data for sequential playback
18107
+ */
18108
+ async generateTransitionFromProtobuf(data, frameCount, options) {
18109
+ const keyframes = decodeAnimationKeyframes(data);
18110
+ if (!keyframes || keyframes.length === 0) {
18111
+ return [];
18112
+ }
18113
+ return this.generateTransition({
18114
+ to: keyframes[0],
18115
+ frameCount,
18116
+ useLinear: (options == null ? void 0 : options.useLinear) ?? true
18117
+ });
18118
+ }
18101
18119
  /**
18102
18120
  * Cancel any in-progress frame sequence playback.
18103
18121
  * Called by renderFromProtobuf when streaming frames arrive during transition.
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-DNq7oTVY.js";
1
+ import { b, c, m, f, d, j, g, C, i, D, E, k, h, L, R, n } from "./index-BFNu-mKX.js";
2
2
  export {
3
3
  b as Avatar,
4
4
  c as AvatarController,
@@ -119,26 +119,6 @@ export interface CameraConfig {
119
119
  up?: [number, number, number];
120
120
  aspect?: number;
121
121
  }
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
122
  /**
143
123
  * Post-processing parameter configuration
144
124
  * Used to overlay in real-time on animation parameters returned by the server
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.102",
4
+ "version": "1.0.0-beta.104",
5
5
  "packageManager": "pnpm@10.18.2",
6
6
  "description": "AvatarKit SDK - 3D Gaussian Splatting Avatar Rendering SDK",
7
7
  "author": "AvatarKit Team",