Browse Source

向下兼容16版本

newdev_shunjiawei
fdp 1 year ago
parent
commit
982ee11e7c
  1. 2
      ios/Flutter/AppFrameworkInfo.plist
  2. 4
      ios/Podfile
  3. 4
      ios/Podfile.lock
  4. 6
      ios/Runner.xcodeproj/project.pbxproj
  5. 7
      ios/Runner/Info.plist
  6. 10
      lib/data/services/speech_impl/azure_asr_service.dart
  7. 19
      lib/modules/translation/controllers/translation_controller.dart
  8. 17
      lib/modules/translation/views/translation_view.dart
  9. 2
      local_plugins/agent_service/ios/agent_service/Package.swift
  10. 2
      local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift
  11. 2
      local_plugins/azure_speech/ios/azure_speech/Package.swift
  12. 124
      local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureAsrHelper.swift
  13. 19
      local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureSpeechPlugin.swift
  14. 3
      local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureTtsHelper.swift
  15. 2
      local_plugins/ble_service/ios/ble_service/Package.swift
  16. 2
      local_plugins/chat_storage/ios/chat_storage/Package.swift
  17. 2
      local_plugins/classic_bluetooth/ios/classic_bluetooth.podspec
  18. 2
      local_plugins/music_service/ios/music_service/Package.swift
  19. 2
      local_plugins/realtime/ios/realtime/Package.swift

2
ios/Flutter/AppFrameworkInfo.plist

@ -21,6 +21,6 @@
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>MinimumOSVersion</key> <key>MinimumOSVersion</key>
<string>18.0</string> <string>16.0</string>
</dict> </dict>
</plist> </plist>

4
ios/Podfile

@ -1,5 +1,5 @@
# Define a global platform for your project # Define a global platform for your project
platform :ios, '18.0' platform :ios, '16.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency. # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true' ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@ -44,7 +44,7 @@ post_install do |installer|
# Ensure all pods use the same iOS deployment target # Ensure all pods use the same iOS deployment target
target.build_configurations.each do |config| target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '18.0' config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.0'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)', '$(inherited)',

4
ios/Podfile.lock

@ -177,7 +177,7 @@ SPEC CHECKSUMS:
AMapLocation: 5248aec2455ebb5d104b367813c946430a2ee033 AMapLocation: 5248aec2455ebb5d104b367813c946430a2ee033
AMapNavi: fceb4715f9a3b5a25f330facebee2aa2bdba42dd AMapNavi: fceb4715f9a3b5a25f330facebee2aa2bdba42dd
audio_waveforms: a6dde7fe7c0ea05f06ffbdb0f7c1b2b2ba6cedcf audio_waveforms: a6dde7fe7c0ea05f06ffbdb0f7c1b2b2ba6cedcf
classic_bluetooth: c146e1618e867a47fa7ab79a3bf262e7d69d557d classic_bluetooth: 29f392f1ab7c52862a9ef036c94f2713b02e0c50
FBAEMKit: e34530df538b8eb8aeb53c35867715ba6c63ef0c FBAEMKit: e34530df538b8eb8aeb53c35867715ba6c63ef0c
FBSDKCoreKit: d3f479a69127acebb1c6aad91c1a33907bcf6c2f FBSDKCoreKit: d3f479a69127acebb1c6aad91c1a33907bcf6c2f
FBSDKCoreKit_Basics: 017b6dc2a1862024815a8229e75661e627ac1e29 FBSDKCoreKit_Basics: 017b6dc2a1862024815a8229e75661e627ac1e29
@ -207,6 +207,6 @@ SPEC CHECKSUMS:
WechatOpenSDK-XCFramework: 36fb2bea0754266c17184adf4963d7e6ff98b69f WechatOpenSDK-XCFramework: 36fb2bea0754266c17184adf4963d7e6ff98b69f
wifi_iot: f645260a2be8608517b2a9bf4c39b98e97003acc wifi_iot: f645260a2be8608517b2a9bf4c39b98e97003acc
PODFILE CHECKSUM: 517ecd5ce5153c9609017e05f4e64ab72605e805 PODFILE CHECKSUM: e69e629768e642fde97676ea149350c61d57751e
COCOAPODS: 1.16.2 COCOAPODS: 1.16.2

6
ios/Runner.xcodeproj/project.pbxproj

