fix: avoid iOS talk mode audio tap crash
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
- Naming: match source names with `*.test.ts`; e2e in `*.e2e.test.ts`.
|
||||
- Run `pnpm test` (or `pnpm test:coverage`) before pushing when you touch logic.
|
||||
- Pure test additions/fixes generally do **not** need a changelog entry unless they alter user-facing behavior or the user asks for one.
|
||||
- Mobile: before using a simulator, check for connected real devices (iOS + Android) and prefer them when available.
|
||||
|
||||
## Commit & Pull Request Guidelines
|
||||
- Create commits with `scripts/committer "<msg>" <file...>`; avoid manual `git add`/`git commit` so staging stays scoped.
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
- macOS menu: device list now uses `node.list` (devices only; no agent/tool presence entries).
|
||||
- macOS menu: device list now shows connected nodes only.
|
||||
- iOS node: fix ReplayKit screen recording crash caused by queue isolation assertions during capture.
|
||||
- iOS Talk Mode: avoid audio tap queue assertions when starting recognition.
|
||||
- iOS/Android nodes: bridge auto-connect refreshes stale tokens and settings now show richer bridge/device details.
|
||||
- iOS/Android nodes: status pill now surfaces camera activity instead of overlay toasts.
|
||||
- iOS/Android/macOS nodes: camera snaps recompress to keep base64 payloads under 5 MB.
|
||||
|
||||
@@ -253,7 +253,7 @@ private struct CanvasContent: View {
|
||||
private struct OverlayButton: View {
|
||||
let systemImage: String
|
||||
let brighten: Bool
|
||||
var tint: Color? = nil
|
||||
var tint: Color?
|
||||
var isActive: Bool = false
|
||||
let action: () -> Void
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import Speech
|
||||
@MainActor
|
||||
@Observable
|
||||
final class TalkModeManager: NSObject {
|
||||
private typealias SpeechRequest = SFSpeechAudioBufferRecognitionRequest
|
||||
var isEnabled: Bool = false
|
||||
var isListening: Bool = false
|
||||
var isSpeaking: Bool = false
|
||||
@@ -105,9 +106,8 @@ final class TalkModeManager: NSObject {
|
||||
let input = self.audioEngine.inputNode
|
||||
let format = input.outputFormat(forBus: 0)
|
||||
input.removeTap(onBus: 0)
|
||||
input.installTap(onBus: 0, bufferSize: 2048, format: format) { [weak request] buffer, _ in
|
||||
request?.append(buffer)
|
||||
}
|
||||
let tapBlock = Self.makeAudioTapAppendCallback(request: request)
|
||||
input.installTap(onBus: 0, bufferSize: 2048, format: format, block: tapBlock)
|
||||
|
||||
self.audioEngine.prepare()
|
||||
try self.audioEngine.start()
|
||||
@@ -135,6 +135,12 @@ final class TalkModeManager: NSObject {
|
||||
self.speechRecognizer = nil
|
||||
}
|
||||
|
||||
private nonisolated static func makeAudioTapAppendCallback(request: SpeechRequest) -> AVAudioNodeTapBlock {
|
||||
{ buffer, _ in
|
||||
request.append(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
private func handleTranscript(transcript: String, isFinal: Bool) async {
|
||||
let trimmed = transcript.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if self.isSpeaking, self.interruptOnSpeech {
|
||||
|
||||
Reference in New Issue
Block a user