@omote/core 0.9.5 → 0.9.7
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/dist/index.d.mts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +46 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +46 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -678,6 +678,13 @@ declare class PlaybackPipeline extends EventEmitter<PlaybackPipelineEvents> {
|
|
|
678
678
|
private neutralTransitionFrame;
|
|
679
679
|
private neutralTransitionStart;
|
|
680
680
|
private neutralAnimationId;
|
|
681
|
+
private static readonly RAMP_IN_HALFLIFE;
|
|
682
|
+
private static readonly RAMP_IN_DURATION_MS;
|
|
683
|
+
private rampInSmoother;
|
|
684
|
+
private rampInActive;
|
|
685
|
+
private rampInLastTime;
|
|
686
|
+
private rampInStartTime;
|
|
687
|
+
private readonly _rampInBuffer;
|
|
681
688
|
private _currentFrame;
|
|
682
689
|
private _currentRawFrame;
|
|
683
690
|
private _emotion;
|
package/dist/index.d.ts
CHANGED
|
@@ -678,6 +678,13 @@ declare class PlaybackPipeline extends EventEmitter<PlaybackPipelineEvents> {
|
|
|
678
678
|
private neutralTransitionFrame;
|
|
679
679
|
private neutralTransitionStart;
|
|
680
680
|
private neutralAnimationId;
|
|
681
|
+
private static readonly RAMP_IN_HALFLIFE;
|
|
682
|
+
private static readonly RAMP_IN_DURATION_MS;
|
|
683
|
+
private rampInSmoother;
|
|
684
|
+
private rampInActive;
|
|
685
|
+
private rampInLastTime;
|
|
686
|
+
private rampInStartTime;
|
|
687
|
+
private readonly _rampInBuffer;
|
|
681
688
|
private _currentFrame;
|
|
682
689
|
private _currentRawFrame;
|
|
683
690
|
private _emotion;
|
package/dist/index.js
CHANGED
|
@@ -1885,18 +1885,19 @@ var _A2EProcessor = class _A2EProcessor {
|
|
|
1885
1885
|
*/
|
|
1886
1886
|
async flush() {
|
|
1887
1887
|
if (this.disposed || this.writeOffset === 0) return;
|
|
1888
|
+
const actualSamples = this.writeOffset;
|
|
1888
1889
|
const padded = new Float32Array(this.chunkSize);
|
|
1889
|
-
padded.set(this.buffer.subarray(0,
|
|
1890
|
+
padded.set(this.buffer.subarray(0, actualSamples), 0);
|
|
1890
1891
|
const chunkTimestamp = this.bufferStartTime > 0 ? this.bufferStartTime : void 0;
|
|
1891
1892
|
logger4.info("flush: routing through drain pipeline", {
|
|
1892
|
-
actualSamples
|
|
1893
|
+
actualSamples,
|
|
1893
1894
|
chunkTimestamp: chunkTimestamp?.toFixed(3),
|
|
1894
1895
|
pendingChunks: this.pendingChunks.length,
|
|
1895
1896
|
inferenceRunning: this.inferenceRunning
|
|
1896
1897
|
});
|
|
1897
1898
|
this.writeOffset = 0;
|
|
1898
1899
|
this.bufferStartTime = 0;
|
|
1899
|
-
this.pendingChunks.push({ chunk: padded, timestamp: chunkTimestamp });
|
|
1900
|
+
this.pendingChunks.push({ chunk: padded, timestamp: chunkTimestamp, actualSamples });
|
|
1900
1901
|
this.drainPendingChunks();
|
|
1901
1902
|
}
|
|
1902
1903
|
/**
|
|
@@ -2054,14 +2055,15 @@ var _A2EProcessor = class _A2EProcessor {
|
|
|
2054
2055
|
logger4.info("drainPendingChunks starting", { pendingChunks: this.pendingChunks.length });
|
|
2055
2056
|
const processNext = async () => {
|
|
2056
2057
|
while (this.pendingChunks.length > 0 && !this.disposed) {
|
|
2057
|
-
const { chunk, timestamp } = this.pendingChunks.shift();
|
|
2058
|
+
const { chunk, timestamp, actualSamples } = this.pendingChunks.shift();
|
|
2058
2059
|
try {
|
|
2059
2060
|
const t0 = getClock().now();
|
|
2060
2061
|
const result = await this.backend.infer(chunk, this.identityIndex);
|
|
2061
2062
|
const inferMs = Math.round(getClock().now() - t0);
|
|
2062
|
-
const
|
|
2063
|
+
const effectiveSamples = actualSamples ?? chunk.length;
|
|
2064
|
+
const actualDuration = effectiveSamples / this.sampleRate;
|
|
2063
2065
|
const actualFrameCount = Math.ceil(actualDuration * FRAME_RATE);
|
|
2064
|
-
const framesToQueue = Math.min(actualFrameCount, result.blendshapes.length);
|
|
2066
|
+
const framesToQueue = Math.min(Math.max(1, actualFrameCount), result.blendshapes.length);
|
|
2065
2067
|
logger4.info("Inference complete", {
|
|
2066
2068
|
inferMs,
|
|
2067
2069
|
modelFrames: result.blendshapes.length,
|
|
@@ -2314,7 +2316,7 @@ function applyProfile(raw, profile, out) {
|
|
|
2314
2316
|
|
|
2315
2317
|
// src/audio/PlaybackPipeline.ts
|
|
2316
2318
|
var logger5 = createLogger("PlaybackPipeline");
|
|
2317
|
-
var
|
|
2319
|
+
var _PlaybackPipeline = class _PlaybackPipeline extends EventEmitter {
|
|
2318
2320
|
constructor(config) {
|
|
2319
2321
|
super();
|
|
2320
2322
|
this.config = config;
|
|
@@ -2333,6 +2335,10 @@ var PlaybackPipeline = class extends EventEmitter {
|
|
|
2333
2335
|
this.neutralTransitionFrame = null;
|
|
2334
2336
|
this.neutralTransitionStart = 0;
|
|
2335
2337
|
this.neutralAnimationId = null;
|
|
2338
|
+
this.rampInActive = false;
|
|
2339
|
+
this.rampInLastTime = 0;
|
|
2340
|
+
this.rampInStartTime = 0;
|
|
2341
|
+
this._rampInBuffer = new Float32Array(52);
|
|
2336
2342
|
// Current frame refs
|
|
2337
2343
|
this._currentFrame = null;
|
|
2338
2344
|
this._currentRawFrame = null;
|
|
@@ -2359,6 +2365,7 @@ var PlaybackPipeline = class extends EventEmitter {
|
|
|
2359
2365
|
modelId: config.lam.modelId,
|
|
2360
2366
|
neutralTransitionEnabled: this.neutralTransitionEnabled
|
|
2361
2367
|
});
|
|
2368
|
+
this.rampInSmoother = new BlendshapeSmoother({ halflife: _PlaybackPipeline.RAMP_IN_HALFLIFE });
|
|
2362
2369
|
this.scheduler = new AudioScheduler({
|
|
2363
2370
|
sampleRate: this.sampleRate,
|
|
2364
2371
|
initialLookaheadSec: audioDelayMs / 1e3
|
|
@@ -2426,6 +2433,10 @@ var PlaybackPipeline = class extends EventEmitter {
|
|
|
2426
2433
|
this.frameLoopCount = 0;
|
|
2427
2434
|
this._currentFrame = null;
|
|
2428
2435
|
this._currentRawFrame = null;
|
|
2436
|
+
this.rampInSmoother.reset();
|
|
2437
|
+
this.rampInActive = true;
|
|
2438
|
+
this.rampInLastTime = 0;
|
|
2439
|
+
this.rampInStartTime = 0;
|
|
2429
2440
|
this.cancelNeutralTransition();
|
|
2430
2441
|
this.scheduler.warmup();
|
|
2431
2442
|
this.sessionStartTime = getClock().now();
|
|
@@ -2562,17 +2573,36 @@ var PlaybackPipeline = class extends EventEmitter {
|
|
|
2562
2573
|
}
|
|
2563
2574
|
}
|
|
2564
2575
|
if (lamFrame) {
|
|
2565
|
-
|
|
2576
|
+
let effectiveFrame = lamFrame;
|
|
2577
|
+
if (this.rampInActive) {
|
|
2578
|
+
const now = getClock().now();
|
|
2579
|
+
if (this.rampInLastTime === 0) {
|
|
2580
|
+
this.rampInStartTime = now;
|
|
2581
|
+
this.rampInLastTime = now;
|
|
2582
|
+
}
|
|
2583
|
+
this.rampInSmoother.setTarget(lamFrame);
|
|
2584
|
+
const dt = (now - this.rampInLastTime) / 1e3;
|
|
2585
|
+
this.rampInLastTime = now;
|
|
2586
|
+
if (dt > 0) {
|
|
2587
|
+
const smoothed = this.rampInSmoother.update(dt);
|
|
2588
|
+
this._rampInBuffer.set(smoothed);
|
|
2589
|
+
effectiveFrame = this._rampInBuffer;
|
|
2590
|
+
}
|
|
2591
|
+
if (now - this.rampInStartTime > _PlaybackPipeline.RAMP_IN_DURATION_MS) {
|
|
2592
|
+
this.rampInActive = false;
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
const scaled = applyProfile(effectiveFrame, this.profile, this._profileBuffer);
|
|
2566
2596
|
this._currentFrame = scaled;
|
|
2567
|
-
this._currentRawFrame =
|
|
2597
|
+
this._currentRawFrame = effectiveFrame;
|
|
2568
2598
|
const fullFrame = {
|
|
2569
2599
|
blendshapes: scaled,
|
|
2570
|
-
rawBlendshapes:
|
|
2600
|
+
rawBlendshapes: effectiveFrame,
|
|
2571
2601
|
timestamp: currentTime,
|
|
2572
2602
|
emotion: this._emotion ?? void 0
|
|
2573
2603
|
};
|
|
2574
2604
|
this.emit("frame", fullFrame);
|
|
2575
|
-
this.emit("frame:raw",
|
|
2605
|
+
this.emit("frame:raw", effectiveFrame);
|
|
2576
2606
|
}
|
|
2577
2607
|
this.frameAnimationId = requestAnimationFrame(updateFrame);
|
|
2578
2608
|
};
|
|
@@ -2672,6 +2702,11 @@ var PlaybackPipeline = class extends EventEmitter {
|
|
|
2672
2702
|
this.emit("state", state);
|
|
2673
2703
|
}
|
|
2674
2704
|
};
|
|
2705
|
+
// Ramp-in smoother: smooths neutral → first inference frame at start-of-speech
|
|
2706
|
+
_PlaybackPipeline.RAMP_IN_HALFLIFE = 0.05;
|
|
2707
|
+
// 50ms — snappy but smooth
|
|
2708
|
+
_PlaybackPipeline.RAMP_IN_DURATION_MS = 150;
|
|
2709
|
+
var PlaybackPipeline = _PlaybackPipeline;
|
|
2675
2710
|
|
|
2676
2711
|
// src/audio/TTSPlayback.ts
|
|
2677
2712
|
var logger6 = createLogger("TTSPlayback");
|