openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
78 lines (77 loc) • 2.29 kB
JavaScript
//#region src/talk/output-activity-tracker.ts
/** Create a fresh output activity tracker for a realtime voice session. */
function createRealtimeVoiceOutputActivityTracker(options = {}) {
const now = options.now ?? Date.now;
let audioMs = 0;
let chunks = 0;
let sourceAudioBytes = 0;
let sinkAudioBytes = 0;
let playbackStarted = false;
let streamEnding = false;
let lastAudioAt;
let playbackStartedAt;
return {
markStreamOpened() {
streamEnding = false;
playbackStarted = false;
playbackStartedAt = void 0;
lastAudioAt = void 0;
},
markStreamEnding() {
streamEnding = true;
},
markPlaybackStarted() {
if (playbackStarted) return;
playbackStarted = true;
playbackStartedAt = now();
},
markAudio(delta) {
audioMs += Math.max(0, delta.audioMs ?? 0);
sourceAudioBytes += Math.max(0, delta.sourceAudioBytes ?? 0);
sinkAudioBytes += Math.max(0, delta.sinkAudioBytes ?? 0);
chunks += 1;
lastAudioAt = now();
},
reset() {
audioMs = 0;
chunks = 0;
sourceAudioBytes = 0;
sinkAudioBytes = 0;
playbackStarted = false;
streamEnding = false;
lastAudioAt = void 0;
playbackStartedAt = void 0;
},
/** Whether output exists or the downstream sink reports active playback. */
isActive(sinkActive = false) {
return sinkActive || chunks > 0;
},
/** Whether caller speech should be treated as interrupting current output. */
isInterruptible(sinkActive = false) {
return sinkActive || chunks > 0 || audioMs > 0;
},
elapsedPlaybackMs() {
return playbackStartedAt === void 0 ? 0 : now() - playbackStartedAt;
},
/** Delay before watchdog should assume playback exceeded the expected audio duration. */
playbackWatchdogDelayMs({ marginMs, minMs = 1e3 }) {
if (playbackStartedAt === void 0 || audioMs <= 0) return;
return Math.max(minMs, audioMs - (now() - playbackStartedAt) + marginMs);
},
/** Current output counters and playback timestamps. */
snapshot() {
return {
audioMs,
chunks,
sourceAudioBytes,
sinkAudioBytes,
playbackStarted,
streamEnding,
...lastAudioAt === void 0 ? {} : { lastAudioAt },
...playbackStartedAt === void 0 ? {} : { playbackStartedAt }
};
}
};
}
//#endregion
export { createRealtimeVoiceOutputActivityTracker as t };