Browse Source

feat(azure_speech): 添加讯飞语音识别配置参数支持

在Azure语音识别插件中添加对讯飞语音识别服务的配置参数支持,包括appId、accessKeyId和accessKeySecret。这些参数现在可以通过初始化方法传递,并在Android和iOS平台实现相应的配置更新逻辑。

当支持的语言仅为中文或英文且讯飞配置完整时,自动启用讯飞语音识别服务。
weicu
lxm 9 months ago
parent
commit
50d1bcd9a8
  1. 9
      lib/data/services/speech_impl/azure_asr_service.dart
  2. 31
      local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt
  3. 8
      local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureSpeechPlugin.kt
  4. 34
      local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/XunFeiAsrHelper.kt
  5. 28
      local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureAsrHelper.swift
  6. 8
      local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureSpeechPlugin.swift
  7. 32
      local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/XunFeiAsrHelper.swift

9
lib/data/services/speech_impl/azure_asr_service.dart

@ -29,6 +29,9 @@ class AzureAsrService extends GetxService implements AsrService {
bool _isInitialized = false;
late final String _subscriptionKey;
late final String _serviceRegion;
late final String _xunfeiAppId;
late final String _xunfeiAccessKeyId;
late final String _xunfeiAccessKeySecret;
final List<String> _defaultSupportedLanguages = ['zh-CN', 'en-US'];
@override
@ -69,6 +72,9 @@ class AzureAsrService extends GetxService implements AsrService {
// final _env = _storage.read("ENV") as Map<String, String>;
_subscriptionKey = AppConfig.env('AZURE_SPEECH_KEY') ?? '';
_serviceRegion = AppConfig.env('AZURE_SPEECH_REGION') ?? '';
_xunfeiAppId = AppConfig.env('XUNFEI_ASR_APP_ID') ?? '';
_xunfeiAccessKeyId = AppConfig.env('XUNFEI_ASR_ACCESS_KEY_ID') ?? '';
_xunfeiAccessKeySecret = AppConfig.env('XUNFEI_ASR_ACCESS_KEY_SECRET') ?? '';
if (_subscriptionKey.isEmpty || _serviceRegion.isEmpty) {
throw Exception(
@ -125,6 +131,9 @@ class AzureAsrService extends GetxService implements AsrService {
'supportedLanguages': languages,
'audioSourceType': _audioSourceType.toString().split('.').last,
'useEchoCancellation': useEchoCancellation,
'xunfeiAppId': _xunfeiAppId,
'xunfeiAccessKeyId': _xunfeiAccessKeyId,
'xunfeiAccessKeySecret': _xunfeiAccessKeySecret,
});
_setupEventChannel();

31
local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt

@ -44,6 +44,9 @@ class AzureAsrHelper(private val context: Context) {
private var useXunfei = false
private var xunFeiAsrHelper: XunFeiAsrHelper? = null
private var xunfeiAppId: String = ""
private var xunfeiAccessKeyId: String = ""
private var xunfeiAccessKeySecret: String = ""
// 音频源配置
var audioSourceType = AudioSourceType.MICROPHONE
@ -92,7 +95,10 @@ class AzureAsrHelper(private val context: Context) {
subscriptionKey: String,
region: String,
supportedLanguages: Array<String> = arrayOf("zh-CN", "en-US"),
audioSourceType: AudioSourceType = AudioSourceType.MICROPHONE
audioSourceType: AudioSourceType = AudioSourceType.MICROPHONE,
xunfeiAppId: String = "",
xunfeiAccessKeyId: String = "",
xunfeiAccessKeySecret: String = ""
): Boolean {
try {
// 检查配置是否为空
@ -108,13 +114,19 @@ class AzureAsrHelper(private val context: Context) {
this.subscriptionKey = subscriptionKey
this.region = region
this.audioSourceType = audioSourceType
this.xunfeiAppId = xunfeiAppId
this.xunfeiAccessKeyId = xunfeiAccessKeyId
this.xunfeiAccessKeySecret = xunfeiAccessKeySecret
// 设置语言
if (supportedLanguages.isNotEmpty()) {
this.supportedLanguages = supportedLanguages
}
this.useXunfei = supportedLanguages.all { it == "zh-CN" || it == "en-US" }
val xunfeiConfigReady = this.xunfeiAppId.isNotBlank() &&
this.xunfeiAccessKeyId.isNotBlank() &&
this.xunfeiAccessKeySecret.isNotBlank()
this.useXunfei = supportedLanguages.all { it == "zh-CN" || it == "en-US" } && xunfeiConfigReady
// 根据支持的语言数量决定是否启用自动语言检测
this.isAutoDetectLanguage = supportedLanguages.size >= 2
@ -283,7 +295,18 @@ class AzureAsrHelper(private val context: Context) {
}
if (xunFeiAsrHelper == null) {
xunFeiAsrHelper = XunFeiAsrHelper(context)
xunFeiAsrHelper = XunFeiAsrHelper(
context = context,
appId = xunfeiAppId,
accessKeyId = xunfeiAccessKeyId,
accessKeySecret = xunfeiAccessKeySecret
)
} else {
xunFeiAsrHelper?.updateConfig(
appId = xunfeiAppId,
accessKeyId = xunfeiAccessKeyId,
accessKeySecret = xunfeiAccessKeySecret
)
}
try {
@ -904,4 +927,4 @@ class AzureAsrHelper(private val context: Context) {
}

8
local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureSpeechPlugin.kt

@ -413,6 +413,9 @@ class AzureSpeechPlugin : BleService.Callback, FlutterPlugin {
val supportedLanguages =
call.argument<List<String>>("supportedLanguages") ?: listOf("zh-CN")
val useExternalAudio = call.argument<Boolean>("useExternalAudio") ?: false
val xunfeiAppId = call.argument<String>("xunfeiAppId") ?: ""
val xunfeiAccessKeyId = call.argument<String>("xunfeiAccessKeyId") ?: ""
val xunfeiAccessKeySecret = call.argument<String>("xunfeiAccessKeySecret") ?: ""
try {
FileLogger.d(tag, "选择音频源类型: ${useExternalAudio}") //
@ -428,6 +431,9 @@ class AzureSpeechPlugin : BleService.Callback, FlutterPlugin {
region = region,
supportedLanguages = supportedLanguages.toTypedArray(),
audioSourceType = audioSourceType,
xunfeiAppId = xunfeiAppId,
xunfeiAccessKeyId = xunfeiAccessKeyId,
xunfeiAccessKeySecret = xunfeiAccessKeySecret,
)
result.success(success)
@ -1212,4 +1218,4 @@ class AzureSpeechPlugin : BleService.Callback, FlutterPlugin {
}
}

34
local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/XunFeiAsrHelper.kt

@ -15,12 +15,16 @@ import java.util.UUID
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
// 讯飞语音识别助手
//调用讯飞开放平台的实时语音转写大模型接口
// 参考文档:https://www.xfyun.cn/doc/spark/asr_llm/rtasr_llm.html
class XunFeiAsrHelper(private val context: Context) {
private val tag = "XunFeiAsrHelper"
private val appId = "43d87d22"
private val accessKeyId = "2bd01ce06ac35957fc0c082f9b6284ec"
private val accessKeySecret = "ODU3OTUyYjhjMjY5NDhkMmMxYWY2Zjlm"
private var appId: String = ""
private var accessKeyId: String = ""
private var accessKeySecret: String = ""
private var webSocket: WebSocket? = null
private val client = OkHttpClient()
@ -35,6 +39,25 @@ class XunFeiAsrHelper(private val context: Context) {
// 是否第去除一个文字的标点符号
private var removeFirstPunctuation = true
constructor(
context: Context,
appId: String,
accessKeyId: String,
accessKeySecret: String
) : this(context) {
updateConfig(appId = appId, accessKeyId = accessKeyId, accessKeySecret = accessKeySecret)
}
fun updateConfig(appId: String, accessKeyId: String, accessKeySecret: String) {
this.appId = appId
this.accessKeyId = accessKeyId
this.accessKeySecret = accessKeySecret
}
private fun isConfigValid(): Boolean {
return appId.isNotBlank() && accessKeyId.isNotBlank() && accessKeySecret.isNotBlank()
}
fun start(callback: AzureAsrHelper.ContinuousRecognizeCallback, language: String, isAutoDetect: Boolean, isRemoveFirstPunctuation: Boolean) {
try {
webSocket?.cancel()
@ -50,6 +73,11 @@ class XunFeiAsrHelper(private val context: Context) {
isAutoDetectLanguage = isAutoDetect
removeFirstPunctuation = isRemoveFirstPunctuation
if (!isConfigValid()) {
callback.onError(currentSessionId, 1007, "Xunfei config missing")
return
}
val url = getWebSocketUrl()
val request = Request.Builder().url(url).build()

28
local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureAsrHelper.swift

@ -59,6 +59,9 @@ public class AzureAsrHelper: NSObject {
private var useXunfei = false
private var xunFeiAsrHelper: XunFeiAsrHelper?
private var xunfeiAppId: String = ""
private var xunfeiAccessKeyId: String = ""
private var xunfeiAccessKeySecret: String = ""
// 音频源配置
public enum AudioSourceType {
@ -94,7 +97,10 @@ public class AzureAsrHelper: NSObject {
subscriptionKey: String,
region: String,
supportedLanguages: [String] = ["zh-CN", "en-US"],
audioSourceType: AudioSourceType = .microphone
audioSourceType: AudioSourceType = .microphone,
xunfeiAppId: String = "",
xunfeiAccessKeyId: String = "",
xunfeiAccessKeySecret: String = ""
) -> Bool {
do {
// 检查配置是否为空
@ -109,6 +115,9 @@ public class AzureAsrHelper: NSObject {
self.subscriptionKey = subscriptionKey
self.region = region
self.audioSourceType = audioSourceType
self.xunfeiAppId = xunfeiAppId
self.xunfeiAccessKeyId = xunfeiAccessKeyId
self.xunfeiAccessKeySecret = xunfeiAccessKeySecret
// 设置语言
if !supportedLanguages.isEmpty {
@ -116,7 +125,10 @@ public class AzureAsrHelper: NSObject {
}
// 检查是否只包含中文或英文,如果是则使用讯飞
self.useXunfei = supportedLanguages.allSatisfy { $0 == "zh-CN" || $0 == "en-US" }
let xunfeiConfigReady = !self.xunfeiAppId.isEmpty &&
!self.xunfeiAccessKeyId.isEmpty &&
!self.xunfeiAccessKeySecret.isEmpty
self.useXunfei = supportedLanguages.allSatisfy { $0 == "zh-CN" || $0 == "en-US" } && xunfeiConfigReady
// 根据支持的语言数量决定是否启用自动语言检测
self.isAutoDetectLanguage = supportedLanguages.count >= 2
@ -430,7 +442,17 @@ public class AzureAsrHelper: NSObject {
}
if xunFeiAsrHelper == nil {
xunFeiAsrHelper = XunFeiAsrHelper()
xunFeiAsrHelper = XunFeiAsrHelper(
appId: xunfeiAppId,
accessKeyId: xunfeiAccessKeyId,
accessKeySecret: xunfeiAccessKeySecret
)
} else {
xunFeiAsrHelper?.updateConfig(
appId: xunfeiAppId,
accessKeyId: xunfeiAccessKeyId,
accessKeySecret: xunfeiAccessKeySecret
)
}
// 启动讯飞识别

8
local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureSpeechPlugin.swift

@ -336,13 +336,19 @@ private func sendAstEvent(_ event: [String: Any]) {
}
let supportedLanguages = args["supportedLanguages"] as? [String] ?? ["zh-CN"]
let xunfeiAppId = args["xunfeiAppId"] as? String ?? ""
let xunfeiAccessKeyId = args["xunfeiAccessKeyId"] as? String ?? ""
let xunfeiAccessKeySecret = args["xunfeiAccessKeySecret"] as? String ?? ""
// 初始化ASR引擎
let success = azureAsrHelper.initialize(
subscriptionKey: subscriptionKey,
region: region,
supportedLanguages: supportedLanguages,
audioSourceType: .microphone
audioSourceType: .microphone,
xunfeiAppId: xunfeiAppId,
xunfeiAccessKeyId: xunfeiAccessKeyId,
xunfeiAccessKeySecret: xunfeiAccessKeySecret
)
result(success)

32
local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/XunFeiAsrHelper.swift

@ -1,12 +1,16 @@
import Foundation
import CryptoKit
// 讯飞语音识别助手
//调用讯飞开放平台的实时语音转写大模型接口
// 参考文档:https://www.xfyun.cn/doc/spark/asr_llm/rtasr_llm.html
class XunFeiAsrHelper: NSObject, URLSessionWebSocketDelegate {
private let tag = "XunFeiAsrHelper"
private let appId = "43d87d22"
private let accessKeyId = "2bd01ce06ac35957fc0c082f9b6284ec"
private let accessKeySecret = "ODU3OTUyYjhjMjY5NDhkMmMxYWY2Zjlm"
private var appId: String
private var accessKeyId: String
private var accessKeySecret: String
private var webSocketTask: URLSessionWebSocketTask?
private lazy var session: URLSession = {
@ -26,6 +30,23 @@ class XunFeiAsrHelper: NSObject, URLSessionWebSocketDelegate {
private var callback: AzureAsrHelper.ContinuousRecognizeCallback?
init(appId: String, accessKeyId: String, accessKeySecret: String) {
self.appId = appId
self.accessKeyId = accessKeyId
self.accessKeySecret = accessKeySecret
super.init()
}
func updateConfig(appId: String, accessKeyId: String, accessKeySecret: String) {
self.appId = appId
self.accessKeyId = accessKeyId
self.accessKeySecret = accessKeySecret
}
private func isConfigValid() -> Bool {
return !appId.isEmpty && !accessKeyId.isEmpty && !accessKeySecret.isEmpty
}
func start(callback: AzureAsrHelper.ContinuousRecognizeCallback, language: String, isAutoDetect: Bool, isRemoveFirstPunctuation: Bool) {
stop()
@ -37,6 +58,11 @@ class XunFeiAsrHelper: NSObject, URLSessionWebSocketDelegate {
self.lastIntermediateResult = ""
self.sessionId = ""
if !isConfigValid() {
callback.onError(sessionid: self.currentSessionId, 1007, "Xunfei config missing")
return
}
let urlString = getWebSocketUrl()
guard let url = URL(string: urlString) else {
print("\(tag): Invalid URL")

Loading…
Cancel
Save