В соответствии с требованиями разрабатываемого приложения, я должен передать несколько аудиофайлов на SFSpeechRecognizer
и получить взамен транскрипцию.Я сделал это двумя способами
Первый метод - Использование рекурсии (работает правильно, вы можете пропустить его, если хотите)
Сначала я выполнил эту задачу, получив транскрипциюпо одному.то есть, когда SFSpeechRecognitionTask
завершается, результат сохраняется и процесс снова запускается через рекурсивный вызов.
class Transcription
{
let url = [URL(fileURLWithPath: "sad")]
var fileCount = 3
let totalFiles = 4;
func getTranscriptionRecursive()
{
getTranscriptionOfAudioFile(atURL: url[fileCount], fileCount: fileCount, totalFiles: totalFiles) { (result) in
if(self.fileCount <= self.totalFiles)
{
self.fileCount = self.fileCount+1
self.getTranscriptionRecursive()
}
}
}
func getTranscriptionOfAudioFile(atURL url: URL, fileCount: Int, totalFiles: Int, completion: @escaping ((SFSpeechRecognitionResult?)->Void))
{
let request = SFSpeechURLRecognitionRequest(url: url)
request.shouldReportPartialResults = false
let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))
if (recognizer?.isAvailable)! {
recognizer?.recognitionTask(with: request) { result, error in
//error handling
completion(result)
}
}
}
}
Этот метод работал отлично, но он занимает слишком много времени, так как каждый запрос SFSpeechRecognizer
занимаетвремя для завершения.
Второй метод - Использование цикла и фонового потока (у этого есть проблема)
Я попытался создать несколько запросов и выполнить ихв фоновом режиме сразу.Для этого я создал цикл For до подсчета аудиофайлов, и в этом цикле я вызвал функцию для создания SFSpeechRecognizer
Запрос и задание.
for index in 0..<urls.count
{
DispatchQueue.global(qos: .background).async {
self.getTranscriptionOfAudio(atURL: self.urls[index]) { (result, myError, message) in
//error handling
//process Results
}
}
}
, где в качестве функции для получения результатов распознавания речи
func getTranscriptionOfAudio(atURL audioURL: URL?, completion: @escaping ((SFSpeechRecognitionResult? , Error?, String?)->Void))
{
let request = SFSpeechURLRecognitionRequest(url: audioURL!)
request.shouldReportPartialResults = false
let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))
if (recognizer?.isAvailable)! {
recognizer?.recognitionTask(with: request) { result, error in
//error handling
completion(results,nil,nil)
}
} else {
completion(nil,nil,"Reognizer could not be initialized");
}
}
Когда я запускаю этот код, выполняется только одна задача, и другие задачи выдают эту ошибку
+ [AFAggregator logDictationFailedWithError:] Ошибка домена = kAFAssistantErrorDomain Code = 209 "(пусто)) "
Я искал эту ошибку в интернете, но нет документации, содержащей ее детали.
Возможно, это связано с параллельным запуском SFSpeechRecognitionTask
, но в официальных документах Apple здесь они не запрещали это делать, так как мы можем создать SFSpeechRecognitionRequest
объект отдельно.Мы не используем одноэлементный объект SFSpeechRecognizer
, дайте мне знать, если кто-нибудь знает, что происходит и что вы предлагаете мне сделать.