Browse Source

优化按住说话

newdev_shunjiawei
fdp 1 year ago
parent
commit
e7c04c6dca
  1. 4
      lib/data/services/music_manager.dart
  2. 88
      lib/modules/agent/controllers/agent_controller.dart
  3. 12
      local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt
  4. 18
      local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt
  5. 2
      local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicService.kt
  6. 6
      local_plugins/music_service/lib/music_service.dart

4
lib/data/services/music_manager.dart

@ -105,7 +105,7 @@ class MusicManager extends GetxService {
required Function() onPrevious,
required Function(int) onSeekTo,
required Function() onStop,
required Function(int, int, int, double) onStop1,
required Function(int, int, int, double) onProgress,
}) async {
try {
await _musicService.setMediaSessionCallbacks(
@ -115,7 +115,7 @@ class MusicManager extends GetxService {
onPrevious: onPrevious,
onSeekTo: onSeekTo,
onStop: onStop,
onStop1: onStop1,
onProgress: onProgress,
);
} catch (e) {
Logger.d('MusicManager', '设置媒体会话回调失败: $e');

88
lib/modules/agent/controllers/agent_controller.dart

@ -165,7 +165,7 @@ class AgentController extends GetxController {
onPrevious: onMediaSessionPrevious,
onSeekTo: onMediaSessionSeekTo,
onStop: onMediaSessionStop,
onStop1: onMediaSessionSeekTo1,
onProgress: onMediaSessionProgress,
);
Logger.d('AgentController', '媒体会话回调设置完成');
} catch (e) {
@ -1307,7 +1307,6 @@ class AgentController extends GetxController {
// 设置按住说话状态
isPushToTalkActive.value = true;
print("开始按住说话,状态已设置为true");
// 开始语音识别
await AgentService.audioContinue();
// await startVoiceInput();
@ -1406,9 +1405,6 @@ class AgentController extends GetxController {
await _updateMediaSessionMetadata(musicData);
await _updateMediaSessionPlaybackState(true);
// 启动进度定时器
_startProgressTimer();
Logger.d(TAG, '音乐播放启动成功');
} catch (e) {
Logger.e(TAG, '播放音乐失败: $e');
@ -1439,7 +1435,6 @@ class AgentController extends GetxController {
Logger.d('AgentController', '恢复播放音乐');
await _musiceManager.resume();
isPlaying.value = true;
_startProgressTimer();
// 更新媒体会话播放状态
await _updateMediaSessionPlaybackState(true);
@ -1451,23 +1446,6 @@ class AgentController extends GetxController {
}
}
// 启动进度更新定时器
void _startProgressTimer() {
_stopProgressTimer(); // 先停止现有定时器
Logger.d('AgentController', '启动播放进度定时器');
_progressTimer = Timer.periodic(const Duration(milliseconds: 500), (timer) {
if (isPlaying.value && currentId.value != 0) {
updateMusicProgress();
} else if (!isPlaying.value) {
// 如果不在播放状态,停止定时器
timer.cancel();
_progressTimer = null;
Logger.d('AgentController', '播放已停止,取消进度定时器');
}
});
}
// 停止进度更新定时器
void _stopProgressTimer() {
if (_progressTimer != null) {
@ -1478,45 +1456,7 @@ class AgentController extends GetxController {
}
// 获取播放进度
Future<void> updateMusicProgress() async {
try {
if (!isPlaying.value || currentId.value == 0) {
return; // 如果没有在播放,直接返回
}
// var progressInfo = await _musiceManager.getProgress();
// final newPosition = progressInfo['currentPosition'] ?? 0;
// final newDuration = progressInfo['duration'] ?? 0;
// final newProgress = progressInfo['progress'] ?? 0.0;
// bool hasUpdate = false;
// // 只有当值发生变化时才更新,避免不必要的UI刷新
// if (currentPosition.value != newPosition) {
// currentPosition.value = newPosition;
// hasUpdate = true;
// }
// if (duration.value != newDuration) {
// duration.value = newDuration;
// hasUpdate = true;
// }
// if ((progress.value - newProgress).abs() > 0.001) {
// // 避免浮点数精度问题
// progress.value = newProgress;
// hasUpdate = true;
// }
// 如果有进度更新,通知系统媒体会话更新进度信息
// if (hasUpdate) {
// await _updateMediaSessionProgress();
// }
} catch (e) {
Logger.e('AgentController', '获取播放进度失败: $e');
}
}
// 获取播放进度
Future<void> updateMusicProgress1(int currentIdInternal, int newPosition,
Future<void> updateMusicProgress(int currentIdInternal, int newPosition,
int newDuration, double newProgress) async {
try {
if (currentIdInternal != 0) {
@ -1524,12 +1464,6 @@ class AgentController extends GetxController {
// return; // 如果没有在播放,直接返回
}
// // var progressInfo = await _musiceManager.getProgress();
// final newPosition = progressInfo['currentPosition'] ?? 0;
// final newDuration = progressInfo['duration'] ?? 0;
// final newProgress = progressInfo['progress'] ?? 0.0;
// print(
// "updateMusicProgress1:currentIdInternal:$currentIdInternal newPosition:$newPosition newDuration:$newDuration newProgress:$newProgress");
bool hasUpdate = false;
if (currentId.value != currentIdInternal) {
currentId.value = currentIdInternal;
@ -1597,20 +1531,17 @@ class AgentController extends GetxController {
Future<void> seekToPosition(int positionMs) async {
try {
await _musiceManager.seekTo(positionMs);
// 立即更新进度状态
// await updateMusicProgress();
} catch (e) {
Logger.e('AgentController', '跳转播放位置失败: $e');
}
}
// 跳转到指定位置
Future<void> seekToPosition1(int currentIdInternal, int newPosition,
Future<void> seekToProgress(int currentIdInternal, int newPosition,
int newDuration, double newProgress) async {
try {
//await _musiceManager.seekTo(positionMs);
// 立即更新进度状态
await updateMusicProgress1(
await updateMusicProgress(
currentIdInternal, newPosition, newDuration, newProgress);
} catch (e) {
Logger.e('AgentController', '跳转播放位置失败: $e');
@ -1700,9 +1631,6 @@ class AgentController extends GetxController {
currentId.value = formattedPlaylist[0]['id'] ?? 0;
}
// 启动进度定时器
_startProgressTimer();
Logger.d(TAG, '音乐列表播放启动成功');
} catch (e) {
Logger.e(TAG, '播放音乐列表失败: $e');
@ -1831,12 +1759,12 @@ class AgentController extends GetxController {
_stopProgressTimer();
}
/// 处理来自系统通知栏的跳转操作
Future<void> onMediaSessionSeekTo1(int currentIdInternal, int newPosition,
/// 处理来自系统进度条
Future<void> onMediaSessionProgress(int currentIdInternal, int newPosition,
int newDuration, double newProgress) async {
// print(
// "onMediaSessionSeekTo1 currentIdInternal :$currentIdInternal ,newPosition:$newPosition newDuration:$newDuration newProgress:$newProgress");
await seekToPosition1(
// "onMediaSessionProgress currentIdInternal :$currentIdInternal ,newPosition:$newPosition newDuration:$newDuration newProgress:$newProgress");
await seekToProgress(
currentIdInternal, newPosition, newDuration, newProgress);
}
}

12
local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt

@ -352,7 +352,6 @@ object AgentService : CoroutineScope {
*/
private fun startIdleCheck() {
stopIdleCheck() // 先停止现有的检查
Log.d(TAG, "启动空闲检测: ${isRecognitionActive}")
if (!isRecognitionActive) return
idleCheckJob = launch {
@ -360,7 +359,6 @@ object AgentService : CoroutineScope {
delay(maxIdleSeconds * 1000L)
if (isActive && isRecognitionActive && !hasSpeechDetected && !isTtsSpeaking && !isAiStreaming) {
Log.d(TAG, "启动空闲检测: stopRecognition")
//stopRecognition()
sendEvent("auto_stop", mapOf("reason" to "idle_timeout", "seconds" to maxIdleSeconds))
}
@ -398,14 +396,12 @@ object AgentService : CoroutineScope {
Log.d(TAG, "服务未初始化")
return false
}
Log.d(TAG, "麦克风音频未暂停,无法设置${azureAsrHelper!!.isPaused},$isExternalActive")
if(!(azureAsrHelper!!.isPaused)&&isExternalActive)
{
Log.d(TAG, "麦克风音频未暂停,无法设置")
BleService.closeCodec()
return false
}
Log.d(TAG, "开始语音识别")
if (isRecognitionActive) return true
// 检查录音权限
@ -499,14 +495,13 @@ object AgentService : CoroutineScope {
_isRecognitionActive.set(false)
stopIdleCheck()
Log.d(TAG, "onSessionStopped")
audioPlayer?.playAudio(R.raw.stop)
}
override fun onCanceled(reason: String, errorDetails: String) {
_isRecognitionActive.set(false)
stopIdleCheck()
Log.d(TAG, "recognition_canceled")
BleService.closeCodec()
sendEvent("recognition_canceled", mapOf(
"reason" to reason,
@ -517,7 +512,7 @@ object AgentService : CoroutineScope {
override fun onError(error: String) {
_isRecognitionActive.set(false)
stopIdleCheck()
Log.d(TAG, "error")
BleService.closeCodec()
Log.e(TAG, "语音识别错误: $error")
sendEvent("error", mapOf(
@ -549,7 +544,6 @@ object AgentService : CoroutineScope {
try {
azureAsrHelper?.stopContinuousRecognition()
Log.d(TAG, "停止语音识别")
BleService.closeCodec()
_isRecognitionActive.set(false)
stopIdleCheck()
@ -569,7 +563,7 @@ object AgentService : CoroutineScope {
try {
if(audioSourceType== AzureAsrHelper.AudioSourceType.EXTERNAL)
{
Log.d(TAG, "当前是什么输入:$audioSourceType")
BleService.closeCodec()
stopRecognition()
startRecognition(false)

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

@ -458,9 +458,12 @@ class AzureAsrHelper(private val context: Context) {
EventHandler<SessionEventArgs> { _, _ ->
// 直接在当前线程调用回调
Log.d(tag, "会话结束事件")
if (audioSourceType == AudioSourceType.EXTERNAL) {
callback.onSessionStopped()
isContinuousRecognitionActive = false
stopAudioProcessing()
}
}
)
@ -633,7 +636,12 @@ class AzureAsrHelper(private val context: Context) {
Log.d(tag, "关闭麦克风stopAudioPause: ")
// 清理旧的识别器
isPaused = true
// 如果正在进行连续识别,先停止
if (isContinuousRecognitionActive) {
// 直接停止,不等待结果
recognizer?.stopContinuousRecognitionAsync()
isContinuousRecognitionActive = false
}
}
@ -642,9 +650,15 @@ class AzureAsrHelper(private val context: Context) {
*/
fun audioContinue() {
Log.d(tag, "继续麦克风stopAudioPause: ")
// 如果正在进行连续识别,先停止
if (!isContinuousRecognitionActive) {
// 直接停止,不等待结果
recognizer?.startContinuousRecognitionAsync()
isContinuousRecognitionActive = true
}
// 开始连续识别
isPaused = false
}
/**

2
local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicService.kt

@ -216,7 +216,7 @@ private fun updateProgress() {
// 更新媒体会话进度
// 通知Flutter层
flutterChannel?.invokeMethod("onMediaSessionSeekTo1", mapOf(
flutterChannel?.invokeMethod("onMediaSessionProgress", mapOf(
"currentIdInternal" to currentIdInternal,
"currentPosition" to currentPosition,
"duration" to duration,

6
local_plugins/music_service/lib/music_service.dart

@ -103,7 +103,7 @@ class MusicService {
required Function() onPrevious,
required Function(int) onSeekTo,
required Function() onStop,
required Function(int, int, int, double) onStop1,
required Function(int, int, int, double) onProgress,
}) async {
// 设置方法调用处理器来处理来自原生平台的回调
_methodChannel.setMethodCallHandler((call) async {
@ -127,12 +127,12 @@ class MusicService {
case 'onMediaSessionStop':
onStop();
break;
case 'onMediaSessionSeekTo1':
case 'onMediaSessionProgress':
final currentIdInternal = call.arguments['currentIdInternal'] as int;
final currentPosition = call.arguments['currentPosition'] as int;
final duration = call.arguments['duration'] as int;
final progress = call.arguments['progress'] as double;
onStop1(currentIdInternal, currentPosition, duration, progress);
onProgress(currentIdInternal, currentPosition, duration, progress);
break;
}
});

Loading…
Cancel
Save