From 759c2d3ed6174619cc44188e56e81e6686923aa0 Mon Sep 17 00:00:00 2001 From: fdp <1286779656@qq.com> Date: Mon, 23 Jun 2025 11:24:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BC=BA=E5=88=B6=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E6=89=AC=E5=A3=B0=E5=99=A8=E4=B8=8D=E7=94=9F=E6=95=88?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../speech_impl/azure_tts_service.dart | 14 ++++++- .../speech_impl/voice_clone_tts_service.dart | 8 +++- lib/data/services/tts_service.dart | 39 +++++++++---------- .../azure_speech/AzureSpeechPlugin.kt | 6 ++- .../azure_speech/AzureTtsHelper.kt | 6 ++- 5 files changed, 49 insertions(+), 24 deletions(-) diff --git a/lib/data/services/speech_impl/azure_tts_service.dart b/lib/data/services/speech_impl/azure_tts_service.dart index d6eccdf9b..8b2512260 100644 --- a/lib/data/services/speech_impl/azure_tts_service.dart +++ b/lib/data/services/speech_impl/azure_tts_service.dart @@ -413,4 +413,16 @@ class AzureTtsService extends GetxService implements TtsService { Logger.error('释放资源失败: ${e.toString()}'); } } -} \ No newline at end of file + + @override + Future setAudioOutputDevice() async { + try { + // 开始合成,传递参数 + final result = await _channel.invokeMethod('setAudioOutputDevice'); + return result; + } catch (e) { + Logger.error('音频输出设备类型失败: ${e.toString()}'); + return false; + } + } +} diff --git a/lib/data/services/speech_impl/voice_clone_tts_service.dart b/lib/data/services/speech_impl/voice_clone_tts_service.dart index 43079325f..656fe4bcb 100644 --- a/lib/data/services/speech_impl/voice_clone_tts_service.dart +++ b/lib/data/services/speech_impl/voice_clone_tts_service.dart @@ -390,4 +390,10 @@ class VoiceCloneTtsService extends GetxService implements TtsService { Logger.error('释放资源失败: ${e.toString()}'); } } -} \ No newline at end of file + + @override + Future setAudioOutputDevice() { + // TODO: implement setAudioOutputDevice + throw UnimplementedError(); + } +} diff --git a/lib/data/services/tts_service.dart b/lib/data/services/tts_service.dart index 62d938b56..4e2ec3ef4 100644 --- a/lib/data/services/tts_service.dart +++ b/lib/data/services/tts_service.dart @@ -2,52 +2,51 @@ import 'dart:async'; /// 语音合成服务接口 abstract class TtsService { - /// 当前选择的语音 String get currentVoice; - + /// 当前是否正在播放 bool get isSpeaking; - + /// TTS事件流,用于监听语音合成事件 Stream get onEvent; - + /// 初始化语音合成服务 Future initialize({ List? supportedLanguages, }); - + /// 设置语音 Future setVoice(String voiceName); - - + /// 单次播放文本,完成后返回 Future speakOnce(String text); - + /// 将文本加入播放队列,支持连续播放多段文本 Future speakStream(String text); - + /// 播放队列中剩余文本 Future flushStream(); - + /// 停止播放 Future stop(); - + /// 释放资源 Future dispose(); + Future setAudioOutputDevice(); } /// TTS事件类型 enum TtsEventType { /// 开始播放 started, - + /// 播放完成 completed, - + /// 播放取消 canceled, - + /// 播放错误 error, } @@ -56,15 +55,15 @@ enum TtsEventType { class TtsEvent { /// 事件类型 final TtsEventType type; - + /// 错误信息(仅在 error 类型中有效) final String error; - + TtsEvent({ required this.type, this.error = '', }); - + /// 创建错误事件的快捷构造函数 factory TtsEvent.error(String errorMessage) { return TtsEvent( @@ -72,12 +71,12 @@ class TtsEvent { error: errorMessage, ); } - + /// 检查是否为错误 bool get isError => type == TtsEventType.error; - + @override String toString() { return 'TtsEvent{type: $type, error: $error}'; } -} \ No newline at end of file +} diff --git a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureSpeechPlugin.kt b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureSpeechPlugin.kt index 54e960092..498613b8c 100644 --- a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureSpeechPlugin.kt +++ b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureSpeechPlugin.kt @@ -15,7 +15,7 @@ import com.deep_voice.speech.tts.TtsEvent import com.deep_voice.speech.tts.TtsEventListener import com.deep_voice.speech.tts.TtsEventType import com.yunqiinnovation.ble_service.BleService - +import com.deep_voice.speech.tts.AudioOutputDevice /** AzureSpeechPlugin */ class AzureSpeechPlugin : BleService.Callback, FlutterPlugin { private val tag = "AzureSpeechPlugin" @@ -501,6 +501,10 @@ class AzureSpeechPlugin : BleService.Callback, FlutterPlugin { azureTtsHelper.release() result.success(true) } + "setAudioOutputDevice" -> { + azureTtsHelper.setAudioOutputDevice(AudioOutputDevice.SPEAKER) + result.success(true) + } else -> { result.notImplemented() diff --git a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureTtsHelper.kt b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureTtsHelper.kt index ea9d42588..d5444ffb2 100644 --- a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureTtsHelper.kt +++ b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureTtsHelper.kt @@ -223,7 +223,11 @@ class AzureTtsHelper(private val context: Context) : ITtsService { } AudioOutputDevice.SPEAKER -> { // 强制使用扬声器 - manager.mode = AudioManager.MODE_NORMAL + /* MODE_NORMAL 默认媒体模式 ❌ 不能强制扬声器(会被耳机覆盖) + MODE_IN_COMMUNICATION VoIP 通信模式 ✅ 可以强制使用扬声器或听筒 + MODE_IN_CALL 电话模式(仅限系统) ✅ 更强但风险大,不推荐使用 + */ + manager.mode = AudioManager.MODE_IN_COMMUNICATION manager.isSpeakerphoneOn = true } AudioOutputDevice.HEADPHONES -> {