chore: prepare GoodBuddy 0.8.2
Cross-platform packages / Validate source (push) Waiting to run
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, macos, macos-15) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, windows, windows-2025) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, linux, ubuntu-24.04) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, macos, macos-15-intel) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, windows, windows-2025) (push) Blocked by required conditions
Cross-platform packages / Publish GitHub Release (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, linux, ubuntu-24.04-arm) (push) Blocked by required conditions
Cross-platform packages / Validate source (push) Waiting to run
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, macos, macos-15) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, windows, windows-2025) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, linux, ubuntu-24.04) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, macos, macos-15-intel) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, windows, windows-2025) (push) Blocked by required conditions
Cross-platform packages / Publish GitHub Release (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, linux, ubuntu-24.04-arm) (push) Blocked by required conditions
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import {
|
||||
SPEECH_TRANSCRIPTION_SAMPLE_RATE,
|
||||
type SpeechTranscriptionInput
|
||||
} from '../../shared/speech-model-contracts'
|
||||
import {
|
||||
SpeechTranscriptionService,
|
||||
createSherpaRecognizerConfig
|
||||
} from './speech-transcription-service'
|
||||
import type { SelectedSpeechRuntimeModel } from './speech-model-manager'
|
||||
|
||||
const requestId = '00000000-0000-4000-8000-000000000001'
|
||||
|
||||
function whisperModel(): SelectedSpeechRuntimeModel {
|
||||
return {
|
||||
id: 'whisper-tiny-multilingual',
|
||||
family: 'whisper',
|
||||
directory: 'C:\\models\\whisper',
|
||||
files: [
|
||||
{
|
||||
name: 'tiny-encoder.int8.onnx',
|
||||
role: 'encoder',
|
||||
size: 1,
|
||||
sha256: 'a'.repeat(64)
|
||||
},
|
||||
{
|
||||
name: 'tiny-decoder.int8.onnx',
|
||||
role: 'decoder',
|
||||
size: 1,
|
||||
sha256: 'b'.repeat(64)
|
||||
},
|
||||
{
|
||||
name: 'tiny-tokens.txt',
|
||||
role: 'tokens',
|
||||
size: 1,
|
||||
sha256: 'c'.repeat(64)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function input(): SpeechTranscriptionInput {
|
||||
return {
|
||||
requestId,
|
||||
sampleRate: SPEECH_TRANSCRIPTION_SAMPLE_RATE,
|
||||
audio: new Float32Array([0, 0.25, -0.25]).buffer
|
||||
}
|
||||
}
|
||||
|
||||
describe('SpeechTranscriptionService', () => {
|
||||
it('wires the selected Whisper files to bounded local inference', async () => {
|
||||
const runner = vi.fn(async () => ' 本地识别结果 ')
|
||||
const service = new SpeechTranscriptionService(
|
||||
{
|
||||
getSelectedRuntimeModel: vi.fn(async () => whisperModel())
|
||||
},
|
||||
runner
|
||||
)
|
||||
|
||||
await expect(service.transcribe(input())).resolves.toEqual({
|
||||
text: '本地识别结果'
|
||||
})
|
||||
expect(runner).toHaveBeenCalledWith(
|
||||
createSherpaRecognizerConfig(whisperModel()),
|
||||
expect.any(Float32Array),
|
||||
SPEECH_TRANSCRIPTION_SAMPLE_RATE,
|
||||
expect.any(AbortSignal)
|
||||
)
|
||||
expect(
|
||||
createSherpaRecognizerConfig(whisperModel()).modelConfig.whisper
|
||||
?.language
|
||||
).toBe('')
|
||||
})
|
||||
|
||||
it('requires an installed selected model and rejects oversized audio', async () => {
|
||||
const service = new SpeechTranscriptionService(
|
||||
{
|
||||
getSelectedRuntimeModel: vi.fn(async () => undefined)
|
||||
},
|
||||
vi.fn()
|
||||
)
|
||||
|
||||
await expect(service.transcribe(input())).rejects.toThrow(
|
||||
'安装并选择本地语音模型'
|
||||
)
|
||||
await expect(
|
||||
service.transcribe({
|
||||
...input(),
|
||||
audio: new ArrayBuffer(
|
||||
SPEECH_TRANSCRIPTION_SAMPLE_RATE * 20 * 4 + 4
|
||||
)
|
||||
})
|
||||
).rejects.toThrow('录音数据')
|
||||
})
|
||||
|
||||
it('aborts active inference and cleans up cancellation state', async () => {
|
||||
const runner = vi.fn(
|
||||
(
|
||||
_config: unknown,
|
||||
_samples: Float32Array,
|
||||
_sampleRate: number,
|
||||
signal: AbortSignal
|
||||
) =>
|
||||
new Promise<string>((_resolve, reject) => {
|
||||
signal.addEventListener(
|
||||
'abort',
|
||||
() => reject(new Error('cancelled by test')),
|
||||
{ once: true }
|
||||
)
|
||||
})
|
||||
)
|
||||
const service = new SpeechTranscriptionService(
|
||||
{
|
||||
getSelectedRuntimeModel: vi.fn(async () => whisperModel())
|
||||
},
|
||||
runner
|
||||
)
|
||||
|
||||
const transcription = service.transcribe(input())
|
||||
await vi.waitFor(() => expect(runner).toHaveBeenCalledOnce())
|
||||
expect(service.cancel(requestId)).toBe(true)
|
||||
await expect(transcription).rejects.toThrow('cancelled by test')
|
||||
expect(service.cancel(requestId)).toBe(false)
|
||||
})
|
||||
|
||||
it('surfaces inference failures and frees the request for retry', async () => {
|
||||
const runner = vi.fn(async () => {
|
||||
throw new Error('Runtime failed')
|
||||
})
|
||||
const service = new SpeechTranscriptionService(
|
||||
{
|
||||
getSelectedRuntimeModel: vi.fn(async () => whisperModel())
|
||||
},
|
||||
runner
|
||||
)
|
||||
|
||||
await expect(service.transcribe(input())).rejects.toThrow(
|
||||
'Runtime failed'
|
||||
)
|
||||
await expect(service.transcribe(input())).rejects.toThrow(
|
||||
'Runtime failed'
|
||||
)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user