feat: migrate on-device Qwen3 ASR to CoreML for background Flow dictation
Replace MLX GPU inference with CoreML bundles so transcription continues while the host app is backgrounded. Adds model download and warm-up, vendored Qwen3Speech, and updates onboarding, settings, and copy for the ~1.6 GB CoreML package (iOS 18+).
This commit is contained in:
@@ -34,7 +34,7 @@ private final class FlowCaptureStreamRelay: @unchecked Sendable {
|
||||
}
|
||||
|
||||
func yield(_ snapshot: AudioBufferSnapshot) {
|
||||
lock.withLock { continuation?.yield(snapshot) }
|
||||
_ = lock.withLock { continuation?.yield(snapshot) }
|
||||
}
|
||||
|
||||
func finish() {
|
||||
@@ -250,6 +250,22 @@ public final class FlowContinuousCapture {
|
||||
)
|
||||
}
|
||||
|
||||
/// Re-activate capture after returning from background without
|
||||
/// reinstalling the tap (iOS may deactivate the audio session).
|
||||
public func reassertIfRunning() {
|
||||
guard isRunning else { return }
|
||||
let session = AVAudioSession.sharedInstance()
|
||||
try? session.setCategory(
|
||||
.playAndRecord,
|
||||
mode: .measurement,
|
||||
options: [.defaultToSpeaker, .allowBluetoothHFP, .mixWithOthers]
|
||||
)
|
||||
try? session.setActive(true, options: .notifyOthersOnDeactivation)
|
||||
if !audioEngine.isRunning {
|
||||
try? audioEngine.start()
|
||||
}
|
||||
}
|
||||
|
||||
/// Begin forwarding downsampled buffers to ASR for one utterance.
|
||||
public func beginUtterance() -> AsyncStream<AudioBufferSnapshot> {
|
||||
let (stream, continuation) = AsyncStream<AudioBufferSnapshot>.makeStream()
|
||||
|
||||
Reference in New Issue
Block a user