diff --git a/lib/talk/startChart/handle/impl/udp_talk_expect_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_expect_handler.dart index 69469f47..cc3977d7 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_expect_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_expect_handler.dart @@ -12,11 +12,14 @@ import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart'; import 'package:star_lock/talk/startChart/proto/generic.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_expect.pb.dart'; +import 'package:star_lock/talk/startChart/views/talkView/talk_view_state.dart'; import '../../start_chart_manage.dart'; class UdpTalkExpectHandler extends ScpMessageBaseHandle implements ScpMessageHandler { + final TalkViewState talkViewState = TalkViewState(); + @override void handleReq(ScpMessage scpMessage) { // 收到预期音视频数据请求 @@ -33,9 +36,12 @@ class UdpTalkExpectHandler extends ScpMessageBaseHandle @override void handleResp(ScpMessage scpMessage) { // 收到预期音视频数据回复 - final GenericResp genericResp = scpMessage.Payload; - if (checkGenericRespSuccess(genericResp)) { + final TalkExpectResp talkExpectResp = scpMessage.Payload; + if (talkExpectResp != null) { print('收到预期音视频数据回复'); + // 停止发送预期数据的定时器 + startChartManage.stopTalkExpectMessageTimer(); + talkViewState.rotateAngle.value = talkExpectResp.rotate ?? 0; } } @@ -56,12 +62,12 @@ class UdpTalkExpectHandler extends ScpMessageBaseHandle int? spIndex, int? messageId}) { if (messageType == MessageTypeConstant.Resp) { - // final TalkExpectResp talkExpectResp = TalkExpectResp(); - // talkExpectResp.mergeFromBuffer(byte); - // return talkExpectResp; - final GenericResp genericResp = GenericResp(); - genericResp.mergeFromBuffer(byte); - return genericResp; + final TalkExpectResp talkExpectResp = TalkExpectResp(); + talkExpectResp.mergeFromBuffer(byte); + return talkExpectResp; + // final GenericResp genericResp = GenericResp(); + // genericResp.mergeFromBuffer(byte); + // return genericResp; } else if (messageType == MessageTypeConstant.Req) { final TalkExpectReq talkExpect = TalkExpectReq(); talkExpect.mergeFromBuffer(byte); diff --git a/lib/talk/startChart/views/talkView/talk_view_logic.dart b/lib/talk/startChart/views/talkView/talk_view_logic.dart index ba384cb8..8f4e92a4 100644 --- a/lib/talk/startChart/views/talkView/talk_view_logic.dart +++ b/lib/talk/startChart/views/talkView/talk_view_logic.dart @@ -32,11 +32,11 @@ class TalkViewLogic extends BaseGetXController { Timer? _syncTimer; // 音视频播放刷新率定时器 int _startTime = 0; // 开始播放时间戳,用于判断帧数据中的时间戳位置 - final int bufferSize = 8; // 缓冲区大小(以帧为单位) + final int bufferSize = 20; // 缓冲区大小(以帧为单位) final List frameTimestamps = []; // 帧时间戳用于计算 FPS int frameIntervalMs = 45; // 初始帧间隔设置为45毫秒(约22FPS) int minFrameIntervalMs = 30; // 最小帧间隔(约33 FPS) - int maxFrameIntervalMs = 500; // 最大帧间隔(约2 FPS) + int maxFrameIntervalMs = 500; // 最大帧间隔(约1 FPS) // int maxFrameIntervalMs = 100; // 最大帧间隔(约10 FPS) /// 初始化音频播放器 @@ -54,7 +54,7 @@ class TalkViewLogic extends BaseGetXController { /// 挂断 void udpHangUpAction() async { - if (state.talkStatus.value == TalkStatus.duringCall) { + if (state.talkStatus.value == TalkStatus.answeredSuccessfully) { // 如果是通话中就挂断 StartChartManage().sendTalkHangupMessage(); } else { @@ -66,31 +66,13 @@ class TalkViewLogic extends BaseGetXController { // 发起接听命令 void initiateAnswerCommand() { - StartChartManage().sendTalkAcceptMessage(); - } - - void _updateFps(List frameTimestamps) { - final int now = DateTime.now().millisecondsSinceEpoch; - // 移除超过1秒的时间戳 - frameTimestamps.removeWhere((timestamp) => now - timestamp > 1000); - - // 计算 FPS - final double fps = frameTimestamps.length.toDouble(); - - // 更新 FPS - state.fps.value = fps; + StartChartManage().startTalkAcceptTimer(); } // 监听音视频数据流 void _startListenTalkData() { state.talkDataRepository.talkDataStream.listen((TalkData talkData) { final contentType = talkData.contentType; - final currentTimestamp = DateTime.now().millisecondsSinceEpoch; - - /// 如果不是通话中的状态不处理对讲数据 - if (state.startChartTalkStatus.status != TalkStatus.duringCall) { - return; - } // 判断数据类型,进行分发处理 switch (contentType) { @@ -105,10 +87,10 @@ class TalkViewLogic extends BaseGetXController { if (state.videoBuffer.length < bufferSize) { state.videoBuffer.add(talkData); } - print('talkData durationMs-->:${talkData.durationMs}'); + // print('talkData durationMs-->:${talkData.durationMs}'); /// 更新网络状态 - updateNetworkStatus(currentTimestamp); + // updateNetworkStatus(currentTimestamp); break; } }); @@ -187,10 +169,6 @@ class TalkViewLogic extends BaseGetXController { if (state.videoBuffer.length > 1) { state.videoBuffer.removeAt(0); } else { - // // 记录当前时间戳 - // frameTimestamps.add(DateTime.now().millisecondsSinceEpoch); - // // 计算并更新 FPS - // _updateFps(frameTimestamps); _playVideoData(state.videoBuffer.removeAt(0)); } } @@ -236,10 +214,6 @@ class TalkViewLogic extends BaseGetXController { if (state.videoBuffer.length > 1) { state.videoBuffer.removeAt(0); } else { - // // 记录当前时间戳 - // frameTimestamps.add(DateTime.now().millisecondsSinceEpoch); - // // 计算并更新 FPS - // _updateFps(frameTimestamps); _playVideoData(state.videoBuffer.removeAt(0)); } } @@ -371,7 +345,8 @@ class TalkViewLogic extends BaseGetXController { } /// 修改发送预期数据 - StartChartManage().changeTalkExpectDataType(talkExpect: talkExpectReq); + StartChartManage().changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer( + talkExpect: talkExpectReq); state.isOpenVoice.value = !state.isOpenVoice.value; } diff --git a/lib/talk/startChart/views/talkView/talk_view_page.dart b/lib/talk/startChart/views/talkView/talk_view_page.dart index 925ce86b..232c08c3 100644 --- a/lib/talk/startChart/views/talkView/talk_view_page.dart +++ b/lib/talk/startChart/views/talkView/talk_view_page.dart @@ -81,26 +81,29 @@ class _TalkViewPageState extends State canPop: false, child: RepaintBoundary( key: state.globalKey, - child: Image.memory( - state.listData.value, - gaplessPlayback: true, - width: 1.sw, - height: 1.sh, - fit: BoxFit.cover, - filterQuality: FilterQuality.high, - errorBuilder: ( - BuildContext context, - Object error, - StackTrace? stackTrace, - ) { - return Container(color: Colors.transparent); - }, + child: RotatedBox( + quarterTurns: 1, // 顺时针旋转 90 度(1 个四分之一圈) + child: Image.memory( + state.listData.value, + gaplessPlayback: true, + width: 1.sw, + height: 1.sh, + fit: BoxFit.cover, + filterQuality: FilterQuality.high, + errorBuilder: ( + BuildContext context, + Object error, + StackTrace? stackTrace, + ) { + return Container(color: Colors.transparent); + }, + ), ), ), ), ), ), - Obx(() => state.talkStatus.value == TalkStatus.answeredSuccessfully + Obx(() => state.listData.value.isEmpty ? Positioned( bottom: 300.h, child: Text( @@ -141,7 +144,7 @@ class _TalkViewPageState extends State // ), // ), // ), - Obx(() => state.talkStatus.value == TalkStatus.answeredSuccessfully + Obx(() => state.listData.value.isEmpty ? buildRotationTransition() : Container()) ], @@ -154,7 +157,7 @@ class _TalkViewPageState extends State // 打开关闭声音 GestureDetector( onTap: () { - if (state.talkStatus.value == TalkStatus.duringCall) { + if (state.talkStatus.value == TalkStatus.answeredSuccessfully) { // 打开关闭声音 logic.updateTalkExpect(); } @@ -177,7 +180,7 @@ class _TalkViewPageState extends State // 截图 GestureDetector( onTap: () async { - if (state.talkStatus.value == TalkStatus.duringCall) { + if (state.talkStatus.value == TalkStatus.answeredSuccessfully) { await logic.captureAndSavePng(); } }, @@ -196,7 +199,7 @@ class _TalkViewPageState extends State // 录制 GestureDetector( onTap: () async { - if (state.talkStatus.value == TalkStatus.duringCall) { + if (state.talkStatus.value == TalkStatus.answeredSuccessfully) { if (state.isRecordingScreen.value) { await logic.stopRecording(); print('停止录屏'); @@ -245,8 +248,7 @@ class _TalkViewPageState extends State getAnswerBtnName(), Colors.white, longPress: () async { - if (state.talkStatus.value == TalkStatus.answeredSuccessfully || - state.talkStatus.value == TalkStatus.duringCall) { + if (state.talkStatus.value == TalkStatus.answeredSuccessfully) { print('开始录音'); logic.startProcessingAudio(); } @@ -283,7 +285,6 @@ class _TalkViewPageState extends State case TalkStatus.waitingAnswer: return 'images/main/icon_lockDetail_monitoringAnswerCalls.png'; case TalkStatus.answeredSuccessfully: - case TalkStatus.duringCall: return 'images/main/icon_lockDetail_monitoringUnTalkback.png'; default: return 'images/main/icon_lockDetail_monitoringAnswerCalls.png'; @@ -295,7 +296,6 @@ class _TalkViewPageState extends State case TalkStatus.waitingAnswer: return '接听'.tr; case TalkStatus.answeredSuccessfully: - case TalkStatus.duringCall: return '长按说话'.tr; default: return '接听'.tr; diff --git a/lib/talk/startChart/views/talkView/talk_view_state.dart b/lib/talk/startChart/views/talkView/talk_view_state.dart index 87db2eac..eb3593ed 100644 --- a/lib/talk/startChart/views/talkView/talk_view_state.dart +++ b/lib/talk/startChart/views/talkView/talk_view_state.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_voice_processor/flutter_voice_processor.dart'; import 'package:get/get.dart'; import 'package:get/get_rx/get_rx.dart'; +import 'package:get/get_rx/src/rx_types/rx_types.dart'; import 'package:network_info_plus/network_info_plus.dart'; import 'package:star_lock/talk/startChart/constant/talk_status.dart'; import 'package:star_lock/talk/startChart/handle/other/talk_data_repository.dart'; @@ -71,11 +72,12 @@ class TalkViewState { RxBool isRecordingScreen = false.obs; // 是否录屏中 RxBool isRecordingAudio = false.obs; // 是否录音中 Rx startRecordingAudioTime = DateTime.now().obs; // 开始录音时间 - Rx endRecordingAudioTime= DateTime.now().obs; // 结束录音时间 - RxInt recordingAudioTime= 0.obs; // 录音时间持续时间 + Rx endRecordingAudioTime = DateTime.now().obs; // 结束录音时间 + RxInt recordingAudioTime = 0.obs; // 录音时间持续时间 RxDouble fps = 0.0.obs; // 添加 FPS 计数 late VoiceProcessor? voiceProcessor; // 音频处理器、录音 final int frameLength = 320; //录音视频帧长度为320 final int sampleRate = 8000; //录音频采样率为8000 List> recordingAudioAllFrames = >[]; // 录制音频的所有帧 + RxInt rotateAngle = 0.obs; // 旋转角度(以弧度为单位) }