Fix speech recognition crash from audio format mismatch
Switch audio session to .record-only, use nil tap format so the system picks a compatible format, and route through AVAudioEngine with a 4096 buffer. Avoids the mDataByteSize(0) assertion seen on some devices. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -65,28 +65,26 @@ final class PronunciationService {
|
||||
|
||||
do {
|
||||
let audioSession = AVAudioSession.sharedInstance()
|
||||
try audioSession.setCategory(.playAndRecord, mode: .measurement, options: [.duckOthers, .defaultToSpeaker])
|
||||
try audioSession.setCategory(.record, mode: .measurement, options: [.duckOthers])
|
||||
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
|
||||
|
||||
audioEngine = AVAudioEngine()
|
||||
// Use SFSpeechAudioBufferRecognitionRequest with the recognizer
|
||||
// directly — avoid AVAudioEngine entirely since it produces
|
||||
// zero-length buffers on some devices causing assertion crashes.
|
||||
request = SFSpeechAudioBufferRecognitionRequest()
|
||||
|
||||
guard let audioEngine, let request else { return }
|
||||
guard let request else { return }
|
||||
request.shouldReportPartialResults = true
|
||||
request.requiresOnDeviceRecognition = recognizer.supportsOnDeviceRecognition
|
||||
|
||||
// Use AVAudioEngine with the native input format
|
||||
audioEngine = AVAudioEngine()
|
||||
guard let audioEngine else { return }
|
||||
|
||||
let inputNode = audioEngine.inputNode
|
||||
let recordingFormat = inputNode.outputFormat(forBus: 0)
|
||||
|
||||
// Validate format — 0 channels crashes installTap
|
||||
guard recordingFormat.channelCount > 0 else {
|
||||
print("[PronunciationService] invalid recording format (0 channels)")
|
||||
self.audioEngine = nil
|
||||
self.request = nil
|
||||
return
|
||||
}
|
||||
|
||||
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
|
||||
guard buffer.frameLength > 0 else { return }
|
||||
// Use nil format — lets the system pick a compatible format
|
||||
// and avoids the mDataByteSize(0) assertion from format mismatches
|
||||
inputNode.installTap(onBus: 0, bufferSize: 4096, format: nil) { buffer, _ in
|
||||
request.append(buffer)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user