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 {
|
do {
|
||||||
let audioSession = AVAudioSession.sharedInstance()
|
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)
|
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()
|
request = SFSpeechAudioBufferRecognitionRequest()
|
||||||
|
guard let request else { return }
|
||||||
guard let audioEngine, let request else { return }
|
|
||||||
request.shouldReportPartialResults = true
|
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 inputNode = audioEngine.inputNode
|
||||||
let recordingFormat = inputNode.outputFormat(forBus: 0)
|
|
||||||
|
|
||||||
// Validate format — 0 channels crashes installTap
|
// Use nil format — lets the system pick a compatible format
|
||||||
guard recordingFormat.channelCount > 0 else {
|
// and avoids the mDataByteSize(0) assertion from format mismatches
|
||||||
print("[PronunciationService] invalid recording format (0 channels)")
|
inputNode.installTap(onBus: 0, bufferSize: 4096, format: nil) { buffer, _ in
|
||||||
self.audioEngine = nil
|
|
||||||
self.request = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
|
|
||||||
guard buffer.frameLength > 0 else { return }
|
|
||||||
request.append(buffer)
|
request.append(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user