mirror of
https://github.com/moeru-ai/airi.git
synced 2026-10-30 19:34:10 +08:00
fix(stage-ui): keep wake word preparation when an equal catalog arrives during load (#3104)
This commit is contained in:
@@ -252,6 +252,27 @@ describe('wakeWordDetector', () => {
|
||||
expect(harness.spotter.setKeywords).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('becomes ready when the same catalog arrives again while the spotter is loading', async () => {
|
||||
let finishLoad!: () => void
|
||||
const loaded = new Promise<void>(resolve => finishLoad = resolve)
|
||||
const harness = createHarness()
|
||||
harness.createSpotter.mockImplementationOnce(async () => {
|
||||
await loaded
|
||||
return harness.spotter
|
||||
})
|
||||
const catalog = () => pronunciations([{ characterId: 'alice', text: 'Alice', tokens: [['AE1', 'L', 'IH0', 'S']] }])
|
||||
|
||||
// A reactive catalog can emit an equal list again, for example after the card store hydrates.
|
||||
const first = harness.detector.setPronunciations(catalog())
|
||||
const second = harness.detector.setPronunciations(catalog())
|
||||
finishLoad()
|
||||
await Promise.all([first, second])
|
||||
|
||||
expect(harness.createSpotter).toHaveBeenCalledTimes(1)
|
||||
expect(harness.detector.ready).toBe(true)
|
||||
expect(harness.onPreparationChange).toHaveBeenLastCalledWith('ready')
|
||||
})
|
||||
|
||||
it('does not load a model for pronunciations of another model', async () => {
|
||||
const harness = createHarness()
|
||||
|
||||
|
||||
@@ -152,7 +152,8 @@ export class WakeWordDetector {
|
||||
const keywords = this.keywordsOf([...next.values()])
|
||||
const update = this.updates.then(async () => {
|
||||
// A newer list or a stop replaced this one while an earlier update ran.
|
||||
if (generation !== this.generation || next !== this.pronunciations)
|
||||
// An equal list replaces `pronunciations` without a new generation, so only the generation tells a newer list.
|
||||
if (generation !== this.generation)
|
||||
return
|
||||
|
||||
if (keywords.length === 0) {
|
||||
@@ -184,7 +185,7 @@ export class WakeWordDetector {
|
||||
// A keyword update starts a new stream in the Worker.
|
||||
this.streamSampleRate = undefined
|
||||
this.resetStream = false
|
||||
if (generation !== this.generation || next !== this.pronunciations)
|
||||
if (generation !== this.generation)
|
||||
return
|
||||
this.keywordsReady = true
|
||||
this.options.onPreparationChange?.('ready')
|
||||
|
||||
@@ -37,13 +37,6 @@ const audioTestAPI = createAudioTestAPI<
|
||||
}]
|
||||
},
|
||||
async execute({ plan, task, invokeHandler, runPreflight }) {
|
||||
// NOTICE:
|
||||
// CI wake word cases time out while preparation stays `preparing`. The root cause is not confirmed.
|
||||
// Context: audio-web wake word cases time out in the CI Unit Test job.
|
||||
// Remove this skip after the preparation failure has a verified fix on CI.
|
||||
if (env.CI && plan.definition.pipelines?.includes('kws'))
|
||||
task.context.skip(true, 'Wake word preparation times out on CI. The root cause is not confirmed.')
|
||||
|
||||
// Electron bundles the wake word model. Web downloads it, so the download must finish before the recording starts.
|
||||
if (plan.definition.pipelines?.includes('kws') && inject('fakemicRuntime').kind === 'web')
|
||||
await prepareWakeWordModel()
|
||||
|
||||
Reference in New Issue
Block a user