-
Notifications
You must be signed in to change notification settings - Fork 245
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #33 from slkzgm/feature/speakers-idle
feat: enhance speaker management, idle detection, and dynamic GPT config
- Loading branch information
Showing
10 changed files
with
635 additions
and
257 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// src/plugins/IdleMonitorPlugin.ts | ||
|
||
import { Plugin, AudioDataWithUser } from '../types'; | ||
import { Space } from '../core/Space'; | ||
|
||
/** | ||
* Plugin that tracks the last speaker audio timestamp | ||
* and the last local audio timestamp to detect overall silence. | ||
*/ | ||
export class IdleMonitorPlugin implements Plugin { | ||
private space?: Space; | ||
private lastSpeakerAudioMs = Date.now(); | ||
private lastLocalAudioMs = Date.now(); | ||
private checkInterval?: NodeJS.Timeout; | ||
|
||
/** | ||
* @param idleTimeoutMs How many ms of silence before triggering idle (default 60s) | ||
* @param checkEveryMs Interval for checking silence (default 10s) | ||
*/ | ||
constructor( | ||
private idleTimeoutMs: number = 60_000, | ||
private checkEveryMs: number = 10_000, | ||
) {} | ||
|
||
onAttach(space: Space) { | ||
this.space = space; | ||
console.log('[IdleMonitorPlugin] onAttach => plugin attached'); | ||
} | ||
|
||
init(params: { space: Space; pluginConfig?: Record<string, any> }): void { | ||
this.space = params.space; | ||
console.log('[IdleMonitorPlugin] init => setting up idle checks'); | ||
|
||
// Update lastSpeakerAudioMs on incoming speaker audio | ||
this.space.on('audioDataFromSpeaker', (data: AudioDataWithUser) => { | ||
this.lastSpeakerAudioMs = Date.now(); | ||
}); | ||
|
||
// Patch space.pushAudio to update lastLocalAudioMs | ||
const originalPushAudio = this.space.pushAudio.bind(this.space); | ||
this.space.pushAudio = (samples, sampleRate) => { | ||
this.lastLocalAudioMs = Date.now(); | ||
originalPushAudio(samples, sampleRate); | ||
}; | ||
|
||
// Periodically check for silence | ||
this.checkInterval = setInterval(() => this.checkIdle(), this.checkEveryMs); | ||
} | ||
|
||
private checkIdle() { | ||
const now = Date.now(); | ||
const lastAudio = Math.max(this.lastSpeakerAudioMs, this.lastLocalAudioMs); | ||
const idleMs = now - lastAudio; | ||
|
||
if (idleMs >= this.idleTimeoutMs) { | ||
console.log( | ||
'[IdleMonitorPlugin] idleTimeout => no audio for', | ||
idleMs, | ||
'ms', | ||
); | ||
this.space?.emit('idleTimeout', { idleMs }); | ||
} | ||
} | ||
|
||
/** | ||
* Returns how many ms have passed since any audio was detected. | ||
*/ | ||
public getIdleTimeMs(): number { | ||
const now = Date.now(); | ||
const lastAudio = Math.max(this.lastSpeakerAudioMs, this.lastLocalAudioMs); | ||
return now - lastAudio; | ||
} | ||
|
||
cleanup(): void { | ||
console.log('[IdleMonitorPlugin] cleanup => stopping idle checks'); | ||
if (this.checkInterval) { | ||
clearInterval(this.checkInterval); | ||
this.checkInterval = undefined; | ||
} | ||
} | ||
} |
Oops, something went wrong.