Last year I asked the question on how to save speech to a file. Stack Overflow Question - Recording speech synthesis to a saved file
Thanks to kakaiikaka for the answer. Although it does work, there was a bit of an error with buffering. The following code isolates the problem. With iOS 16, although there is an error it does work as intended. The completion handler that I have prints as intended. The following error is printed 20 times or so.
2023-06-17 15:35:33.811838-0400 RecordSpeechFix[3899:1958883] [AXTTSCommon] TTSPlaybackEnqueueFullAudioQueueBuffer: error -66686 enqueueing buffer
With iOS 17 (the first beta) there is a more descriptive error, and it does not work. The completion handler does not print. The following error is printed 20 or so times.
Input data proc returned inconsistent 512 packets for 2,048 bytes; at 2 bytes per packet, that is actually 1,024 packets
I'm making the assumption that this is the same problem. Fixing the error for iOS16 will also fix the error for iOS17. I could be wrong with that assumption.
//
// ContentView.swift
// RecordSpeechFix
//
// Created by Dennis Sargent on 6/16/23.
//
import AVFoundation
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Record Speech")
}
.padding()
.onTapGesture {
saveSpeechUtteranceToFile(phrase: "This produces warnings.") {
print("In iOS 16, this will print. In iOS17, this will not.")
}
}
}
func documentsDirectory(fileName: String, ext: String) -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectoryURL = paths[0]
return documentsDirectoryURL.appendingPathComponent("\(fileName).\(ext)")
}
let synthesizer = AVSpeechSynthesizer()
func saveSpeechUtteranceToFile(phrase: String, completionHandler: @escaping () -> ()) {
let fileURL = documentsDirectory(fileName: "Test", ext: ".caf")
let utterance = AVSpeechUtterance(string: phrase)
utterance.voice = AVSpeechSynthesisVoice(language: "en-US")
utterance.rate = 0.50
utterance.volume = 1.0
var output: AVAudioFile?
synthesizer.write(utterance) {(buffer: AVAudioBuffer) in
guard let pcmBuffer = buffer as? AVAudioPCMBuffer else {
fatalError("unknown buffer type: \(buffer)")
}
if pcmBuffer.frameLength == 0 {
// Done
completionHandler()
} else {
do{
if output == nil {
try output = AVAudioFile(
forWriting: fileURL,
settings: pcmBuffer.format.settings,
commonFormat: .pcmFormatInt16,
interleaved: false)
}
try output?.write(from: pcmBuffer)
}catch {
print("Buffer has an error")
}
}
}
}
}
I'm not too familiar with general audio recording. It appears that there is some sort of buffering problem. Any ideas what settings are needed to clear up these errors?