fix(flow): drain trailing audio and harden chunked ASR pipeline
- P0/P1: tail-drain state machine in FlowContinuousCapture with converter flush; FlowSessionManager awaits drain before finalize - P2: FlowCaptureTailDrain policy/tracker, pipeline diagnostics, unit tests - P3: short final chunk merged re-transcription in ChunkedUtterancePipeline - P4: UtteranceTranscriptStitcher composedSafely fallback; preview path parity in LiveDictationController Co-authored-by: Rocky <hkgood@users.noreply.github.com>
This commit is contained in:
@@ -63,4 +63,33 @@ final class UtteranceStreamChunkerTests: XCTestCase {
|
||||
XCTAssertGreaterThanOrEqual(received.count, 2)
|
||||
XCTAssertTrue(received.last?.isLast == true)
|
||||
}
|
||||
|
||||
func testFinalChunkIncludesLateArrivingTailSamples() async {
|
||||
let config = FlowUtteranceChunkConfig(
|
||||
firstChunkDurationSeconds: 0.5,
|
||||
subsequentChunkDurationSeconds: 1.0,
|
||||
overlapDurationSeconds: 0,
|
||||
pauseExtensionMaxSeconds: 0,
|
||||
pauseRMSThreshold: 0.02,
|
||||
sampleRate: 1_000
|
||||
)
|
||||
let head = [Float](repeating: 0.05, count: 600)
|
||||
let tail = [Float](repeating: 0.08, count: 250)
|
||||
|
||||
let (stream, continuation) = AsyncStream<AudioBufferSnapshot>.makeStream()
|
||||
continuation.yield(AudioBufferSnapshot(samples: head, sampleRate: Double(config.sampleRate)))
|
||||
continuation.yield(AudioBufferSnapshot(samples: tail, sampleRate: Double(config.sampleRate)))
|
||||
continuation.finish()
|
||||
|
||||
var received: [UtteranceAudioChunk] = []
|
||||
for await chunk in UtteranceStreamChunker.chunks(from: stream, config: config) {
|
||||
received.append(chunk)
|
||||
}
|
||||
|
||||
guard let last = received.last else {
|
||||
return XCTFail("expected at least one chunk")
|
||||
}
|
||||
XCTAssertTrue(last.isLast)
|
||||
XCTAssertGreaterThanOrEqual(last.samples.count, tail.count)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user