@spatialwalk/avatarkit 1.0.0-beta.13 → 1.0.0-beta.15
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 +38 -0
- package/README.md +13 -3
- package/dist/{StreamingAudioPlayer-CsVJinsO.js → StreamingAudioPlayer-Dj1w6HZz.js} +57 -41
- package/dist/StreamingAudioPlayer-Dj1w6HZz.js.map +1 -0
- package/dist/animation/AnimationWebSocketClient.d.ts +2 -0
- package/dist/animation/AnimationWebSocketClient.d.ts.map +1 -1
- package/dist/audio/AnimationPlayer.d.ts +8 -0
- package/dist/audio/AnimationPlayer.d.ts.map +1 -1
- package/dist/audio/StreamingAudioPlayer.d.ts +1 -0
- package/dist/audio/StreamingAudioPlayer.d.ts.map +1 -1
- package/dist/avatar_core_wasm-D-1WNg4B.js +1676 -0
- package/dist/avatar_core_wasm-D-1WNg4B.js.map +1 -0
- package/dist/avatar_core_wasm.wasm +0 -0
- package/dist/core/AvatarController.d.ts +31 -20
- package/dist/core/AvatarController.d.ts.map +1 -1
- package/dist/core/AvatarDownloader.d.ts.map +1 -1
- package/dist/core/AvatarView.d.ts.map +1 -1
- package/dist/{index-Cy9jPcQt.js → index-Bh6KkhoR.js} +636 -583
- package/dist/index-Bh6KkhoR.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/vanilla/vite.config.d.ts +3 -0
- package/dist/vanilla/vite.config.d.ts.map +1 -0
- package/package.json +12 -11
- package/dist/StreamingAudioPlayer-CsVJinsO.js.map +0 -1
- package/dist/avatar_core_wasm-D4eEi7Eh.js +0 -1666
- package/dist/avatar_core_wasm-D4eEi7Eh.js.map +0 -1
- package/dist/index-Cy9jPcQt.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,44 @@ 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.15] - 2025-01-20
|
|
9
|
+
|
|
10
|
+
### ✨ New Features
|
|
11
|
+
- Added authentication support for API requests
|
|
12
|
+
- `appId` is now automatically included in HTTP headers (`X-App-Id`) and WebSocket URL query parameters
|
|
13
|
+
- `sessionToken` is now automatically included in HTTP headers (`Authorization: Bearer {token}`) and WebSocket URL query parameters
|
|
14
|
+
- All network requests (character loading, resource downloads, WebSocket connections) now include authentication credentials
|
|
15
|
+
|
|
16
|
+
### 🔧 Improvements
|
|
17
|
+
- Fixed canvas resize handling for different aspect ratios
|
|
18
|
+
- Projection matrix is now correctly updated when canvas aspect ratio changes
|
|
19
|
+
- Rendering system properly handles portrait (9:16) and landscape (16:9) aspect ratios
|
|
20
|
+
- Canvas automatically adapts to container size changes via ResizeObserver
|
|
21
|
+
|
|
22
|
+
### 🐛 Bug Fixes
|
|
23
|
+
- Fixed `RenderSystem.handleResize()` to update projection matrix when canvas size changes
|
|
24
|
+
- Previously only updated aspect ratio, now also updates projection matrix for correct rendering
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## [1.0.0-beta.14] - 2025-11-18
|
|
29
|
+
|
|
30
|
+
### ✨ New Features
|
|
31
|
+
- Added pause and resume functionality for avatar playback
|
|
32
|
+
- New `pause()` method to pause audio and animation playback
|
|
33
|
+
- New `resume()` method to resume playback from paused state
|
|
34
|
+
- Added `paused` state to `AvatarState` enum
|
|
35
|
+
- State changes are communicated via `onAvatarState` callback
|
|
36
|
+
- Works in both network mode and external data mode
|
|
37
|
+
|
|
38
|
+
### 🔧 Improvements
|
|
39
|
+
- Canvas now uses container's full dimensions instead of fixed 1:1 aspect ratio
|
|
40
|
+
- Canvas automatically adapts to container size (width and height)
|
|
41
|
+
- External developers can control canvas aspect ratio by setting container dimensions
|
|
42
|
+
- Rendering system correctly handles any aspect ratio without distortion
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
8
46
|
## [1.0.0-beta.13] - 2025-11-17
|
|
9
47
|
|
|
10
48
|
### 🔒 API Improvements
|
package/README.md
CHANGED
|
@@ -362,6 +362,12 @@ avatarView.avatarController.sendKeyframes(
|
|
|
362
362
|
#### Common Methods (Both Modes)
|
|
363
363
|
|
|
364
364
|
```typescript
|
|
365
|
+
// Pause playback (can be resumed later)
|
|
366
|
+
avatarView.avatarController.pause()
|
|
367
|
+
|
|
368
|
+
// Resume playback (from paused state)
|
|
369
|
+
await avatarView.avatarController.resume()
|
|
370
|
+
|
|
365
371
|
// Interrupt current playback (stops and clears data)
|
|
366
372
|
avatarView.avatarController.interrupt()
|
|
367
373
|
|
|
@@ -377,7 +383,7 @@ avatarView.avatarController.onError = (error: Error) => {}
|
|
|
377
383
|
**Important Notes:**
|
|
378
384
|
- `start()` and `close()` are only available in network mode
|
|
379
385
|
- `play()`, `sendAudioChunk()`, and `sendKeyframes()` are only available in external data mode
|
|
380
|
-
- `
|
|
386
|
+
- `pause()`, `resume()`, `interrupt()`, and `clear()` are available in both modes
|
|
381
387
|
- The playback mode is determined when creating `AvatarView` and cannot be changed
|
|
382
388
|
|
|
383
389
|
## 🔧 Configuration
|
|
@@ -416,6 +422,9 @@ interface AvatarViewOptions {
|
|
|
416
422
|
- `'network'`: SDK handles WebSocket communication, send audio via `send()`
|
|
417
423
|
- `'external'`: External components provide audio and animation data, SDK handles synchronized playback
|
|
418
424
|
- `container`: Optional container element for Canvas, if not provided, Canvas will be created but not added to DOM
|
|
425
|
+
- Canvas automatically uses the container's full dimensions (width and height)
|
|
426
|
+
- Canvas aspect ratio adapts to container size - set container dimensions to control the aspect ratio
|
|
427
|
+
- SDK automatically handles resize events via ResizeObserver
|
|
419
428
|
|
|
420
429
|
```typescript
|
|
421
430
|
enum AvatarPlaybackMode {
|
|
@@ -457,7 +466,8 @@ enum ConnectionState {
|
|
|
457
466
|
enum AvatarState {
|
|
458
467
|
idle = 'idle', // Idle state, showing breathing animation
|
|
459
468
|
active = 'active', // Active, waiting for playable content
|
|
460
|
-
playing = 'playing' // Playing
|
|
469
|
+
playing = 'playing', // Playing
|
|
470
|
+
paused = 'paused' // Paused (can be resumed)
|
|
461
471
|
}
|
|
462
472
|
```
|
|
463
473
|
|
|
@@ -620,5 +630,5 @@ Issues and Pull Requests are welcome!
|
|
|
620
630
|
|
|
621
631
|
For questions, please contact:
|
|
622
632
|
- Email: support@spavatar.com
|
|
623
|
-
- Documentation: https://docs.
|
|
633
|
+
- Documentation: https://docs.spatialreal.ai
|
|
624
634
|
- GitHub: https://github.com/spavatar/sdk
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var i = (h, t, e) =>
|
|
4
|
-
import { A as
|
|
5
|
-
class
|
|
1
|
+
var C = Object.defineProperty;
|
|
2
|
+
var g = (h, t, e) => t in h ? C(h, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : h[t] = e;
|
|
3
|
+
var i = (h, t, e) => g(h, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
+
import { A as m, e as f, a as c, l as u } from "./index-Bh6KkhoR.js";
|
|
5
|
+
class y {
|
|
6
6
|
constructor(t) {
|
|
7
7
|
// AudioContext is managed internally
|
|
8
8
|
i(this, "audioContext", null);
|
|
@@ -17,6 +17,8 @@ class A {
|
|
|
17
17
|
// Accumulated paused time
|
|
18
18
|
i(this, "pausedAt", 0);
|
|
19
19
|
// Time when paused
|
|
20
|
+
i(this, "pausedAudioContextTime", 0);
|
|
21
|
+
// audioContext.currentTime when paused (for resume calculation)
|
|
20
22
|
i(this, "scheduledTime", 0);
|
|
21
23
|
// Next chunk schedule time in AudioContext time
|
|
22
24
|
// Playback state
|
|
@@ -31,7 +33,7 @@ class A {
|
|
|
31
33
|
i(this, "activeSources", []);
|
|
32
34
|
// Event callbacks
|
|
33
35
|
i(this, "onEndedCallback");
|
|
34
|
-
this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, this.sampleRate = (t == null ? void 0 : t.sampleRate) ??
|
|
36
|
+
this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, this.sampleRate = (t == null ? void 0 : t.sampleRate) ?? m.audio.sampleRate, this.channelCount = (t == null ? void 0 : t.channelCount) ?? 1, this.debug = (t == null ? void 0 : t.debug) ?? !1;
|
|
35
37
|
}
|
|
36
38
|
/**
|
|
37
39
|
* Initialize audio context (create and ensure it's ready)
|
|
@@ -47,11 +49,11 @@ class A {
|
|
|
47
49
|
state: this.audioContext.state
|
|
48
50
|
});
|
|
49
51
|
} catch (t) {
|
|
50
|
-
const e =
|
|
52
|
+
const e = f(t);
|
|
51
53
|
throw c.logEvent("activeAudioSessionFailed", "warning", {
|
|
52
54
|
sessionId: this.sessionId,
|
|
53
55
|
reason: e
|
|
54
|
-
}),
|
|
56
|
+
}), u.error("Failed to initialize AudioContext:", e), t instanceof Error ? t : new Error(e);
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
/**
|
|
@@ -59,7 +61,7 @@ class A {
|
|
|
59
61
|
*/
|
|
60
62
|
addChunk(t, e = !1) {
|
|
61
63
|
if (!this.audioContext) {
|
|
62
|
-
|
|
64
|
+
u.error("AudioContext not initialized");
|
|
63
65
|
return;
|
|
64
66
|
}
|
|
65
67
|
this.audioChunks.push({ data: t, isLast: e }), this.log(`Added chunk ${this.audioChunks.length}`, {
|
|
@@ -68,13 +70,13 @@ class A {
|
|
|
68
70
|
isLast: e,
|
|
69
71
|
isPlaying: this.isPlaying,
|
|
70
72
|
scheduledChunks: this.scheduledChunks
|
|
71
|
-
}), !this.isPlaying && this.autoStartEnabled && this.audioChunks.length > 0 ? (this.log("[StreamingAudioPlayer] Auto-starting playback from addChunk"), this.startPlayback()) : this.isPlaying ? (this.log("[StreamingAudioPlayer] Already playing, scheduling next chunk"), this.scheduleNextChunk()) : this.log("[StreamingAudioPlayer] Not playing and no chunks, waiting for more chunks");
|
|
73
|
+
}), !this.isPlaying && this.autoStartEnabled && this.audioChunks.length > 0 ? (this.log("[StreamingAudioPlayer] Auto-starting playback from addChunk"), this.startPlayback()) : this.isPlaying && !this.isPaused ? (this.log("[StreamingAudioPlayer] Already playing, scheduling next chunk"), this.scheduleNextChunk()) : this.log("[StreamingAudioPlayer] Not playing and no chunks, waiting for more chunks");
|
|
72
74
|
}
|
|
73
75
|
/**
|
|
74
76
|
* Start new session (stop current and start fresh)
|
|
75
77
|
*/
|
|
76
78
|
async startNewSession(t) {
|
|
77
|
-
this.stop(), this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, this.audioChunks = [], this.scheduledChunks = 0, this.pausedTimeOffset = 0, this.pausedAt = 0, this.log("Starting new session", {
|
|
79
|
+
this.stop(), this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, this.audioChunks = [], this.scheduledChunks = 0, this.pausedTimeOffset = 0, this.pausedAt = 0, this.pausedAudioContextTime = 0, this.log("Starting new session", {
|
|
78
80
|
chunks: t.length
|
|
79
81
|
});
|
|
80
82
|
for (const e of t)
|
|
@@ -114,8 +116,8 @@ class A {
|
|
|
114
116
|
this.log("[StreamingAudioPlayer] Cannot schedule chunk: AudioContext not initialized");
|
|
115
117
|
return;
|
|
116
118
|
}
|
|
117
|
-
if (!this.isPlaying) {
|
|
118
|
-
this.log("[StreamingAudioPlayer] Cannot schedule chunk: Not playing");
|
|
119
|
+
if (!this.isPlaying || this.isPaused) {
|
|
120
|
+
this.log("[StreamingAudioPlayer] Cannot schedule chunk: Not playing or paused");
|
|
119
121
|
return;
|
|
120
122
|
}
|
|
121
123
|
const t = this.scheduledChunks;
|
|
@@ -128,9 +130,9 @@ class A {
|
|
|
128
130
|
this.scheduledChunks++;
|
|
129
131
|
return;
|
|
130
132
|
}
|
|
131
|
-
const l = e.data,
|
|
133
|
+
const l = e.data, d = e.isLast, a = this.pcmToAudioBuffer(l);
|
|
132
134
|
if (!a) {
|
|
133
|
-
|
|
135
|
+
u.error("Failed to create AudioBuffer from PCM data"), c.logEvent("character_player", "error", {
|
|
134
136
|
sessionId: this.sessionId,
|
|
135
137
|
event: "audio_buffer_creation_failed"
|
|
136
138
|
});
|
|
@@ -139,17 +141,17 @@ class A {
|
|
|
139
141
|
try {
|
|
140
142
|
const s = this.audioContext.createBufferSource();
|
|
141
143
|
s.buffer = a, s.connect(this.audioContext.destination), s.start(this.scheduledTime), this.activeSources.push(s), s.onended = () => {
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
+
const o = this.activeSources.indexOf(s);
|
|
145
|
+
o >= 0 && this.activeSources.splice(o, 1), d && this.activeSources.length === 0 && (this.log("Last audio chunk ended, marking playback as ended"), this.markEnded());
|
|
144
146
|
}, this.scheduledTime += a.duration, this.scheduledChunks++, this.log(`[StreamingAudioPlayer] Scheduled chunk ${t + 1}/${this.audioChunks.length}`, {
|
|
145
147
|
startTime: this.scheduledTime - a.duration,
|
|
146
148
|
duration: a.duration,
|
|
147
149
|
nextScheduleTime: this.scheduledTime,
|
|
148
|
-
isLast:
|
|
150
|
+
isLast: d,
|
|
149
151
|
activeSources: this.activeSources.length
|
|
150
152
|
});
|
|
151
153
|
} catch (s) {
|
|
152
|
-
|
|
154
|
+
u.errorWithError("Failed to schedule audio chunk:", s), c.logEvent("character_player", "error", {
|
|
153
155
|
sessionId: this.sessionId,
|
|
154
156
|
event: "schedule_chunk_failed",
|
|
155
157
|
reason: s instanceof Error ? s.message : String(s)
|
|
@@ -164,25 +166,25 @@ class A {
|
|
|
164
166
|
if (!this.audioContext)
|
|
165
167
|
return null;
|
|
166
168
|
if (t.length === 0) {
|
|
167
|
-
const
|
|
169
|
+
const o = Math.floor(this.sampleRate * 0.01), n = this.audioContext.createBuffer(
|
|
168
170
|
this.channelCount,
|
|
169
|
-
|
|
171
|
+
o,
|
|
170
172
|
this.sampleRate
|
|
171
173
|
);
|
|
172
|
-
for (let
|
|
173
|
-
n.getChannelData(
|
|
174
|
+
for (let r = 0; r < this.channelCount; r++)
|
|
175
|
+
n.getChannelData(r).fill(0);
|
|
174
176
|
return n;
|
|
175
177
|
}
|
|
176
|
-
const e = new Uint8Array(t), l = new Int16Array(e.buffer, 0, e.length / 2),
|
|
178
|
+
const e = new Uint8Array(t), l = new Int16Array(e.buffer, 0, e.length / 2), d = l.length / this.channelCount, a = this.audioContext.createBuffer(
|
|
177
179
|
this.channelCount,
|
|
178
|
-
|
|
180
|
+
d,
|
|
179
181
|
this.sampleRate
|
|
180
182
|
);
|
|
181
183
|
for (let s = 0; s < this.channelCount; s++) {
|
|
182
|
-
const
|
|
183
|
-
for (let n = 0; n <
|
|
184
|
-
const
|
|
185
|
-
|
|
184
|
+
const o = a.getChannelData(s);
|
|
185
|
+
for (let n = 0; n < d; n++) {
|
|
186
|
+
const r = n * this.channelCount + s;
|
|
187
|
+
o[n] = l[r] / 32768;
|
|
186
188
|
}
|
|
187
189
|
}
|
|
188
190
|
return a;
|
|
@@ -202,20 +204,33 @@ class A {
|
|
|
202
204
|
* Pause playback
|
|
203
205
|
*/
|
|
204
206
|
pause() {
|
|
205
|
-
!this.isPlaying || this.isPaused || (this.isPaused = !0, this.
|
|
206
|
-
|
|
207
|
+
!this.isPlaying || this.isPaused || !this.audioContext || (this.pausedAt = this.getCurrentTime(), this.pausedAudioContextTime = this.audioContext.currentTime, this.isPaused = !0, this.audioContext.state === "running" && this.audioContext.suspend().catch((t) => {
|
|
208
|
+
u.errorWithError("Failed to suspend AudioContext:", t), this.isPaused = !1;
|
|
209
|
+
}), this.log("Playback paused", {
|
|
210
|
+
pausedAt: this.pausedAt,
|
|
211
|
+
pausedAudioContextTime: this.pausedAudioContextTime,
|
|
212
|
+
audioContextState: this.audioContext.state
|
|
207
213
|
}));
|
|
208
214
|
}
|
|
209
215
|
/**
|
|
210
216
|
* Resume playback
|
|
211
217
|
*/
|
|
212
218
|
async resume() {
|
|
213
|
-
if (!this.isPaused || !this.audioContext)
|
|
219
|
+
if (!this.isPaused || !this.audioContext || !this.isPlaying)
|
|
214
220
|
return;
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
221
|
+
if (this.audioContext.state === "suspended")
|
|
222
|
+
try {
|
|
223
|
+
await this.audioContext.resume();
|
|
224
|
+
} catch (e) {
|
|
225
|
+
throw u.errorWithError("Failed to resume AudioContext:", e), e;
|
|
226
|
+
}
|
|
227
|
+
const t = this.audioContext.currentTime;
|
|
228
|
+
this.sessionStartTime = this.pausedAudioContextTime - this.pausedAt - this.pausedTimeOffset, this.isPaused = !1, this.scheduledChunks < this.audioChunks.length && this.scheduleAllChunks(), this.log("Playback resumed", {
|
|
229
|
+
pausedAt: this.pausedAt,
|
|
230
|
+
pausedAudioContextTime: this.pausedAudioContextTime,
|
|
231
|
+
currentAudioContextTime: t,
|
|
232
|
+
adjustedSessionStartTime: this.sessionStartTime,
|
|
233
|
+
audioContextState: this.audioContext.state
|
|
219
234
|
});
|
|
220
235
|
}
|
|
221
236
|
/**
|
|
@@ -223,7 +238,8 @@ class A {
|
|
|
223
238
|
*/
|
|
224
239
|
stop() {
|
|
225
240
|
if (this.audioContext) {
|
|
226
|
-
this.
|
|
241
|
+
this.isPaused && this.audioContext.state === "suspended" && (this.audioContext.resume().catch(() => {
|
|
242
|
+
}), this.isPaused = !1), this.isPlaying = !1, this.isPaused = !1, this.sessionStartTime = 0, this.scheduledTime = 0;
|
|
227
243
|
for (const t of this.activeSources) {
|
|
228
244
|
t.onended = null;
|
|
229
245
|
try {
|
|
@@ -292,7 +308,7 @@ class A {
|
|
|
292
308
|
* Dispose and cleanup
|
|
293
309
|
*/
|
|
294
310
|
dispose() {
|
|
295
|
-
this.stop(), this.audioContext && (this.audioContext.close(), this.audioContext = null), this.audioChunks = [], this.scheduledChunks = 0, this.sessionStartTime = 0, this.pausedTimeOffset = 0, this.pausedAt = 0, this.scheduledTime = 0, this.onEndedCallback = void 0, this.log("StreamingAudioPlayer disposed");
|
|
311
|
+
this.stop(), this.audioContext && (this.audioContext.close(), this.audioContext = null), this.audioChunks = [], this.scheduledChunks = 0, this.sessionStartTime = 0, this.pausedTimeOffset = 0, this.pausedAt = 0, this.pausedAudioContextTime = 0, this.scheduledTime = 0, this.onEndedCallback = void 0, this.log("StreamingAudioPlayer disposed");
|
|
296
312
|
}
|
|
297
313
|
/**
|
|
298
314
|
* Flush buffered audio
|
|
@@ -310,10 +326,10 @@ class A {
|
|
|
310
326
|
* Debug logging
|
|
311
327
|
*/
|
|
312
328
|
log(t, e) {
|
|
313
|
-
this.debug &&
|
|
329
|
+
this.debug && u.log(`[StreamingAudioPlayer] ${t}`, e || "");
|
|
314
330
|
}
|
|
315
331
|
}
|
|
316
332
|
export {
|
|
317
|
-
|
|
333
|
+
y as StreamingAudioPlayer
|
|
318
334
|
};
|
|
319
|
-
//# sourceMappingURL=StreamingAudioPlayer-
|
|
335
|
+
//# sourceMappingURL=StreamingAudioPlayer-Dj1w6HZz.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamingAudioPlayer-Dj1w6HZz.js","sources":["../audio/StreamingAudioPlayer.ts"],"sourcesContent":["/**\n * Streaming Audio Player\n * Implements real-time audio playback using Web Audio API\n * Supports dynamic PCM chunk addition without Workers\n */\n\nimport { APP_CONFIG } from '../config/app-config'\nimport { AvatarKit } from '../core/AvatarKit'\nimport { errorToMessage } from '../utils/error-utils'\nimport { logger } from '../utils/logger'\n\nexport interface StreamingAudioPlayerOptions {\n sampleRate?: number // PCM sample rate (default: APP_CONFIG.audio.sampleRate, backend requires 16kHz)\n channelCount?: number // Number of channels (default: 1)\n debug?: boolean\n}\n\nexport class StreamingAudioPlayer {\n // AudioContext is managed internally\n private audioContext: AudioContext | null = null\n private sampleRate: number\n private channelCount: number\n private debug: boolean\n\n // Session-level state\n private sessionId: string\n private sessionStartTime = 0 // AudioContext time when session started\n private pausedTimeOffset = 0 // Accumulated paused time\n private pausedAt = 0 // Time when paused\n private pausedAudioContextTime = 0 // audioContext.currentTime when paused (for resume calculation)\n private scheduledTime = 0 // Next chunk schedule time in AudioContext time\n\n // Playback state\n private isPlaying = false\n private isPaused = false\n private autoStartEnabled = true // Control whether to auto-start when buffer is ready\n\n // Audio buffer queue\n private audioChunks: Array<{ data: Uint8Array, isLast: boolean }> = []\n private scheduledChunks = 0 // Number of chunks already scheduled\n private activeSources: AudioBufferSourceNode[] = []\n\n // Event callbacks\n private onEndedCallback?: () => void\n\n constructor(options?: StreamingAudioPlayerOptions) {\n this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`\n this.sampleRate = options?.sampleRate ?? APP_CONFIG.audio.sampleRate\n this.channelCount = options?.channelCount ?? 1\n this.debug = options?.debug ?? false\n }\n\n /**\n * Initialize audio context (create and ensure it's ready)\n */\n async initialize(): Promise<void> {\n if (this.audioContext) {\n return\n }\n\n try {\n // Create AudioContext\n this.audioContext = new AudioContext({\n sampleRate: this.sampleRate,\n })\n\n // Resume context (required for some browsers)\n if (this.audioContext.state === 'suspended') {\n await this.audioContext.resume()\n }\n\n this.log('AudioContext initialized', {\n sessionId: this.sessionId,\n sampleRate: this.audioContext.sampleRate,\n state: this.audioContext.state,\n })\n }\n catch (error) {\n const message = errorToMessage(error)\n AvatarKit.logEvent('activeAudioSessionFailed', 'warning', {\n sessionId: this.sessionId,\n reason: message,\n })\n logger.error('Failed to initialize AudioContext:', message)\n throw error instanceof Error ? error : new Error(message)\n }\n }\n\n /**\n * Add audio chunk (16-bit PCM)\n */\n addChunk(pcmData: Uint8Array, isLast: boolean = false): void {\n if (!this.audioContext) {\n logger.error('AudioContext not initialized')\n return\n }\n\n // Store chunk with metadata\n this.audioChunks.push({ data: pcmData, isLast })\n\n // Track buffer underrun warning\n if (this.isPlaying && this.audioChunks.length === this.scheduledChunks) {\n // Buffer underrun detected - chunks consumed faster than added\n }\n\n this.log(`Added chunk ${this.audioChunks.length}`, {\n size: pcmData.length,\n totalChunks: this.audioChunks.length,\n isLast,\n isPlaying: this.isPlaying,\n scheduledChunks: this.scheduledChunks,\n })\n\n // Auto-start if we have any audio chunks and auto-start is enabled\n if (!this.isPlaying && this.autoStartEnabled && this.audioChunks.length > 0) {\n this.log('[StreamingAudioPlayer] Auto-starting playback from addChunk')\n this.startPlayback()\n }\n // Schedule next chunk if already playing and not paused\n else if (this.isPlaying && !this.isPaused) {\n this.log('[StreamingAudioPlayer] Already playing, scheduling next chunk')\n this.scheduleNextChunk()\n } else {\n this.log('[StreamingAudioPlayer] Not playing and no chunks, waiting for more chunks')\n }\n }\n\n /**\n * Start new session (stop current and start fresh)\n */\n async startNewSession(audioChunks: Array<{ data: Uint8Array, isLast: boolean }>): Promise<void> {\n // Stop current session if playing\n this.stop()\n\n // Generate new session ID to prevent data mixing\n this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`\n\n // Reset session state\n this.audioChunks = []\n this.scheduledChunks = 0\n this.pausedTimeOffset = 0\n this.pausedAt = 0\n this.pausedAudioContextTime = 0\n // Don't set sessionStartTime or scheduledTime here - let startPlayback() set them\n this.log('Starting new session', {\n chunks: audioChunks.length,\n })\n\n // Add audio chunks with their metadata\n for (const chunk of audioChunks) {\n this.addChunk(chunk.data, chunk.isLast)\n }\n }\n\n /**\n * Start playback\n */\n private startPlayback(): void {\n if (!this.audioContext) {\n this.log('[StreamingAudioPlayer] Cannot start playback: AudioContext not initialized')\n return\n }\n if (this.isPlaying) {\n this.log('[StreamingAudioPlayer] Cannot start playback: Already playing')\n return\n }\n\n this.isPlaying = true\n this.sessionStartTime = this.audioContext.currentTime\n this.scheduledTime = this.sessionStartTime\n\n this.log('[StreamingAudioPlayer] Starting playback', {\n sessionStartTime: this.sessionStartTime,\n bufferedChunks: this.audioChunks.length,\n scheduledChunks: this.scheduledChunks,\n activeSources: this.activeSources.length,\n })\n\n // Schedule all available chunks\n this.scheduleAllChunks()\n }\n\n /**\n * Schedule all pending chunks\n */\n private scheduleAllChunks(): void {\n while (this.scheduledChunks < this.audioChunks.length) {\n this.scheduleNextChunk()\n }\n }\n\n /**\n * Schedule next audio chunk\n */\n private scheduleNextChunk(): void {\n if (!this.audioContext) {\n this.log('[StreamingAudioPlayer] Cannot schedule chunk: AudioContext not initialized')\n return\n }\n if (!this.isPlaying || this.isPaused) {\n this.log('[StreamingAudioPlayer] Cannot schedule chunk: Not playing or paused')\n return\n }\n\n const chunkIndex = this.scheduledChunks\n if (chunkIndex >= this.audioChunks.length) {\n this.log(`[StreamingAudioPlayer] No more chunks to schedule (chunkIndex: ${chunkIndex}, totalChunks: ${this.audioChunks.length})`)\n return\n }\n\n const chunk = this.audioChunks[chunkIndex]\n\n // 当音频块为空且不是最后一个块时,跳过调度\n if (chunk.data.length === 0 && !chunk.isLast) {\n this.scheduledChunks++\n return\n }\n\n const pcmData = chunk.data\n const isLast = chunk.isLast\n const audioBuffer = this.pcmToAudioBuffer(pcmData)\n\n if (!audioBuffer) {\n const errorMessage = 'Failed to create AudioBuffer from PCM data'\n logger.error(errorMessage)\n AvatarKit.logEvent('character_player', 'error', {\n sessionId: this.sessionId,\n event: 'audio_buffer_creation_failed',\n })\n return\n }\n\n try {\n // Create and configure source node\n const source = this.audioContext.createBufferSource()\n source.buffer = audioBuffer\n source.connect(this.audioContext.destination)\n\n // Schedule playback\n source.start(this.scheduledTime)\n\n // Track active source for hard-cancel\n this.activeSources.push(source)\n source.onended = () => {\n // Remove from active list when it ends\n const idx = this.activeSources.indexOf(source)\n if (idx >= 0)\n this.activeSources.splice(idx, 1)\n\n // Check if this was the last chunk and all sources have ended\n if (isLast && this.activeSources.length === 0) {\n this.log('Last audio chunk ended, marking playback as ended')\n this.markEnded()\n }\n }\n\n // Update scheduled time for next chunk\n this.scheduledTime += audioBuffer.duration\n\n this.scheduledChunks++\n\n this.log(`[StreamingAudioPlayer] Scheduled chunk ${chunkIndex + 1}/${this.audioChunks.length}`, {\n startTime: this.scheduledTime - audioBuffer.duration,\n duration: audioBuffer.duration,\n nextScheduleTime: this.scheduledTime,\n isLast,\n activeSources: this.activeSources.length,\n })\n }\n catch (err) {\n logger.errorWithError('Failed to schedule audio chunk:', err)\n AvatarKit.logEvent('character_player', 'error', {\n sessionId: this.sessionId,\n event: 'schedule_chunk_failed',\n reason: err instanceof Error ? err.message : String(err),\n })\n }\n }\n\n /**\n * Convert PCM data to AudioBuffer\n * Input: 16-bit PCM (int16), Output: AudioBuffer (float32 [-1, 1])\n */\n private pcmToAudioBuffer(pcmData: Uint8Array): AudioBuffer | null {\n if (!this.audioContext) {\n return null\n }\n\n // Handle empty PCM data (e.g., when isLast is true)\n if (pcmData.length === 0) {\n // For empty chunks (typically the last chunk), create minimal silence\n // Use a very short duration to avoid playback stuttering\n const silenceDuration = 0.01 // 1ms - minimal silence to maintain timing\n const numSamples = Math.floor(this.sampleRate * silenceDuration)\n\n const audioBuffer = this.audioContext.createBuffer(\n this.channelCount,\n numSamples,\n this.sampleRate,\n )\n\n // Fill with silence (all zeros)\n for (let channel = 0; channel < this.channelCount; channel++) {\n const channelData = audioBuffer.getChannelData(channel)\n channelData.fill(0) // Fill with silence\n }\n\n return audioBuffer\n }\n\n // Create aligned copy to avoid byte offset issues\n // Int16Array requires byteOffset to be a multiple of 2\n const alignedData = new Uint8Array(pcmData)\n const int16Array = new Int16Array(alignedData.buffer, 0, alignedData.length / 2)\n\n // Calculate number of samples\n const numSamples = int16Array.length / this.channelCount\n\n // Create AudioBuffer\n const audioBuffer = this.audioContext.createBuffer(\n this.channelCount,\n numSamples,\n this.sampleRate,\n )\n\n // Convert int16 to float32 [-1, 1]\n for (let channel = 0; channel < this.channelCount; channel++) {\n const channelData = audioBuffer.getChannelData(channel)\n\n for (let i = 0; i < numSamples; i++) {\n const sampleIndex = i * this.channelCount + channel\n // Normalize int16 (-32768 to 32767) to float32 (-1 to 1)\n channelData[i] = int16Array[sampleIndex] / 32768.0\n }\n }\n\n return audioBuffer\n }\n\n /**\n * Get current playback time (seconds)\n */\n getCurrentTime(): number {\n if (!this.audioContext || !this.isPlaying) {\n return 0\n }\n\n if (this.isPaused) {\n return this.pausedAt\n }\n\n // Calculate elapsed time using session start time and paused offset\n const currentAudioTime = this.audioContext.currentTime\n const elapsed = currentAudioTime - this.sessionStartTime - this.pausedTimeOffset\n\n return Math.max(0, elapsed)\n }\n\n /**\n * Pause playback\n */\n pause(): void {\n if (!this.isPlaying || this.isPaused || !this.audioContext) {\n return\n }\n\n // 1. 记录逻辑时间(用于 getCurrentTime 返回固定值)\n this.pausedAt = this.getCurrentTime()\n\n // 2. 记录 AudioContext 时间戳(关键!用于恢复计算)\n this.pausedAudioContextTime = this.audioContext.currentTime\n\n // 3. 设置暂停标志\n this.isPaused = true\n\n // 4. 挂起 AudioContext 以暂停所有活动的音频源\n if (this.audioContext.state === 'running') {\n this.audioContext.suspend().catch((err) => {\n logger.errorWithError('Failed to suspend AudioContext:', err)\n // 如果挂起失败,恢复状态\n this.isPaused = false\n })\n }\n\n this.log('Playback paused', {\n pausedAt: this.pausedAt,\n pausedAudioContextTime: this.pausedAudioContextTime,\n audioContextState: this.audioContext.state,\n })\n }\n\n /**\n * Resume playback\n */\n async resume(): Promise<void> {\n if (!this.isPaused || !this.audioContext || !this.isPlaying) {\n return\n }\n\n // 1. 首先恢复 AudioContext(使 currentTime 继续)\n if (this.audioContext.state === 'suspended') {\n try {\n await this.audioContext.resume()\n }\n catch (err) {\n logger.errorWithError('Failed to resume AudioContext:', err)\n throw err\n }\n }\n\n // 2. 调整 sessionStartTime,使 getCurrentTime() 从 pausedAt 继续\n // 数学推导:\n // 恢复后,我们希望:getCurrentTime() = pausedAt + (currentAudioTime - pausedAudioContextTime)\n // 当前公式:getCurrentTime() = currentAudioTime - sessionStartTime - pausedTimeOffset\n //\n // 令两者相等:\n // pausedAt + (currentAudioTime - pausedAudioContextTime) = currentAudioTime - sessionStartTime - pausedTimeOffset\n // => sessionStartTime = pausedAudioContextTime - pausedAt - pausedTimeOffset\n const currentAudioTime = this.audioContext.currentTime\n this.sessionStartTime = this.pausedAudioContextTime - this.pausedAt - this.pausedTimeOffset\n\n // 3. 清除暂停标志\n this.isPaused = false\n\n // 4. 继续调度未调度的音频块(如果在暂停期间有新数据到达)\n if (this.scheduledChunks < this.audioChunks.length) {\n this.scheduleAllChunks()\n }\n\n this.log('Playback resumed', {\n pausedAt: this.pausedAt,\n pausedAudioContextTime: this.pausedAudioContextTime,\n currentAudioContextTime: currentAudioTime,\n adjustedSessionStartTime: this.sessionStartTime,\n audioContextState: this.audioContext.state,\n })\n }\n\n /**\n * Stop playback\n */\n stop(): void {\n if (!this.audioContext) {\n return\n }\n\n // 如果暂停,先恢复 AudioContext(以便正确停止源)\n if (this.isPaused && this.audioContext.state === 'suspended') {\n this.audioContext.resume().catch(() => {\n // 忽略恢复错误,因为我们要停止播放\n })\n this.isPaused = false\n }\n\n this.isPlaying = false\n this.isPaused = false\n this.sessionStartTime = 0 // Reset session start time\n this.scheduledTime = 0 // Reset scheduled time for next session\n\n // Hard stop all scheduled sources immediately\n for (const source of this.activeSources) {\n source.onended = null\n try {\n source.stop(0)\n }\n catch {}\n try {\n source.disconnect()\n }\n catch {}\n }\n this.activeSources = []\n\n // 清理音频块和调度状态,确保下次播放时状态干净\n this.audioChunks = []\n this.scheduledChunks = 0\n\n this.log('[StreamingAudioPlayer] Playback stopped, state reset')\n\n // Note: Individual source nodes will stop automatically\n // We just reset our state\n }\n\n /**\n * Enable or disable auto-start (for delayed start scenarios)\n */\n setAutoStart(enabled: boolean): void {\n this.autoStartEnabled = enabled\n this.log(`Auto-start ${enabled ? 'enabled' : 'disabled'}`)\n }\n\n /**\n * Start playback manually (for delayed start scenarios)\n * This allows starting playback after transition animation completes\n */\n play(): void {\n if (this.isPlaying) {\n return\n }\n // Enable auto-start when manually starting playback\n this.autoStartEnabled = true\n this.startPlayback()\n }\n\n /**\n * Mark playback as ended\n */\n markEnded(): void {\n this.log('Playback ended')\n this.isPlaying = false\n this.onEndedCallback?.()\n }\n\n /**\n * Set ended callback\n */\n onEnded(callback: () => void): void {\n this.onEndedCallback = callback\n }\n\n /**\n * Check if playing\n */\n isPlayingNow(): boolean {\n return this.isPlaying && !this.isPaused\n }\n\n /**\n * Get total duration of buffered audio\n */\n getBufferedDuration(): number {\n if (!this.audioContext) {\n return 0\n }\n\n let totalSamples = 0\n for (const chunk of this.audioChunks) {\n totalSamples += chunk.data.length / 2 / this.channelCount // 16-bit = 2 bytes per sample\n }\n\n return totalSamples / this.sampleRate\n }\n\n /**\n * Get remaining duration (buffered - played) in seconds\n */\n getRemainingDuration(): number {\n const total = this.getBufferedDuration()\n const played = this.getCurrentTime()\n return Math.max(0, total - played)\n }\n\n\n /**\n * Dispose and cleanup\n */\n dispose(): void {\n this.stop()\n\n // Close AudioContext\n if (this.audioContext) {\n this.audioContext.close()\n this.audioContext = null\n }\n\n // Clear session state\n this.audioChunks = []\n this.scheduledChunks = 0\n this.sessionStartTime = 0\n this.pausedTimeOffset = 0\n this.pausedAt = 0\n this.pausedAudioContextTime = 0\n this.scheduledTime = 0\n this.onEndedCallback = undefined\n\n this.log('StreamingAudioPlayer disposed')\n }\n\n /**\n * Flush buffered audio\n * - hard: stops all playing sources and clears all chunks\n * - soft (default): clears UNSCHEDULED chunks only\n */\n flush(options?: { hard?: boolean }): void {\n const hard = options?.hard === true\n if (hard) {\n this.stop()\n this.audioChunks = []\n this.scheduledChunks = 0\n this.sessionStartTime = 0\n this.pausedAt = 0\n this.scheduledTime = 0\n this.log('Flushed (hard)')\n return\n }\n\n // Soft flush: drop unscheduled region\n if (this.scheduledChunks < this.audioChunks.length) {\n this.audioChunks.splice(this.scheduledChunks)\n }\n this.log('Flushed (soft)', { remainingScheduled: this.scheduledChunks })\n }\n\n /**\n * Debug logging\n */\n private log(message: string, data?: unknown): void {\n if (this.debug) {\n logger.log(`[StreamingAudioPlayer] ${message}`, data || '')\n }\n }\n}\n"],"names":["StreamingAudioPlayer","options","__publicField","APP_CONFIG","error","message","errorToMessage","AvatarKit","logger","pcmData","isLast","audioChunks","chunk","chunkIndex","audioBuffer","source","idx","err","numSamples","channel","alignedData","int16Array","channelData","i","sampleIndex","elapsed","currentAudioTime","enabled","_a","callback","totalSamples","total","played","data"],"mappings":"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"}
|
|
@@ -4,12 +4,14 @@ export interface AnimationWebSocketClientOptions {
|
|
|
4
4
|
reconnectAttempts?: number;
|
|
5
5
|
debug?: boolean;
|
|
6
6
|
jwtToken?: string;
|
|
7
|
+
appId?: string;
|
|
7
8
|
}
|
|
8
9
|
export declare class AnimationWebSocketClient extends EventEmitter {
|
|
9
10
|
private wsUrl;
|
|
10
11
|
private reconnectAttempts;
|
|
11
12
|
private debug;
|
|
12
13
|
private jwtToken?;
|
|
14
|
+
private appId?;
|
|
13
15
|
private ws;
|
|
14
16
|
private currentCharacterId;
|
|
15
17
|
private currentRetryCount;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnimationWebSocketClient.d.ts","sourceRoot":"","sources":["../../animation/AnimationWebSocketClient.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEnD,MAAM,WAAW,+BAA+B;IAC9C,KAAK,EAAE,MAAM,CAAA;IACb,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"AnimationWebSocketClient.d.ts","sourceRoot":"","sources":["../../animation/AnimationWebSocketClient.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEnD,MAAM,WAAW,+BAA+B;IAC9C,KAAK,EAAE,MAAM,CAAA;IACb,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,qBAAa,wBAAyB,SAAQ,YAAY;IACxD,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,iBAAiB,CAAQ;IACjC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAC,CAAQ;IACzB,OAAO,CAAC,KAAK,CAAC,CAAQ;IAEtB,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,iBAAiB,CAAY;IACrC,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,sBAAsB,CAAiB;IAC/C,OAAO,CAAC,cAAc,CAAsB;gBAEhC,OAAO,EAAE,+BAA+B;IASpD;;OAEG;IACG,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuCjD;;OAEG;IACH,UAAU,IAAI,IAAI;IAmBlB;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO;IAqC3E;;;OAGG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,qBAAqB,IAAI,MAAM;IAM/B,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,gBAAgB;IAoExB,OAAO,CAAC,aAAa;IA2CrB,OAAO,CAAC,iBAAiB;CAmB1B"}
|
|
@@ -52,6 +52,14 @@ export declare class AnimationPlayer {
|
|
|
52
52
|
* 添加音频块(仅用于流式播放)
|
|
53
53
|
*/
|
|
54
54
|
addAudioChunk(audio: Uint8Array, isLast?: boolean): void;
|
|
55
|
+
/**
|
|
56
|
+
* 暂停播放
|
|
57
|
+
*/
|
|
58
|
+
pause(): void;
|
|
59
|
+
/**
|
|
60
|
+
* 继续播放
|
|
61
|
+
*/
|
|
62
|
+
resume(): Promise<void>;
|
|
55
63
|
dispose(): void;
|
|
56
64
|
}
|
|
57
65
|
//# sourceMappingURL=AnimationPlayer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnimationPlayer.d.ts","sourceRoot":"","sources":["../../audio/AnimationPlayer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAMlE,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,eAAe,CAAoC;IAC3D,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,eAAe,CAAC,CAAY;IACpC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAQ;IACpC,OAAO,CAAC,YAAY,CAAQ;IAE5B;;;OAGG;WACU,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IA2BhD;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBvE;;;OAGG;IACG,mBAAmB,CAAC,eAAe,EAAE,oBAAoB,EAAE,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAYrG;;OAEG;IACH,gBAAgB,IAAI,OAAO;IAI3B;;OAEG;IACH,kBAAkB,IAAI,oBAAoB,GAAG,IAAI;IAIjD;;;OAGG;IACG,kCAAkC,IAAI,OAAO,CAAC,IAAI,CAAC;IA2BzD;;;OAGG;IACG,sBAAsB,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBjE,OAAO,CAAC,mBAAmB;IAerB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAc3B,IAAI,IAAI,IAAI;IAcZ,SAAS,IAAI,OAAO;IAOpB,oBAAoB,IAAI,MAAM;IAK9B;;OAEG;IACH,cAAc,IAAI,MAAM;IAOxB;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,GAAE,OAAe,GAAG,IAAI;IAQ/D,OAAO,IAAI,IAAI;CAehB"}
|
|
1
|
+
{"version":3,"file":"AnimationPlayer.d.ts","sourceRoot":"","sources":["../../audio/AnimationPlayer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAMlE,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,eAAe,CAAoC;IAC3D,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,eAAe,CAAC,CAAY;IACpC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAQ;IACpC,OAAO,CAAC,YAAY,CAAQ;IAE5B;;;OAGG;WACU,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IA2BhD;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBvE;;;OAGG;IACG,mBAAmB,CAAC,eAAe,EAAE,oBAAoB,EAAE,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAYrG;;OAEG;IACH,gBAAgB,IAAI,OAAO;IAI3B;;OAEG;IACH,kBAAkB,IAAI,oBAAoB,GAAG,IAAI;IAIjD;;;OAGG;IACG,kCAAkC,IAAI,OAAO,CAAC,IAAI,CAAC;IA2BzD;;;OAGG;IACG,sBAAsB,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBjE,OAAO,CAAC,mBAAmB;IAerB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAc3B,IAAI,IAAI,IAAI;IAcZ,SAAS,IAAI,OAAO;IAOpB,oBAAoB,IAAI,MAAM;IAK9B;;OAEG;IACH,cAAc,IAAI,MAAM;IAOxB;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,GAAE,OAAe,GAAG,IAAI;IAQ/D;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAU7B,OAAO,IAAI,IAAI;CAehB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StreamingAudioPlayer.d.ts","sourceRoot":"","sources":["../../audio/StreamingAudioPlayer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,WAAW,2BAA2B;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,qBAAa,oBAAoB;IAE/B,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,KAAK,CAAS;IAGtB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,aAAa,CAAI;IAGzB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,gBAAgB,CAAO;IAG/B,OAAO,CAAC,WAAW,CAAmD;IACtE,OAAO,CAAC,eAAe,CAAI;IAC3B,OAAO,CAAC,aAAa,CAA8B;IAGnD,OAAO,CAAC,eAAe,CAAC,CAAY;gBAExB,OAAO,CAAC,EAAE,2BAA2B;IAOjD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiCjC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,GAAE,OAAe,GAAG,IAAI;IAoC5D;;OAEG;IACG,eAAe,CAAC,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"StreamingAudioPlayer.d.ts","sourceRoot":"","sources":["../../audio/StreamingAudioPlayer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,WAAW,2BAA2B;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,qBAAa,oBAAoB;IAE/B,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,KAAK,CAAS;IAGtB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,sBAAsB,CAAI;IAClC,OAAO,CAAC,aAAa,CAAI;IAGzB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,gBAAgB,CAAO;IAG/B,OAAO,CAAC,WAAW,CAAmD;IACtE,OAAO,CAAC,eAAe,CAAI;IAC3B,OAAO,CAAC,aAAa,CAA8B;IAGnD,OAAO,CAAC,eAAe,CAAC,CAAY;gBAExB,OAAO,CAAC,EAAE,2BAA2B;IAOjD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiCjC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,GAAE,OAAe,GAAG,IAAI;IAoC5D;;OAEG;IACG,eAAe,CAAC,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB/F;;OAEG;IACH,OAAO,CAAC,aAAa;IAyBrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAqFzB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAwDxB;;OAEG;IACH,cAAc,IAAI,MAAM;IAgBxB;;OAEG;IACH,KAAK,IAAI,IAAI;IA8Bb;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IA4C7B;;OAEG;IACH,IAAI,IAAI,IAAI;IA0CZ;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKpC;;;OAGG;IACH,IAAI,IAAI,IAAI;IASZ;;OAEG;IACH,SAAS,IAAI,IAAI;IAMjB;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAInC;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACH,mBAAmB,IAAI,MAAM;IAa7B;;OAEG;IACH,oBAAoB,IAAI,MAAM;IAO9B;;OAEG;IACH,OAAO,IAAI,IAAI;IAsBf;;;;OAIG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAoBzC;;OAEG;IACH,OAAO,CAAC,GAAG;CAKZ"}
|