@ -530,7 +530,7 @@
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Deep Voice"; INFOPLIST_KEY_CFBundleDisplayName = "Deep Voice";
IPHONEOS_DEPLOYMENT_TARGET = 18.0; IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
@ -722,7 +722,7 @@
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Deep Voice"; INFOPLIST_KEY_CFBundleDisplayName = "Deep Voice";
IPHONEOS_DEPLOYMENT_TARGET = 18.0; IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
@ -748,7 +748,7 @@
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Deep Voice"; INFOPLIST_KEY_CFBundleDisplayName = "Deep Voice";
IPHONEOS_DEPLOYMENT_TARGET = 18.0; IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",

7
ios/Runner/Info.plist

@ -72,6 +72,13 @@
</array> </array>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
<key>NSBluetoothAlwaysUsageDescription</key> <key>NSBluetoothAlwaysUsageDescription</key>
<string>需要蓝牙权限用于连接和管理音频设备</string> <string>需要蓝牙权限用于连接和管理音频设备</string>
<key>NSBluetoothPeripheralUsageDescription</key> <key>NSBluetoothPeripheralUsageDescription</key>

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

@ -81,11 +81,11 @@ class AzureAsrService extends GetxService implements AsrService {
try { try {
final List<String> languages = final List<String> languages =
supportedLanguages ?? _defaultSupportedLanguages; supportedLanguages ?? _defaultSupportedLanguages;
//底层会初始化前释放
// 检查是否需要重新初始化 // // 检查是否需要重新初始化
if (_isInitialized) { // if (_isInitialized) {
await dispose(); // await dispose();
} // }
// 设置音频源类型 // 设置音频源类型
_audioSourceType = useExternalAudio _audioSourceType = useExternalAudio

19
lib/modules/translation/controllers/translation_controller.dart

@ -121,13 +121,18 @@ class TranslationController extends GetxController {
// 监听识别结果 // 监听识别结果
if (activeSpeaker.value != 0) { if (activeSpeaker.value != 0) {
isPlayback = false; isPlayback = false;
final recognitionStream = if (id == 1) {
await _asrService.startContinuousRecognition(_audioSourceType); await _asrService.restoreOriginalAudioState();
} else {
await _asrService.disableBluetoothAudio();
}
await _asrService.startContinuousRecognition(_audioSourceType);
lastActiveSpeaker.value = id; lastActiveSpeaker.value = id;
} else { } else {
if (fTFTranslationResult != '' && !isPlayback) { if (fTFTranslationResult != '' && !isPlayback) {
isPlayback = true; isPlayback = true;
print("松开走了着");
await _ttsService.setAudioOutputDevice(lastActiveSpeaker.value); await _ttsService.setAudioOutputDevice(lastActiveSpeaker.value);
await Future.delayed(const Duration(milliseconds: 1300)); await Future.delayed(const Duration(milliseconds: 1300));
await playTranslatedText(fTFTranslationResult!); await playTranslatedText(fTFTranslationResult!);
@ -141,9 +146,11 @@ class TranslationController extends GetxController {
} }
// 禁用蓝牙音频 // 禁用蓝牙音频
void disableBluetoothAudio() => _asrService.disableBluetoothAudio(); Future<void> disableBluetoothAudio() async =>
await _asrService.disableBluetoothAudio();
//恢复原始音频状态 //恢复原始音频状态
void restoreOriginalAudioState() => _asrService.restoreOriginalAudioState(); Future<void> restoreOriginalAudioState() async =>
await _asrService.restoreOriginalAudioState();
// 兼容旧版视图的计算属性 // 兼容旧版视图的计算属性
Rx<TranslationItem?> get currentItem { Rx<TranslationItem?> get currentItem {
@ -337,6 +344,7 @@ class TranslationController extends GetxController {
_translationDebounceTimer?.cancel(); _translationDebounceTimer?.cancel();
scrollController.dispose(); scrollController.dispose();
restoreOtherServices(); restoreOtherServices();
_asrService.dispose();
super.onClose(); super.onClose();
} }
@ -477,9 +485,8 @@ class TranslationController extends GetxController {
if (!isRecognizing.value) return; if (!isRecognizing.value) return;
try { try {
restoreOriginalAudioState();
await _asrService.stopContinuousRecognition(); await _asrService.stopContinuousRecognition();
await _asrService.restoreOriginalAudioState();
isRecognizing.value = false; isRecognizing.value = false;
// 如果当前有中间结果,将其作为最终结果处理 // 如果当前有中间结果,将其作为最终结果处理

17
lib/modules/translation/views/translation_view.dart

@ -109,7 +109,6 @@ class TranslationView extends GetView<TranslationController> {
)), )),
centerTitle: true, centerTitle: true,
actions: [ actions: [
Obx(() { Obx(() {
if (controller.isRecording.value) { if (controller.isRecording.value) {
// 录音中:显示红色计时器样式,点击可停止录音 // 录音中:显示红色计时器样式,点击可停止录音
@ -305,7 +304,8 @@ class TranslationView extends GetView<TranslationController> {
itemCount: itemCount, itemCount: itemCount,
itemBuilder: (context, index) { itemBuilder: (context, index) {
// 如果是最后一项且有更多历史记录,显示加载指示器(reverse模式下) // 如果是最后一项且有更多历史记录,显示加载指示器(reverse模式下)
if (index == controller.translationHistory.length && controller.hasMoreHistory.value) { if (index == controller.translationHistory.length &&
controller.hasMoreHistory.value) {
return _buildLoadMoreIndicator(); return _buildLoadMoreIndicator();
} }
@ -313,7 +313,8 @@ class TranslationView extends GetView<TranslationController> {
final historyIndex = controller.translationHistory.length - 1 - index; final historyIndex = controller.translationHistory.length - 1 - index;
// 检查索引是否有效(reverse模式下的索引验证) // 检查索引是否有效(reverse模式下的索引验证)
if (historyIndex < 0 || historyIndex >= controller.translationHistory.length) { if (historyIndex < 0 ||
historyIndex >= controller.translationHistory.length) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
@ -460,8 +461,6 @@ class TranslationView extends GetView<TranslationController> {
child: Obx(() { child: Obx(() {
// 同时模式显示双按钮 // 同时模式显示双按钮
if (controller.currentMode.value == 'faceToFace') { if (controller.currentMode.value == 'faceToFace') {
controller.startRecognition();
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
@ -592,11 +591,6 @@ class TranslationView extends GetView<TranslationController> {
// 设置300ms延迟防止误触 // 设置300ms延迟防止误触
_holdTimer = Timer(const Duration(milliseconds: 200), () { _holdTimer = Timer(const Duration(milliseconds: 200), () {
if (activeSpeaker == 0) { if (activeSpeaker == 0) {
if (speakerId == 1) {
controller.restoreOriginalAudioState();
} else {
controller.disableBluetoothAudio();
}
controller.setActiveSpeaker(speakerId); controller.setActiveSpeaker(speakerId);
} }
}); });
@ -802,7 +796,8 @@ class TranslationView extends GetView<TranslationController> {
child: GestureDetector( child: GestureDetector(
onTap: () => controller.loadMoreHistory(), onTap: () => controller.loadMoreHistory(),
child: Container( child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), padding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.red[50], color: Colors.red[50],
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),

2
local_plugins/agent_service/ios/agent_service/Package.swift

@ -3,7 +3,7 @@ import PackageDescription
let package = Package( let package = Package(
name: "agent_service", name: "agent_service",
platforms: [.iOS("18.0")], platforms: [.iOS("16.0")],
products: [ products: [
.library(name: "agent-service", targets: ["agent_service"]) .library(name: "agent-service", targets: ["agent_service"])
], ],

2
local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift

@ -324,7 +324,7 @@ class AgentServiceImpl: NSObject {
} else { } else {
AudioSessionHub.shared.begin(.voice) AudioSessionHub.shared.begin(.voice)
} }
print("ai启动语音=\(audioSourceType)=\(useBle)")
guard let success = azureAsrHelper?.startContinuousRecognition( guard let success = azureAsrHelper?.startContinuousRecognition(
// callback: self, // callback: self,
audioSourceType: audioSourceType audioSourceType: audioSourceType

2
local_plugins/azure_speech/ios/azure_speech/Package.swift

@ -3,7 +3,7 @@ import PackageDescription
let package = Package( let package = Package(
name: "azure_speech", name: "azure_speech",
platforms: [.iOS("18.0")], platforms: [.iOS("16.0")],
products: [ products: [
.library(name: "azure-speech", targets: ["azure_speech"]) .library(name: "azure-speech", targets: ["azure_speech"])
], ],

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

@ -149,7 +149,7 @@ public class AzureAsrHelper: NSObject {
return false return false
} }
// 启动音频处理 // 启动音频处理
audioStream?.startAudioInput() audioStream?.startAudioInput(audioSourceType: audioSourceType)
// 开始连续识别 // 开始连续识别
try recognizer?.startContinuousRecognition() try recognizer?.startContinuousRecognition()
@ -172,7 +172,6 @@ public class AzureAsrHelper: NSObject {
* @return 是否成功停止 * @return 是否成功停止
*/ */
public func stopContinuousRecognition() -> Bool { public func stopContinuousRecognition() -> Bool {
print("stopContinuousRecognition")
guard speechConfig != nil else { guard speechConfig != nil else {
os_log("语音服务未初始化", log: log, type: .error) os_log("语音服务未初始化", log: log, type: .error)
return false return false
@ -238,7 +237,7 @@ public class AzureAsrHelper: NSObject {
recognizer = nil recognizer = nil
speechConfig = nil speechConfig = nil
audioConfig = nil audioConfig = nil
audioStream = nil
// 确保状态被重置 // 确保状态被重置
_isContinuousRecognitionActive = false _isContinuousRecognitionActive = false
//externalAudioStream = nil //externalAudioStream = nil
@ -249,6 +248,7 @@ public class AzureAsrHelper: NSObject {
audioConfig = nil audioConfig = nil
recognizer = nil recognizer = nil
speechConfig = nil speechConfig = nil
audioStream = nil
} }
} }
@ -302,7 +302,7 @@ public class AzureAsrHelper: NSObject {
if (audioStream == nil) { if (audioStream == nil) {
// 创建外部音频拉流对象 // 创建外部音频拉流对象
// 明确指定使用外部音频源(推流模式) // 明确指定使用外部音频源(推流模式)
audioStream = AudioStream(audioSourceType: audioSourceType) audioStream = AudioStream()
audioStream?.initAudioRecord() audioStream?.initAudioRecord()
} }
@ -328,28 +328,29 @@ public class AzureAsrHelper: NSObject {
return false return false
} }
guard let recognizer = recognizer else { return false} guard let recognizer = recognizer else { return false}
// 识别中事件 // 正在识别事件
recognizer.addRecognizingEventHandler { [weak self] (sender, event) in recognizer.addRecognizingEventHandler { [weak self] (_, event) in
guard let self = self else { return } guard let self = self else { return }
print("识别中事件:") let result = event.result
let result = event.result let detectedLanguage = self.detectLanguage(from: result)
let detectedLanguage = self.getDetectedLanguage(from: result) print("识别中事件: \(detectedLanguage)")
// os_log("识别中: %{public}@", log: self.log, type: .info, result.text ?? "") DispatchQueue.main.async {
// 直接在当前线程调用回调
callback.onRecognizing(result.text ?? "", detectedLanguage) callback.onRecognizing(result.text ?? "", detectedLanguage)
} }
}
// 识别完成事件
recognizer.addRecognizedEventHandler { [weak self] (sender, event) in // 识别完成事件
guard let self = self else { return } recognizer.addRecognizedEventHandler { [weak self] (_, event) in
print("识别完成事件:") guard let self = self else { return }
let result = event.result let result = event.result
if result.reason == SPXResultReason.recognizedSpeech { if result.reason == .recognizedSpeech {
let detectedLanguage = self.getDetectedLanguage(from: result) let detectedLanguage = self.detectLanguage(from: result)
// 直接在当前线程调用回调 print("识别完成事件: \(detectedLanguage)")
DispatchQueue.main.async {
callback.onResult(result.text ?? "", detectedLanguage) callback.onResult(result.text ?? "", detectedLanguage)
} }
} }
}
// 会话开始事件 // 会话开始事件
recognizer.addSessionStartedEventHandler { (sender, event) in recognizer.addSessionStartedEventHandler { (sender, event) in
@ -381,7 +382,16 @@ public class AzureAsrHelper: NSObject {
} }
return true return true
} }
// 提取的辅助方法
private func detectLanguage(from result: SPXSpeechRecognitionResult) -> String {
if isAutoDetectLanguage {
let langResult = try SPXAutoDetectSourceLanguageResult(result)
return langResult.language ?? ""
} else {
return currentLanguage
}
}
/** /**
* 获取检测到的语言 * 获取检测到的语言
*/ */
@ -399,6 +409,7 @@ public class AzureAsrHelper: NSObject {
// 尝试另一种方式获取语言 // 尝试另一种方式获取语言
do { do {
let langResult = try SPXAutoDetectSourceLanguageResult(result) let langResult = try SPXAutoDetectSourceLanguageResult(result)
print("获取检测到的语言")
return langResult.language ?? "" return langResult.language ?? ""
} catch { } catch {
return "" return ""
@ -490,24 +501,26 @@ public class AzureAsrHelper: NSObject {
private let writeQueue = LinkedBlockingQueue<Data>() private let writeQueue = LinkedBlockingQueue<Data>()
private var audioEngine: AVAudioEngine? private var audioEngine: AVAudioEngine?
private var audioFormat: AVAudioFormat? private var audioFormat: AVAudioFormat?
private let audioSourceType: AudioSourceType // 添加引用 private let audioSession = AVAudioSession.sharedInstance()
private var audioSourceType = AudioSourceType.microphone
private var isRunning = false private var isRunning = false
public var isWriting = false public var isWriting = false
private let bufferSize: Int = 4096 private let bufferSize: Int = 4096
private let writeThread = DispatchQueue(label: "audio.stream.writer") private var writeThread: DispatchQueue?
private var currentRoute: AudioOutputRoute?
init(audioSourceType: AudioSourceType) {
self.audioSourceType = audioSourceType
}
/** /**
* 初始化 * 初始化
*/ */
public func initAudioRecord() { public func initAudioRecord() {
print("初始化了")
audioFormat = getOptimalAudioFormat() audioFormat = getOptimalAudioFormat()
pushAudioStream = SPXPushAudioInputStream() pushAudioStream = SPXPushAudioInputStream()
isRunning=true isRunning=true
// 创建新的写线程
writeThread = DispatchQueue(label: "audio.stream.writer")
startWriteThread() startWriteThread()
self.setAudioOutputRoute(.receiver)
} }
/// 获取最佳音频格式 (iOS 通常支持标准采样率) /// 获取最佳音频格式 (iOS 通常支持标准采样率)
@ -523,8 +536,9 @@ public class AzureAsrHelper: NSObject {
/** /**
* 开始音频输入 * 开始音频输入
*/ */
public func startAudioInput() { public func startAudioInput(audioSourceType: AudioSourceType = .microphone) {
isWriting=true isWriting=true
self.audioSourceType = audioSourceType;
print("startAudioInput=audioSourceType\(audioSourceType)") print("startAudioInput=audioSourceType\(audioSourceType)")
switch audioSourceType { switch audioSourceType {
case .microphone: case .microphone:
@ -538,10 +552,11 @@ public class AzureAsrHelper: NSObject {
* 开启音频写入线程 * 开启音频写入线程
*/ */
public func startWriteThread() { public func startWriteThread() {
writeThread.async { [weak self] in writeThread?.async { [weak self] in
guard let self = self else { return } guard let self = self else { return }
while self.isRunning { while self.isRunning {
print("是否写入: \(self.isWriting)")
if !self.isWriting { if !self.isWriting {
usleep(10_000) usleep(10_000)
continue continue
@ -549,7 +564,7 @@ public class AzureAsrHelper: NSObject {
guard let dataToWrite = self.writeQueue.take() else { continue } guard let dataToWrite = self.writeQueue.take() else { continue }
//print("写入数据长度: \(dataToWrite.count)") print("写入数据长度: \(dataToWrite.count)")
self.pushAudioStream?.write(dataToWrite) self.pushAudioStream?.write(dataToWrite)
} }
} }
@ -565,14 +580,13 @@ public class AzureAsrHelper: NSObject {
if audioSourceType != .external { if audioSourceType != .external {
return return
} }
print("外部data=\(data)")
// 放入队列,由写线程写入 // 放入队列,由写线程写入
writeQueue.put(data) writeQueue.put(data)
} }
private func runMicrophoneCapture() { private func runMicrophoneCapture() {
do { do {
//self.setAudioOutputRoute(.speaker)
audioEngine = AVAudioEngine() audioEngine = AVAudioEngine()
guard let inputNode = audioEngine?.inputNode else { guard let inputNode = audioEngine?.inputNode else {
throw NSError(domain: "AudioSetup", code: 1) throw NSError(domain: "AudioSetup", code: 1)
@ -622,8 +636,10 @@ public class AzureAsrHelper: NSObject {
} }
} }
// 重新激活
try audioEngine?.start() try audioSession.setActive(true, options: [.notifyOthersOnDeactivation])
try audioEngine?.start()
} catch { } catch {
print("麦克风启动失败: \(error)") print("麦克风启动失败: \(error)")
} }
@ -664,23 +680,27 @@ public class AzureAsrHelper: NSObject {
if audioSourceType == .external { if audioSourceType == .external {
//pushAudioData(data: Data()) //pushAudioData(data: Data())
audioEngine?.stop() audioEngine?.pause()
audioEngine?.inputNode.removeTap(onBus: 0) //audioEngine?.inputNode.removeTap(onBus: 0)
} }
} }
public func stopAudioCapture() { public func stopAudioCapture() {
guard isWriting==true else { return } guard isWriting==true else { return }
print("stopContinuousRecognition")
isWriting=false isWriting=false
audioEngine?.stop() audioEngine?.pause()
audioEngine?.inputNode.removeTap(onBus: 0) audioEngine?.inputNode.removeTap(onBus: 0)
writeThread.async { writeThread?.async {
self.writeQueue.close() self.writeQueue.close()
} }
} }
public func releaseAudioResources() { public func releaseAudioResources() {
print("释放了")
stopAudioCapture() stopAudioCapture()
audioEngine?.stop()
writeThread = nil
audioEngine?.inputNode.removeTap(onBus: 0)
isRunning=false isRunning=false
audioEngine = nil audioEngine = nil
} }
@ -692,13 +712,18 @@ public class AzureAsrHelper: NSObject {
case bluetooth case bluetooth
} }
public func setAudioOutputRoute(_ route: AudioOutputRoute) { public func setAudioOutputRoute(_ route: AudioOutputRoute) {
let audioSession = AVAudioSession.sharedInstance() guard currentRoute != route else { return }
print("setAudioOutputRoute")
do { do {
isWriting=false //
try audioEngine?.stop() if self.isWriting {
print("当前正在识别")
try audioEngine?.pause()
// 先停用以避免冲突 // 先停用以避免冲突
try audioSession.setActive(false) try audioSession.setActive(false)
}
switch route { switch route {
case .speaker: case .speaker:
// 使用扬声器时必须用videoChat模式 // 使用扬声器时必须用videoChat模式
@ -728,12 +753,17 @@ public class AzureAsrHelper: NSObject {
try audioSession.overrideOutputAudioPort(.none) try audioSession.overrideOutputAudioPort(.none)
// 不需要override,系统自动路由 // 不需要override,系统自动路由
} }
self.currentRoute = route
if self.isWriting {
// 重新激活 // 重新激活
try audioSession.setActive(true, options: [.notifyOthersOnDeactivation]) try audioSession.setActive(true, options: [.notifyOthersOnDeactivation])
try audioEngine?.start() try audioEngine?.start()
isWriting=true writeThread?.async {
self.writeQueue.close()
}
}
} catch { } catch {
print("路由切换失败: \(error)") print("路由切换失败: \(error)")
} }

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

@ -185,6 +185,7 @@ import os.log
) )
result(success) result(success)
case "stopContinuousRecognition": case "stopContinuousRecognition":
let success = azureAsrHelper.stopContinuousRecognition() let success = azureAsrHelper.stopContinuousRecognition()
currentAsrCallback = nil currentAsrCallback = nil
result(success) result(success)
@ -277,16 +278,16 @@ import os.log
} }
case "disableBluetoothAudio": case "disableBluetoothAudio":
print("disableBluetoothAudio") print("disableBluetoothAudio")
azureAsrHelper.disableBluetoothAudio(); azureAsrHelper.disableBluetoothAudio();
azureTtsHelper.setAudioOutputDevice() azureTtsHelper.stop()
result(true) result(true)
case "restoreOriginalAudioState": case "restoreOriginalAudioState":
print("restoreOriginalAudioState") print("restoreOriginalAudioState")
azureAsrHelper.restoreOriginalAudioState(); azureAsrHelper.restoreOriginalAudioState();
azureTtsHelper.setAudioOutputDevice() azureTtsHelper.stop()
result(true) result(true)
default: default:
@ -369,18 +370,18 @@ import os.log
if (type == 0) { if (type == 0) {
// 默认(如果有耳机选耳机,否则使用系统扬声器) // 默认(如果有耳机选耳机,否则使用系统扬声器)
azureAsrHelper.restoreOriginalAudioState(); azureAsrHelper.restoreOriginalAudioState();
azureTtsHelper.setAudioOutputDevice() // azureTtsHelper.setAudioOutputDevice()
} else if (type == 1) { } else if (type == 1) {
// 强制使用声器 // 强制使用声器
azureAsrHelper.disableBluetoothAudio(); azureAsrHelper.disableBluetoothAudio();
azureTtsHelper.setAudioOutputDevice() // azureTtsHelper.setAudioOutputDevice()
} else if (type == 2) { } else if (type == 2) {
// 强制使用耳机 // 强制使用耳机
azureAsrHelper.restoreOriginalAudioState(); azureAsrHelper.restoreOriginalAudioState();
azureTtsHelper.setAudioOutputDevice() //azureTtsHelper.setAudioOutputDevice()
} }
@ -405,7 +406,7 @@ private class AsrCallbackWrapper: AzureAsrHelper.ContinuousRecognizeCallback {
plugin?.sendAsrEvent([ plugin?.sendAsrEvent([
"type": "result", "type": "result",
"text": text, "text": text,
"language": detectedLanguage "detectedLanguage": detectedLanguage
]) ])
} }
@ -413,7 +414,7 @@ private class AsrCallbackWrapper: AzureAsrHelper.ContinuousRecognizeCallback {
plugin?.sendAsrEvent([ plugin?.sendAsrEvent([
"type": "recognizing", "type": "recognizing",
"text": recognizing, "text": recognizing,
"language": detectedLanguage "detectedLanguage": detectedLanguage
]) ])
} }

3
local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureTtsHelper.swift

@ -308,9 +308,10 @@ public class AzureTtsHelper: NSObject, ITtsService {
// 重新创建合成器以应用新设备 // 重新创建合成器以应用新设备
if isInitialized { if isInitialized {
print(" 重新创建合成器以应用新设备")
recreateSynthesizer() recreateSynthesizer()
} }
// 如果之前正在播放,恢复播放 // 如果之前正在播放,恢复播放
if wasSpeaking, let lastText = lastSpokenText { if wasSpeaking, let lastText = lastSpokenText {
speakOnce(lastText) speakOnce(lastText)

2
local_plugins/ble_service/ios/ble_service/Package.swift

@ -3,7 +3,7 @@ import PackageDescription
let package = Package( let package = Package(
name: "ble_service", name: "ble_service",
platforms: [.iOS("18.0")], platforms: [.iOS("16.0")],
products: [ products: [
.library(name: "ble-service", targets: ["ble_service"]) .library(name: "ble-service", targets: ["ble_service"])
], ],

2
local_plugins/chat_storage/ios/chat_storage/Package.swift

@ -3,7 +3,7 @@ import PackageDescription
let package = Package( let package = Package(
name: "chat_storage", name: "chat_storage",
platforms: [.iOS("18.0")], platforms: [.iOS("16.0")],
products: [ products: [
.library(name: "chat-storage", targets: ["chat_storage"]) .library(name: "chat-storage", targets: ["chat_storage"])
], ],

2
local_plugins/classic_bluetooth/ios/classic_bluetooth.podspec

@ -13,7 +13,7 @@ Pod::Spec.new do |s|
s.author = { 'YunQi Innovation' => 'support@yunqiinnovation.com' } s.author = { 'YunQi Innovation' => 'support@yunqiinnovation.com' }
s.source = { :path => '.' } s.source = { :path => '.' }
s.source_files = 'Classes/**/*' s.source_files = 'Classes/**/*'
s.ios.deployment_target = '18.0' s.ios.deployment_target = '16.0'
s.dependency 'Flutter' s.dependency 'Flutter'
s.swift_version = '5.0' s.swift_version = '5.0'

2
local_plugins/music_service/ios/music_service/Package.swift

@ -3,7 +3,7 @@ import PackageDescription
let package = Package( let package = Package(
name: "music_service", name: "music_service",
platforms: [.iOS("18.0")], platforms: [.iOS("16.0")],
products: [ products: [
.library(name: "music-service", targets: ["music_service"]) .library(name: "music-service", targets: ["music_service"])
], ],

2
local_plugins/realtime/ios/realtime/Package.swift

@ -3,7 +3,7 @@ import PackageDescription
let package = Package( let package = Package(
name: "realtime", name: "realtime",
platforms: [.iOS("18.0")], platforms: [.iOS("16.0")],
products: [ products: [
.library(name: "realtime", targets: ["realtime"]) .library(name: "realtime", targets: ["realtime"])
], ],

Loading…
Cancel
Save