@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 +12 -0
- package/dist/{StreamingAudioPlayer-tmb18x3O.js → StreamingAudioPlayer-CCmsLyxv.js} +6 -10
- package/dist/core/AvatarView.d.ts +17 -14
- package/dist/{index-DNq7oTVY.js → index-BFNu-mKX.js} +39 -21
- package/dist/index.js +1 -1
- package/dist/types/index.d.ts +0 -20
- package/package.json +1 -1
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-
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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
|
|
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
|
-
|
|
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-
|
|
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("
|
|
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.
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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
|
|
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
package/dist/types/index.d.ts
CHANGED
|
@@ -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