|
|
|
@ -100,14 +100,9 @@ public class AzureAsrHelper: NSObject { |
|
|
|
// 创建语音配置 |
|
|
|
speechConfig = try SPXSpeechConfiguration(subscription: subscriptionKey, region: region) |
|
|
|
// 针对翻译场景的性能优化 |
|
|
|
optimizeForTranslation() |
|
|
|
// optimizeForTranslation() |
|
|
|
if isAutoDetectLanguage { |
|
|
|
// 针对翻译场景优化的语言检测配置 |
|
|
|
speechConfig?.setPropertyTo("Continuous", byName: "SpeechServiceConnection_LanguageIdMode") |
|
|
|
|
|
|
|
// 设置语言检测的置信度阈值,提高准确性 |
|
|
|
speechConfig?.setPropertyTo("0.7", byName: "SpeechServiceConnection_AutoDetectSourceLanguageConfidenceThreshold") |
|
|
|
|
|
|
|
// 不在这里设置语言,让SPXAutoDetectSourceLanguageConfiguration处理 |
|
|
|
os_log("启用语言检测模式,支持语言: %{public}@", log: log, type: .info, supportedLanguages.joined(separator: ",")) |
|
|
|
} else { |
|
|
|
@ -150,55 +145,7 @@ public class AzureAsrHelper: NSObject { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 检测输入文本的语言,从支持的语言列表中选择最匹配的 |
|
|
|
* |
|
|
|
* @param text 需要检测的文本 |
|
|
|
* @return 从supportedLanguages中选择的最匹配语言代码 |
|
|
|
*/ |
|
|
|
public func detectTextLanguage(_ text: String) -> String? { |
|
|
|
// 如果只有一种支持的语言,直接返回 |
|
|
|
if supportedLanguages.count == 1 { |
|
|
|
return supportedLanguages[0] |
|
|
|
} |
|
|
|
|
|
|
|
// 获取所有可能的语言及其置信度 |
|
|
|
let languageResults = LanguageDetector.detectLanguageWithConfidence(from: text) |
|
|
|
|
|
|
|
// 遍历检测结果,找到第一个在supportedLanguages中的语言 |
|
|
|
for result in languageResults { |
|
|
|
let azureLanguageCode = LanguageDetector.convertToAzureLanguageCode(result.language) |
|
|
|
if supportedLanguages.contains(azureLanguageCode) { |
|
|
|
return azureLanguageCode |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 如果没有找到匹配的语言,返回第一个支持的语言作为默认值 |
|
|
|
return supportedLanguages.first |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 检测文本语言并返回详细信息 |
|
|
|
* |
|
|
|
* @param text 需要检测的文本 |
|
|
|
* @return 包含语言代码、置信度和语言名称的字典 |
|
|
|
*/ |
|
|
|
public func detectTextLanguageWithDetails(_ text: String) -> [String: Any]? { |
|
|
|
let results = LanguageDetector.detectLanguageWithConfidence(from: text) |
|
|
|
guard let topResult = results.first else { |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
let azureLanguageCode = LanguageDetector.convertToAzureLanguageCode(topResult.language) |
|
|
|
let languageName = LanguageDetector.getLanguageName(from: topResult.language) |
|
|
|
|
|
|
|
return [ |
|
|
|
"languageCode": azureLanguageCode, |
|
|
|
"confidence": topResult.confidence, |
|
|
|
"languageName": languageName, |
|
|
|
"originalCode": topResult.language |
|
|
|
] |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 开始连续语音识别 |
|
|
|
* |
|
|
|
@ -249,28 +196,7 @@ public class AzureAsrHelper: NSObject { |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
// /** |
|
|
|
// * 获取检测到的语言 |
|
|
|
// */ |
|
|
|
// private func getDetectedLanguage(from result: SPXSpeechRecognitionResult) -> String { |
|
|
|
// if !isAutoDetectLanguage { |
|
|
|
// return "" |
|
|
|
// } |
|
|
|
|
|
|
|
// // 尝试从属性中获取语言 |
|
|
|
// if let properties = result.properties, |
|
|
|
// let language = properties.getPropertyByName("SpeechServiceResponse_RecognitionLanguage") { |
|
|
|
// return language |
|
|
|
// } |
|
|
|
|
|
|
|
// // 尝试另一种方式获取语言 |
|
|
|
// do { |
|
|
|
// let langResult = try SPXAutoDetectSourceLanguageResult(result) |
|
|
|
// return langResult.language ?? "" |
|
|
|
// } catch { |
|
|
|
// return "" |
|
|
|
// } |
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 停止连续语音识别 |
|
|
|
@ -388,11 +314,20 @@ public class AzureAsrHelper: NSObject { |
|
|
|
// 创建识别器 |
|
|
|
if isAutoDetectLanguage { |
|
|
|
// 使用正确的初始化方法 |
|
|
|
let autoDetectConfig = try SPXAutoDetectSourceLanguageConfiguration(supportedLanguages) |
|
|
|
print("autoDetectConfig: \(autoDetectConfig)") |
|
|
|
guard let autoDetectSourceLanguageConfig = try? SPXAutoDetectSourceLanguageConfiguration(supportedLanguages) else { |
|
|
|
print("创建自动语言检测配置失败,使用默认语言配置") |
|
|
|
// 如果创建失败,使用默认的单语言配置 |
|
|
|
recognizer = try SPXSpeechRecognizer( |
|
|
|
speechConfiguration: speechConfig!, |
|
|
|
audioConfiguration: audioConfig! |
|
|
|
) |
|
|
|
return true |
|
|
|
} |
|
|
|
|
|
|
|
print("autoDetectConfig: \(autoDetectSourceLanguageConfig)") |
|
|
|
recognizer = try SPXSpeechRecognizer( |
|
|
|
speechConfiguration: speechConfig!, |
|
|
|
autoDetectSourceLanguageConfiguration: autoDetectConfig, |
|
|
|
autoDetectSourceLanguageConfiguration: autoDetectSourceLanguageConfig, |
|
|
|
audioConfiguration: audioConfig! |
|
|
|
) |
|
|
|
} else { |
|
|
|
@ -484,60 +419,7 @@ public class AzureAsrHelper: NSObject { |
|
|
|
return currentLanguage |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 针对翻译场景的性能优化配置 |
|
|
|
*/ |
|
|
|
private func optimizeForTranslation() { |
|
|
|
guard let speechConfig = speechConfig else { return } |
|
|
|
|
|
|
|
// 启用实时转录,减少延迟 |
|
|
|
speechConfig.setPropertyTo("true", byName: "SpeechServiceConnection_EnableAudioLogging") |
|
|
|
speechConfig.setPropertyTo("INTERACTIVE", byName: "SpeechServiceConnection_RecoMode") |
|
|
|
speechConfig.setPropertyTo("PCM", byName: "Speech_PushStreamFormat") |
|
|
|
// 优化语音端点检测,适合翻译场景 |
|
|
|
speechConfig.setPropertyTo("300", byName: "SpeechServiceConnection_InitialSilenceTimeoutMs") |
|
|
|
speechConfig.setPropertyTo("500", byName: "SpeechServiceConnection_EndSilenceTimeoutMs") |
|
|
|
speechConfig.setPropertyTo("500", byName: "Speech_SegmentationSilenceTimeoutMs") |
|
|
|
// 启用标点符号,提高翻译质量 |
|
|
|
speechConfig.setPropertyTo("true", byName: "SpeechServiceResponse_RequestProfanityFilterTrueFalse") |
|
|
|
// 设置分段策略为时间模式 |
|
|
|
speechConfig.setPropertyTo("Time", byName: "Speech_SegmentationStrategy") |
|
|
|
|
|
|
|
// 【优化】语言检测配置 - 减少检测延迟,实现快速响应 |
|
|
|
if isAutoDetectLanguage { |
|
|
|
// 降低语言检测置信度阈值,提高检测灵敏度 |
|
|
|
speechConfig.setPropertyTo("0.3", byName: "SpeechServiceConnection_AutoDetectSourceLanguageConfidenceThreshold") |
|
|
|
|
|
|
|
// 使用Continuous模式,在每句话结束后重新检测语言 |
|
|
|
speechConfig.setPropertyTo("Continuous", byName: "SpeechServiceConnection_LanguageIdMode") |
|
|
|
|
|
|
|
// 启用快速语言检测 |
|
|
|
speechConfig.setPropertyTo("true", byName: "SpeechServiceConnection_EnableLanguageDetectionFast") |
|
|
|
|
|
|
|
// 【关键优化】设置语言检测的最小音频长度为100毫秒,实现快速响应 |
|
|
|
speechConfig.setPropertyTo("100", byName: "SpeechServiceConnection_LanguageDetectionMinAudioLengthMs") |
|
|
|
|
|
|
|
// 【新增】设置语言检测的最大等待时间,避免长时间等待 |
|
|
|
speechConfig.setPropertyTo("2000", byName: "SpeechServiceConnection_LanguageDetectionMaxWaitTimeMs") |
|
|
|
|
|
|
|
// 强制在每个语音段开始时重新检测语言 |
|
|
|
speechConfig.setPropertyTo("true", byName: "SpeechServiceConnection_ForceLanguageDetectionOnNewSegment") |
|
|
|
|
|
|
|
// 【新增】启用句子级别的语言检测 |
|
|
|
speechConfig.setPropertyTo("true", byName: "SpeechServiceConnection_EnableLanguageDetectionPerSentence") |
|
|
|
|
|
|
|
// 【新增】设置语言检测的频率 - 每个识别结果后都检测 |
|
|
|
speechConfig.setPropertyTo("PerResult", byName: "SpeechServiceConnection_LanguageDetectionFrequency") |
|
|
|
|
|
|
|
// 【新增】启用实时语言检测,减少缓冲延迟 |
|
|
|
speechConfig.setPropertyTo("true", byName: "SpeechServiceConnection_EnableRealtimeLanguageDetection") |
|
|
|
|
|
|
|
// 【新增】设置语言检测的采样间隔为200毫秒 |
|
|
|
speechConfig.setPropertyTo("200", byName: "SpeechServiceConnection_LanguageDetectionSamplingIntervalMs") |
|
|
|
} |
|
|
|
|
|
|
|
os_log("翻译场景优化配置已应用,包含语言检测优化", log: log, type: .info) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 动态切换语言(翻译场景中的语言切换) |
|
|
|
@ -588,13 +470,16 @@ public class AzureAsrHelper: NSObject { |
|
|
|
let result = event.result |
|
|
|
guard !(result.text?.isEmpty ?? true) else { return } |
|
|
|
|
|
|
|
// let detectedLanguage = self.getDetectedLanguage(from: result) |
|
|
|
|
|
|
|
// 检测文本语言,避免重复调用 |
|
|
|
let detectedLanguage = self.detectTextLanguage(result.text ?? "") ?? "zh-CN" |
|
|
|
// 使用现有的 getDetectedLanguage 方法替代 result.language |
|
|
|
let detectedLanguage = self.getDetectedLanguage(from: result) |
|
|
|
let text = result.text |
|
|
|
|
|
|
|
print("正在识别事件=检测到语言: \(detectedLanguage), 识别中: \(text)") |
|
|
|
// // 检测文本语言,避免重复调用 |
|
|
|
// let detectedLanguage = self.detectTextLanguage(result.text ?? "") ?? "zh-CN" |
|
|
|
|
|
|
|
// 输出检测到的语言信息 |
|
|
|
print("检测到的语言: \(detectedLanguage)") |
|
|
|
// // 输出检测到的语言信息 |
|
|
|
// print("检测到的语言: \(detectedLanguage)") |
|
|
|
|
|
|
|
DispatchQueue.main.async { |
|
|
|
callback.onRecognizing(result.text ?? "", detectedLanguage) |
|
|
|
@ -608,11 +493,16 @@ public class AzureAsrHelper: NSObject { |
|
|
|
guard result.reason == .recognizedSpeech, |
|
|
|
!(result.text?.isEmpty ?? true) else { return } |
|
|
|
|
|
|
|
// 使用现有的 getDetectedLanguage 方法替代 result.language |
|
|
|
let detectedLanguage = self.getDetectedLanguage(from: result) |
|
|
|
let text = result.text |
|
|
|
|
|
|
|
print("识别完成事件=检测到语言: \(detectedLanguage), 识别中: \(text)") |
|
|
|
// 检测文本语言,避免重复调用 |
|
|
|
let detectedLanguage = self.detectTextLanguage(result.text ?? "") ?? "zh-CN" |
|
|
|
// let detectedLanguage = self.detectTextLanguage(result.text ?? "") ?? "zh-CN" |
|
|
|
|
|
|
|
// 输出检测到的语言信息 |
|
|
|
print("检测到的语言: \(detectedLanguage)") |
|
|
|
// // 输出检测到的语言信息 |
|
|
|
// print("检测到的语言: \(detectedLanguage)") |
|
|
|
|
|
|
|
// 在主线程回调结果 |
|
|
|
DispatchQueue.main.async { |
|
|
|
@ -1175,3 +1065,54 @@ private func runMicrophoneCapture() { |
|
|
|
func onError(_ error: String) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// //ios 语言检测 |
|
|
|
// /** |
|
|
|
// * 检测输入文本的语言,从支持的语言列表中选择最匹配的 |
|
|
|
// * |
|
|
|
// * @param text 需要检测的文本 |
|
|
|
// * @return 从supportedLanguages中选择的最匹配语言代码 |
|
|
|
// */ |
|
|
|
// public func detectTextLanguage(_ text: String) -> String? { |
|
|
|
// // 如果只有一种支持的语言,直接返回 |
|
|
|
// if supportedLanguages.count == 1 { |
|
|
|
// return supportedLanguages[0] |
|
|
|
// } |
|
|
|
|
|
|
|
// // 获取所有可能的语言及其置信度 |
|
|
|
// let languageResults = LanguageDetector.detectLanguageWithConfidence(from: text) |
|
|
|
|
|
|
|
// // 遍历检测结果,找到第一个在supportedLanguages中的语言 |
|
|
|
// for result in languageResults { |
|
|
|
// let azureLanguageCode = LanguageDetector.convertToAzureLanguageCode(result.language) |
|
|
|
// if supportedLanguages.contains(azureLanguageCode) { |
|
|
|
// return azureLanguageCode |
|
|
|
// } |
|
|
|
// } |
|
|
|
|
|
|
|
// // 如果没有找到匹配的语言,返回第一个支持的语言作为默认值 |
|
|
|
// return supportedLanguages.first |
|
|
|
// } |
|
|
|
|
|
|
|
// /** |
|
|
|
// * 检测文本语言并返回详细信息 |
|
|
|
// * |
|
|
|
// * @param text 需要检测的文本 |
|
|
|
// * @return 包含语言代码、置信度和语言名称的字典 |
|
|
|
// */ |
|
|
|
// public func detectTextLanguageWithDetails(_ text: String) -> [String: Any]? { |
|
|
|
// let results = LanguageDetector.detectLanguageWithConfidence(from: text) |
|
|
|
// guard let topResult = results.first else { |
|
|
|
// return nil |
|
|
|
// } |
|
|
|
|
|
|
|
// let azureLanguageCode = LanguageDetector.convertToAzureLanguageCode(topResult.language) |
|
|
|
// let languageName = LanguageDetector.getLanguageName(from: topResult.language) |
|
|
|
|
|
|
|
// return [ |
|
|
|
// "languageCode": azureLanguageCode, |
|
|
|
// "confidence": topResult.confidence, |
|
|
|
// "languageName": languageName, |
|
|
|
// "originalCode": topResult.language |
|
|
|
// ] |
|
|
|
// } |