|
|
@@ -101,7 +101,7 @@ final class MeetingTranscriptionService {
|
|
|
systemURL: URL?,
|
|
|
chunkSeconds: TimeInterval = 30,
|
|
|
overlapSeconds: TimeInterval = 0,
|
|
|
- locales: [Locale] = [Locale(identifier: "en-US")],
|
|
|
+ locales: [Locale] = [],
|
|
|
onProgress: (@Sendable (MeetingTranscriptionProgress) -> Void)? = nil
|
|
|
) async throws -> [TranscriptSegment] {
|
|
|
try await requestAuthorization()
|
|
|
@@ -125,7 +125,7 @@ final class MeetingTranscriptionService {
|
|
|
let counter = ProgressCounter(total: totalChunks, onProgress: onProgress)
|
|
|
await counter.emitInitial()
|
|
|
|
|
|
- let effectiveLocales = locales.isEmpty ? [Locale(identifier: "en-US")] : locales
|
|
|
+ let effectiveLocales = locales.isEmpty ? preferredLocalesForGlobalRecognition() : locales
|
|
|
|
|
|
async let micSegments: [TranscriptSegment] = {
|
|
|
guard let plan = micPlan else { return [] }
|
|
|
@@ -248,6 +248,48 @@ final class MeetingTranscriptionService {
|
|
|
return ""
|
|
|
}
|
|
|
|
|
|
+ private func preferredLocalesForGlobalRecognition() -> [Locale] {
|
|
|
+ let supported = SFSpeechRecognizer.supportedLocales()
|
|
|
+ guard supported.isEmpty == false else {
|
|
|
+ return [Locale.current, Locale(identifier: "en-US")]
|
|
|
+ }
|
|
|
+
|
|
|
+ let normalizedSupportedByIdentifier: [String: Locale] = Dictionary(
|
|
|
+ uniqueKeysWithValues: supported.map { locale in
|
|
|
+ (normalizeLocaleIdentifier(locale.identifier), locale)
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ var ordered: [Locale] = []
|
|
|
+ var seen = Set<String>()
|
|
|
+
|
|
|
+ func appendIfSupportedIdentifier(_ identifier: String) {
|
|
|
+ let normalized = normalizeLocaleIdentifier(identifier)
|
|
|
+ guard seen.contains(normalized) == false else { return }
|
|
|
+ guard let supportedLocale = normalizedSupportedByIdentifier[normalized] else { return }
|
|
|
+ seen.insert(normalized)
|
|
|
+ ordered.append(supportedLocale)
|
|
|
+ }
|
|
|
+
|
|
|
+ appendIfSupportedIdentifier(Locale.current.identifier)
|
|
|
+ for identifier in Locale.preferredLanguages {
|
|
|
+ appendIfSupportedIdentifier(identifier)
|
|
|
+ }
|
|
|
+
|
|
|
+ for locale in supported.sorted(by: { $0.identifier < $1.identifier }) {
|
|
|
+ appendIfSupportedIdentifier(locale.identifier)
|
|
|
+ }
|
|
|
+
|
|
|
+ if ordered.isEmpty {
|
|
|
+ return [Locale(identifier: "en-US")]
|
|
|
+ }
|
|
|
+ return ordered
|
|
|
+ }
|
|
|
+
|
|
|
+ private func normalizeLocaleIdentifier(_ identifier: String) -> String {
|
|
|
+ identifier.replacingOccurrences(of: "_", with: "-").lowercased()
|
|
|
+ }
|
|
|
+
|
|
|
private func transcribeBuffer(buffer: AVAudioPCMBuffer, recognizer: SFSpeechRecognizer) async throws -> String {
|
|
|
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
|
request.shouldReportPartialResults = false
|