perf(asr): speed up local Flow dictation and land CLM/keyboard refactor
Reduce perceived latency from key release to final text: - Adaptive chunking: 2.5s first chunk + 5s follow-ups so short utterances start on-device recognition while still recording. - Session-level ASR warmup and audio-format cache reuse to remove per-utterance cold-start of SpeechAnalyzer. - Mirror live pipelined partials to the keyboard transcript line via a new flow.transcriptionPartial App Group key + Darwin ping. Also commits the accumulated custom language model, Flow session, keyboard extension restructure, and Xiaomi MiMo provider work in progress on this branch.
This commit is contained in:
@@ -6,8 +6,10 @@
|
||||
import Foundation
|
||||
|
||||
public struct FlowUtteranceChunkConfig: Sendable, Equatable {
|
||||
/// Target maximum duration per ASR chunk.
|
||||
public let maxChunkDurationSeconds: TimeInterval
|
||||
/// Target duration for the first ASR chunk (starts pipelining early).
|
||||
public let firstChunkDurationSeconds: TimeInterval
|
||||
/// Target duration for later chunks once pipelining is underway.
|
||||
public let subsequentChunkDurationSeconds: TimeInterval
|
||||
/// Tail overlap fed into the next chunk for boundary dedup when stitching.
|
||||
public let overlapDurationSeconds: TimeInterval
|
||||
/// After hitting the max window, wait up to this long for a pause before hard-splitting.
|
||||
@@ -17,21 +19,52 @@ public struct FlowUtteranceChunkConfig: Sendable, Equatable {
|
||||
public let sampleRate: Int
|
||||
|
||||
public init(
|
||||
maxChunkDurationSeconds: TimeInterval,
|
||||
firstChunkDurationSeconds: TimeInterval = 2.5,
|
||||
subsequentChunkDurationSeconds: TimeInterval = 5.0,
|
||||
overlapDurationSeconds: TimeInterval,
|
||||
pauseExtensionMaxSeconds: TimeInterval,
|
||||
pauseRMSThreshold: Float,
|
||||
sampleRate: Int
|
||||
) {
|
||||
self.maxChunkDurationSeconds = maxChunkDurationSeconds
|
||||
self.firstChunkDurationSeconds = firstChunkDurationSeconds
|
||||
self.subsequentChunkDurationSeconds = subsequentChunkDurationSeconds
|
||||
self.overlapDurationSeconds = overlapDurationSeconds
|
||||
self.pauseExtensionMaxSeconds = pauseExtensionMaxSeconds
|
||||
self.pauseRMSThreshold = pauseRMSThreshold
|
||||
self.sampleRate = sampleRate
|
||||
}
|
||||
|
||||
/// Uniform chunk size — used by unit tests and legacy call sites.
|
||||
public init(
|
||||
maxChunkDurationSeconds: TimeInterval,
|
||||
overlapDurationSeconds: TimeInterval,
|
||||
pauseExtensionMaxSeconds: TimeInterval,
|
||||
pauseRMSThreshold: Float,
|
||||
sampleRate: Int
|
||||
) {
|
||||
self.firstChunkDurationSeconds = maxChunkDurationSeconds
|
||||
self.subsequentChunkDurationSeconds = maxChunkDurationSeconds
|
||||
self.overlapDurationSeconds = overlapDurationSeconds
|
||||
self.pauseExtensionMaxSeconds = pauseExtensionMaxSeconds
|
||||
self.pauseRMSThreshold = pauseRMSThreshold
|
||||
self.sampleRate = sampleRate
|
||||
}
|
||||
|
||||
/// Backward-compatible alias for tests that read `maxChunkSamples`.
|
||||
public var maxChunkDurationSeconds: TimeInterval {
|
||||
subsequentChunkDurationSeconds
|
||||
}
|
||||
|
||||
public func maxChunkDurationSeconds(forChunkIndex index: Int) -> TimeInterval {
|
||||
index == 0 ? firstChunkDurationSeconds : subsequentChunkDurationSeconds
|
||||
}
|
||||
|
||||
public func maxChunkSamples(forChunkIndex index: Int) -> Int {
|
||||
Int(maxChunkDurationSeconds(forChunkIndex: index) * Double(sampleRate))
|
||||
}
|
||||
|
||||
public var maxChunkSamples: Int {
|
||||
Int(maxChunkDurationSeconds * Double(sampleRate))
|
||||
maxChunkSamples(forChunkIndex: 1)
|
||||
}
|
||||
|
||||
public var overlapSamples: Int {
|
||||
@@ -44,7 +77,8 @@ public struct FlowUtteranceChunkConfig: Sendable, Equatable {
|
||||
|
||||
/// Default for keyboard Flow utterances (≤ 3 min, pipelined ASR).
|
||||
public static let flowDefault = FlowUtteranceChunkConfig(
|
||||
maxChunkDurationSeconds: 30,
|
||||
firstChunkDurationSeconds: 2.5,
|
||||
subsequentChunkDurationSeconds: 5.0,
|
||||
overlapDurationSeconds: 0.5,
|
||||
pauseExtensionMaxSeconds: 2,
|
||||
pauseRMSThreshold: 0.015,
|
||||
|
||||
Reference in New Issue
Block a user