fix:调整优化h264播放逻辑并增加音频
This commit is contained in:
parent
4242ac0a80
commit
8478dd33d1
@ -774,9 +774,10 @@ class LockDetailLogic extends BaseGetXController {
|
|||||||
showToast('设备未配网'.tr);
|
showToast('设备未配网'.tr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送监控id
|
// 发送监控id
|
||||||
StartChartManage().startCallRequestMessageTimer(
|
StartChartManage().startCallRequestMessageTimer(
|
||||||
ToPeerId: StartChartManage().lockPeerId ?? '');
|
ToPeerId: StartChartManage().lockNetworkInfo.peerId ?? '');
|
||||||
} else {
|
} else {
|
||||||
showToast('猫眼设置为省电模式时无法进行监控,请在猫眼设置中切换为其他模式'.tr);
|
showToast('猫眼设置为省电模式时无法进行监控,请在猫眼设置中切换为其他模式'.tr);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -374,6 +374,9 @@ class LockFeature {
|
|||||||
this.isNoSupportedBlueBroadcast,
|
this.isNoSupportedBlueBroadcast,
|
||||||
this.wifiLockType,
|
this.wifiLockType,
|
||||||
this.wifi,
|
this.wifi,
|
||||||
|
this.isH264,
|
||||||
|
this.isH265,
|
||||||
|
this.isMJpeg,
|
||||||
});
|
});
|
||||||
|
|
||||||
LockFeature.fromJson(Map<String, dynamic> json) {
|
LockFeature.fromJson(Map<String, dynamic> json) {
|
||||||
@ -391,6 +394,9 @@ class LockFeature {
|
|||||||
isNoSupportedBlueBroadcast = json['isNoSupportedBlueBroadcast'];
|
isNoSupportedBlueBroadcast = json['isNoSupportedBlueBroadcast'];
|
||||||
wifiLockType = json['wifiLockType'];
|
wifiLockType = json['wifiLockType'];
|
||||||
wifi = json['wifi'];
|
wifi = json['wifi'];
|
||||||
|
isH264 = json['isH264'];
|
||||||
|
isH265 = json['isH265'];
|
||||||
|
isMJpeg = json['isMJpeg'];
|
||||||
}
|
}
|
||||||
|
|
||||||
int? password;
|
int? password;
|
||||||
@ -407,6 +413,9 @@ class LockFeature {
|
|||||||
int? isNoSupportedBlueBroadcast;
|
int? isNoSupportedBlueBroadcast;
|
||||||
int? wifiLockType;
|
int? wifiLockType;
|
||||||
int? wifi;
|
int? wifi;
|
||||||
|
int? isH264;
|
||||||
|
int? isH265;
|
||||||
|
int? isMJpeg;
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final Map<String, dynamic> data = <String, dynamic>{};
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
@ -424,6 +433,9 @@ class LockFeature {
|
|||||||
data['isNoSupportedBlueBroadcast'] = isNoSupportedBlueBroadcast;
|
data['isNoSupportedBlueBroadcast'] = isNoSupportedBlueBroadcast;
|
||||||
data['wifiLockType'] = wifiLockType;
|
data['wifiLockType'] = wifiLockType;
|
||||||
data['wifi'] = wifi;
|
data['wifi'] = wifi;
|
||||||
|
data['isH264'] = isH264;
|
||||||
|
data['isH265'] = isH265;
|
||||||
|
data['isMJpeg'] = isMJpeg;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import 'dart:typed_data';
|
|||||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:star_lock/talk/starChart/entity/scp_message.dart';
|
import 'package:star_lock/talk/starChart/entity/scp_message.dart';
|
||||||
|
import 'package:star_lock/talk/starChart/handle/other/talk_data_model.dart';
|
||||||
import 'package:star_lock/talk/starChart/handle/scp_message_base_handle.dart';
|
import 'package:star_lock/talk/starChart/handle/scp_message_base_handle.dart';
|
||||||
import 'package:star_lock/talk/starChart/handle/scp_message_handle.dart';
|
import 'package:star_lock/talk/starChart/handle/scp_message_handle.dart';
|
||||||
import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
|
||||||
@ -22,7 +23,7 @@ class UdpEchoTestHandler extends ScpMessageBaseHandle
|
|||||||
EasyLoading.showToast(scpMessage.Payload, duration: 2000.milliseconds);
|
EasyLoading.showToast(scpMessage.Payload, duration: 2000.milliseconds);
|
||||||
} else {
|
} else {
|
||||||
talkDataRepository.addTalkData(
|
talkDataRepository.addTalkData(
|
||||||
TalkData(content: payload, contentType: TalkData_ContentTypeE.Image));
|
TalkDataModel(talkData: TalkData(content: payload, contentType: TalkData_ContentTypeE.Image)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import 'dart:typed_data';
|
|||||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||||
import 'package:flutter_pcm_sound/flutter_pcm_sound.dart';
|
import 'package:flutter_pcm_sound/flutter_pcm_sound.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:star_lock/main/lockMian/entity/lockListInfo_entity.dart';
|
||||||
import 'package:star_lock/talk/starChart/constant/message_type_constant.dart';
|
import 'package:star_lock/talk/starChart/constant/message_type_constant.dart';
|
||||||
import 'package:star_lock/talk/starChart/constant/talk_status.dart';
|
import 'package:star_lock/talk/starChart/constant/talk_status.dart';
|
||||||
import 'package:star_lock/talk/starChart/entity/scp_message.dart';
|
import 'package:star_lock/talk/starChart/entity/scp_message.dart';
|
||||||
@ -13,6 +14,7 @@ import 'package:star_lock/talk/starChart/proto/gateway_reset.pb.dart';
|
|||||||
import 'package:star_lock/talk/starChart/proto/generic.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/generic.pb.dart';
|
||||||
import 'package:star_lock/talk/starChart/proto/talk_accept.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/talk_accept.pb.dart';
|
||||||
import 'package:star_lock/talk/starChart/proto/talk_expect.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/talk_expect.pb.dart';
|
||||||
|
import 'package:star_lock/tools/commonDataManage.dart';
|
||||||
|
|
||||||
import '../../star_chart_manage.dart';
|
import '../../star_chart_manage.dart';
|
||||||
|
|
||||||
@ -77,7 +79,24 @@ class UdpTalkAcceptHandler extends ScpMessageBaseHandle
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _handleSendExpect() {
|
void _handleSendExpect() {
|
||||||
// 修改预期数据并启动发送预期数据定时器,在收到回复时停止
|
final LockListInfoItemEntity currentKeyInfo =
|
||||||
startChartManage.sendImageVideoAndG711AudioTalkExpectData();
|
CommonDataManage().currentKeyInfo;
|
||||||
|
final isH264 = currentKeyInfo.lockFeature?.isH264 == 1;
|
||||||
|
final isMJpeg = currentKeyInfo.lockFeature?.isMJpeg == 1;
|
||||||
|
|
||||||
|
// 优先使用H264,其次是MJPEG
|
||||||
|
if (isH264) {
|
||||||
|
// 锁支持H264,发送H264视频和G711音频期望
|
||||||
|
startChartManage.sendH264VideoAndG711AudioTalkExpectData();
|
||||||
|
print('锁支持H264,发送H264视频格式期望数据');
|
||||||
|
} else if (isMJpeg) {
|
||||||
|
// 锁只支持MJPEG,发送图像视频和G711音频期望
|
||||||
|
startChartManage.sendImageVideoAndG711AudioTalkExpectData();
|
||||||
|
print('锁不支持H264,支持MJPEG,发送MJPEG视频格式期望数据');
|
||||||
|
} else {
|
||||||
|
// 默认使用图像视频
|
||||||
|
startChartManage.sendImageVideoAndG711AudioTalkExpectData();
|
||||||
|
print('锁不支持H264和MJPEG,默认发送图像视频格式期望数据');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import 'package:star_lock/talk/starChart/constant/message_type_constant.dart';
|
|||||||
import 'package:star_lock/talk/starChart/entity/scp_message.dart';
|
import 'package:star_lock/talk/starChart/entity/scp_message.dart';
|
||||||
import 'package:star_lock/talk/starChart/handle/other/h264_frame_handler.dart';
|
import 'package:star_lock/talk/starChart/handle/other/h264_frame_handler.dart';
|
||||||
import 'package:star_lock/talk/starChart/handle/other/packet_loss_statistics.dart';
|
import 'package:star_lock/talk/starChart/handle/other/packet_loss_statistics.dart';
|
||||||
|
import 'package:star_lock/talk/starChart/handle/other/talk_data_model.dart';
|
||||||
import 'package:star_lock/talk/starChart/handle/scp_message_base_handle.dart';
|
import 'package:star_lock/talk/starChart/handle/scp_message_base_handle.dart';
|
||||||
import 'package:star_lock/talk/starChart/handle/scp_message_handle.dart';
|
import 'package:star_lock/talk/starChart/handle/scp_message_handle.dart';
|
||||||
import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
|
||||||
@ -63,7 +64,7 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle
|
|||||||
int? messageId}) {
|
int? messageId}) {
|
||||||
// 获取统计信息
|
// 获取统计信息
|
||||||
final stats = PacketLossStatistics().getStatistics();
|
final stats = PacketLossStatistics().getStatistics();
|
||||||
_asyncLog('丢包统计: $stats');
|
// _asyncLog('丢包统计: $stats');
|
||||||
// _asyncLog(
|
// _asyncLog(
|
||||||
// '分包数据:messageId:$messageId [$spIndex/$spTotal] PayloadLength:$PayloadLength');
|
// '分包数据:messageId:$messageId [$spIndex/$spTotal] PayloadLength:$PayloadLength');
|
||||||
if (messageType == MessageTypeConstant.RealTimeData) {
|
if (messageType == MessageTypeConstant.RealTimeData) {
|
||||||
@ -118,7 +119,7 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle
|
|||||||
void _handleVideoH264(TalkData talkData) {
|
void _handleVideoH264(TalkData talkData) {
|
||||||
final TalkDataH264Frame talkDataH264Frame = TalkDataH264Frame();
|
final TalkDataH264Frame talkDataH264Frame = TalkDataH264Frame();
|
||||||
talkDataH264Frame.mergeFromBuffer(talkData.content);
|
talkDataH264Frame.mergeFromBuffer(talkData.content);
|
||||||
frameHandler.handleFrame(talkDataH264Frame);
|
frameHandler.handleFrame(talkDataH264Frame, talkData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 处理图片数据
|
/// 处理图片数据
|
||||||
@ -127,7 +128,11 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle
|
|||||||
await _processCompletePayload(Uint8List.fromList(talkData.content));
|
await _processCompletePayload(Uint8List.fromList(talkData.content));
|
||||||
processCompletePayload.forEach((element) {
|
processCompletePayload.forEach((element) {
|
||||||
talkData.content = element;
|
talkData.content = element;
|
||||||
talkDataRepository.addTalkData(talkData);
|
talkDataRepository.addTalkData(
|
||||||
|
TalkDataModel(
|
||||||
|
talkData: talkData,
|
||||||
|
),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +143,11 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle
|
|||||||
// // 转pcm数据
|
// // 转pcm数据
|
||||||
// List<int> pcmBytes = G711().convertList(g711Data);
|
// List<int> pcmBytes = G711().convertList(g711Data);
|
||||||
// talkData.content = pcmBytes;
|
// talkData.content = pcmBytes;
|
||||||
talkDataRepository.addTalkData(talkData);
|
talkDataRepository.addTalkData(
|
||||||
|
TalkDataModel(
|
||||||
|
talkData: talkData,
|
||||||
|
),
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error decoding G.711 to PCM: $e');
|
print('Error decoding G.711 to PCM: $e');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import '../../star_chart_manage.dart';
|
|||||||
|
|
||||||
class UdpTalkExpectHandler extends ScpMessageBaseHandle
|
class UdpTalkExpectHandler extends ScpMessageBaseHandle
|
||||||
implements ScpMessageHandler {
|
implements ScpMessageHandler {
|
||||||
final TalkViewState talkViewState = Get.put(TalkViewLogic()).state;
|
// final TalkViewState talkViewState = Get.put(TalkViewLogic()).state;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void handleReq(ScpMessage scpMessage) {
|
void handleReq(ScpMessage scpMessage) {
|
||||||
@ -40,7 +40,7 @@ class UdpTalkExpectHandler extends ScpMessageBaseHandle
|
|||||||
startChartManage.stopTalkExpectMessageTimer();
|
startChartManage.stopTalkExpectMessageTimer();
|
||||||
// 停止发送对讲请求
|
// 停止发送对讲请求
|
||||||
startChartManage.stopCallRequestMessageTimer();
|
startChartManage.stopCallRequestMessageTimer();
|
||||||
talkViewState.rotateAngle.value = talkExpectResp.rotate ?? 0;
|
// talkViewState.rotateAngle.value = talkExpectResp.rotate ?? 0;
|
||||||
// 收到预期数据的应答后,代表建立了连接,启动通话保持的监听
|
// 收到预期数据的应答后,代表建立了连接,启动通话保持的监听
|
||||||
// 启动通话保持监听定时器(用来判断如果x秒内没有收到通话保持则执行的操作);
|
// 启动通话保持监听定时器(用来判断如果x秒内没有收到通话保持则执行的操作);
|
||||||
talkePingOverTimeTimerManager.start();
|
talkePingOverTimeTimerManager.start();
|
||||||
|
|||||||
@ -7,7 +7,9 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:star_lock/appRouters.dart';
|
import 'package:star_lock/appRouters.dart';
|
||||||
import 'package:star_lock/app_settings/app_settings.dart';
|
import 'package:star_lock/app_settings/app_settings.dart';
|
||||||
|
import 'package:star_lock/main/lockMian/entity/lockListInfo_entity.dart';
|
||||||
import 'package:star_lock/talk/starChart/constant/message_type_constant.dart';
|
import 'package:star_lock/talk/starChart/constant/message_type_constant.dart';
|
||||||
|
import 'package:star_lock/talk/starChart/constant/talk_constant.dart';
|
||||||
import 'package:star_lock/talk/starChart/constant/talk_status.dart';
|
import 'package:star_lock/talk/starChart/constant/talk_status.dart';
|
||||||
import 'package:star_lock/talk/starChart/entity/scp_message.dart';
|
import 'package:star_lock/talk/starChart/entity/scp_message.dart';
|
||||||
import 'package:star_lock/talk/starChart/handle/scp_message_base_handle.dart';
|
import 'package:star_lock/talk/starChart/handle/scp_message_base_handle.dart';
|
||||||
@ -16,6 +18,7 @@ import 'package:star_lock/talk/starChart/proto/gateway_reset.pb.dart';
|
|||||||
import 'package:star_lock/talk/starChart/proto/generic.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/generic.pb.dart';
|
||||||
import 'package:star_lock/talk/starChart/proto/talk_expect.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/talk_expect.pb.dart';
|
||||||
import 'package:star_lock/talk/starChart/proto/talk_request.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/talk_request.pb.dart';
|
||||||
|
import 'package:star_lock/tools/commonDataManage.dart';
|
||||||
import 'package:star_lock/tools/push/xs_jPhush.dart';
|
import 'package:star_lock/tools/push/xs_jPhush.dart';
|
||||||
import 'package:star_lock/tools/storage.dart';
|
import 'package:star_lock/tools/storage.dart';
|
||||||
import 'package:star_lock/translations/current_locale_tool.dart';
|
import 'package:star_lock/translations/current_locale_tool.dart';
|
||||||
@ -30,7 +33,6 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void handleReq(ScpMessage scpMessage) async {
|
void handleReq(ScpMessage scpMessage) async {
|
||||||
|
|
||||||
final currentTime = DateTime.now().millisecondsSinceEpoch;
|
final currentTime = DateTime.now().millisecondsSinceEpoch;
|
||||||
// 确保与上次请求间隔至少1秒
|
// 确保与上次请求间隔至少1秒
|
||||||
if (currentTime - _lastRequestTime < 1000) {
|
if (currentTime - _lastRequestTime < 1000) {
|
||||||
@ -105,18 +107,16 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
|
|||||||
_showTalkRequestNotification(talkObjectName: talkObjectName);
|
_showTalkRequestNotification(talkObjectName: talkObjectName);
|
||||||
// 设置为等待接听状态
|
// 设置为等待接听状态
|
||||||
talkStatus.setPassiveCallWaitingAnswer();
|
talkStatus.setPassiveCallWaitingAnswer();
|
||||||
// 收到呼叫请求,跳转到接听页面
|
|
||||||
if (startChartManage
|
if (startChartManage
|
||||||
.getDefaultTalkExpect()
|
.getDefaultTalkExpect()
|
||||||
.videoType
|
.videoType
|
||||||
.indexOf(VideoTypeE.H264) ==
|
.contains(VideoTypeE.H264)) {
|
||||||
-1) {
|
|
||||||
Get.toNamed(
|
Get.toNamed(
|
||||||
Routers.starChartTalkView,
|
Routers.h264WebView,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Get.toNamed(
|
Get.toNamed(
|
||||||
Routers.h264WebView,
|
Routers.starChartTalkView,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,7 +189,24 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _handleSendExpect() {
|
void _handleSendExpect() {
|
||||||
// 修改预期数据并启动发送预期数据定时器,在收到回复时停止
|
final LockListInfoItemEntity currentKeyInfo =
|
||||||
startChartManage.sendOnlyImageVideoTalkExpectData();
|
CommonDataManage().currentKeyInfo;
|
||||||
|
final isH264 = currentKeyInfo.lockFeature?.isH264 == 1;
|
||||||
|
final isMJpeg = currentKeyInfo.lockFeature?.isMJpeg == 1;
|
||||||
|
|
||||||
|
// 优先使用H264,其次是MJPEG
|
||||||
|
if (isH264) {
|
||||||
|
// 锁支持H264,发送H264视频和G711音频期望
|
||||||
|
startChartManage.sendOnlyH264VideoTalkExpectData();
|
||||||
|
print('锁支持H264,发送H264视频格式期望数据');
|
||||||
|
} else if (isMJpeg) {
|
||||||
|
// 锁只支持MJPEG,发送图像视频和G711音频期望
|
||||||
|
startChartManage.sendOnlyImageVideoTalkExpectData();
|
||||||
|
print('锁不支持H264,支持MJPEG,发送MJPEG视频格式期望数据');
|
||||||
|
} else {
|
||||||
|
// 默认使用图像视频
|
||||||
|
startChartManage.sendOnlyImageVideoTalkExpectData();
|
||||||
|
print('锁不支持H264和MJPEG,默认发送图像视频格式期望数据');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,15 +3,20 @@ import 'dart:typed_data';
|
|||||||
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:star_lock/app_settings/app_settings.dart';
|
import 'package:star_lock/app_settings/app_settings.dart';
|
||||||
|
import 'package:star_lock/talk/starChart/handle/other/talk_data_model.dart';
|
||||||
|
import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
|
||||||
import '../../proto/talk_data_h264_frame.pb.dart';
|
import '../../proto/talk_data_h264_frame.pb.dart';
|
||||||
|
|
||||||
class H264FrameHandler {
|
class H264FrameHandler {
|
||||||
|
final void Function(TalkDataModel frameData) onCompleteFrame;
|
||||||
|
|
||||||
final void Function(List<int> frameData) onCompleteFrame;
|
// 只记录最近一个I帧的序号
|
||||||
|
int _lastProcessedIFrameSeq = -1;
|
||||||
|
|
||||||
H264FrameHandler({required this.onCompleteFrame});
|
H264FrameHandler({required this.onCompleteFrame});
|
||||||
|
|
||||||
void handleFrame(TalkDataH264Frame frame) {
|
void handleFrame(TalkDataH264Frame frame, TalkData talkData) {
|
||||||
onCompleteFrame(frame.frameData);
|
onCompleteFrame(
|
||||||
|
TalkDataModel(talkData: talkData, talkDataH264Frame: frame));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
lib/talk/starChart/handle/other/talk_data_model.dart
Normal file
9
lib/talk/starChart/handle/other/talk_data_model.dart
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import 'package:star_lock/talk/starChart/proto/talk_data.pbserver.dart';
|
||||||
|
import 'package:star_lock/talk/starChart/proto/talk_data_h264_frame.pb.dart';
|
||||||
|
|
||||||
|
class TalkDataModel {
|
||||||
|
TalkData? talkData;
|
||||||
|
TalkDataH264Frame? talkDataH264Frame;
|
||||||
|
|
||||||
|
TalkDataModel({required this.talkData, this.talkDataH264Frame});
|
||||||
|
}
|
||||||
@ -1,9 +1,10 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:star_lock/talk/starChart/handle/other/talk_data_model.dart';
|
||||||
import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
|
||||||
|
|
||||||
class TalkDataRepository {
|
class TalkDataRepository {
|
||||||
TalkDataRepository._() {
|
TalkDataRepository._() {
|
||||||
_talkDataStreamController = StreamController<TalkData>.broadcast(
|
_talkDataStreamController = StreamController<TalkDataModel>.broadcast(
|
||||||
onListen: () {
|
onListen: () {
|
||||||
_isListening = true;
|
_isListening = true;
|
||||||
},
|
},
|
||||||
@ -18,13 +19,13 @@ class TalkDataRepository {
|
|||||||
|
|
||||||
static TalkDataRepository get instance => _instance;
|
static TalkDataRepository get instance => _instance;
|
||||||
|
|
||||||
late final StreamController<TalkData> _talkDataStreamController;
|
late final StreamController<TalkDataModel> _talkDataStreamController;
|
||||||
bool _isListening = false;
|
bool _isListening = false;
|
||||||
|
|
||||||
// 直接返回原始流,不做转换
|
// 直接返回原始流,不做转换
|
||||||
Stream<TalkData> get talkDataStream => _talkDataStreamController.stream;
|
Stream<TalkDataModel> get talkDataStream => _talkDataStreamController.stream;
|
||||||
|
|
||||||
void addTalkData(TalkData talkData) {
|
void addTalkData(TalkDataModel talkData) {
|
||||||
if (_isListening) {
|
if (_isListening) {
|
||||||
_talkDataStreamController.add(talkData);
|
_talkDataStreamController.add(talkData);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import 'package:star_lock/talk/starChart/constant/payload_type_constant.dart';
|
|||||||
import 'package:star_lock/talk/starChart/constant/udp_constant.dart';
|
import 'package:star_lock/talk/starChart/constant/udp_constant.dart';
|
||||||
import 'package:star_lock/talk/starChart/entity/scp_message.dart';
|
import 'package:star_lock/talk/starChart/entity/scp_message.dart';
|
||||||
import 'package:star_lock/talk/starChart/handle/other/h264_frame_handler.dart';
|
import 'package:star_lock/talk/starChart/handle/other/h264_frame_handler.dart';
|
||||||
|
import 'package:star_lock/talk/starChart/handle/other/talk_data_model.dart';
|
||||||
|
|
||||||
import 'package:star_lock/talk/starChart/handle/other/talk_data_repository.dart';
|
import 'package:star_lock/talk/starChart/handle/other/talk_data_repository.dart';
|
||||||
import 'package:star_lock/talk/starChart/handle/other/talke_data_over_time_timer_manager.dart';
|
import 'package:star_lock/talk/starChart/handle/other/talke_data_over_time_timer_manager.dart';
|
||||||
@ -55,10 +56,10 @@ class ScpMessageBaseHandle {
|
|||||||
|
|
||||||
// 处理出完整帧数据后的回调
|
// 处理出完整帧数据后的回调
|
||||||
final H264FrameHandler frameHandler =
|
final H264FrameHandler frameHandler =
|
||||||
H264FrameHandler(onCompleteFrame: (frameData) {
|
H264FrameHandler(onCompleteFrame: (TalkDataModel talkDataModel) {
|
||||||
// 处理完整的帧数据
|
// 处理完整的帧数据
|
||||||
TalkDataRepository.instance.addTalkData(
|
TalkDataRepository.instance.addTalkData(
|
||||||
TalkData(contentType: TalkData_ContentTypeE.H264, content: frameData),
|
talkDataModel,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -71,6 +72,7 @@ class ScpMessageBaseHandle {
|
|||||||
messageId: scpMessage.MessageId!,
|
messageId: scpMessage.MessageId!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 回复失败消息
|
// 回复失败消息
|
||||||
void replyErrorMessage(ScpMessage scpMessage) {
|
void replyErrorMessage(ScpMessage scpMessage) {
|
||||||
startChartManage.sendGenericRespErrorMessage(
|
startChartManage.sendGenericRespErrorMessage(
|
||||||
|
|||||||
@ -113,7 +113,7 @@ class StartChartManage {
|
|||||||
final int _maxPayloadSize = 8 * 1024; // 分包大小
|
final int _maxPayloadSize = 8 * 1024; // 分包大小
|
||||||
|
|
||||||
// 默认通话的期望数据格式
|
// 默认通话的期望数据格式
|
||||||
TalkExpectReq _defaultTalkExpect = TalkConstant.ImageExpect;
|
TalkExpectReq _defaultTalkExpect = TalkConstant.H264Expect;
|
||||||
|
|
||||||
String relayPeerId = ''; // 中继peerId
|
String relayPeerId = ''; // 中继peerId
|
||||||
|
|
||||||
@ -227,20 +227,6 @@ class StartChartManage {
|
|||||||
|
|
||||||
/// 设置数据接收回调
|
/// 设置数据接收回调
|
||||||
_onReceiveData(_udpSocket!, Get.context!);
|
_onReceiveData(_udpSocket!, Get.context!);
|
||||||
|
|
||||||
// //ToDo: 增加对讲调试、正式可删除
|
|
||||||
// // 每秒重置数据速率
|
|
||||||
// Timer.periodic(Duration(seconds: 1), (Timer t) {
|
|
||||||
// UdpTalkDataHandler().resetDataRates();
|
|
||||||
// // 更新调试信息
|
|
||||||
// Provider.of<DebugInfoModel>(Get.context!, listen: false)
|
|
||||||
// .updateDebugInfo(
|
|
||||||
// UdpTalkDataHandler().getLastRecvDataRate() ~/ 1024, // 转换为KB
|
|
||||||
// UdpTalkDataHandler().getLastRecvPacketCount(),
|
|
||||||
// UdpTalkDataHandler().getLastSendDataRate() ~/ 1024, // 转换为KB
|
|
||||||
// UdpTalkDataHandler().getLastSendPacketCount(),
|
|
||||||
// );
|
|
||||||
// });
|
|
||||||
}).catchError((error) {
|
}).catchError((error) {
|
||||||
_log(text: 'Failed to bind UDP socket: $error');
|
_log(text: 'Failed to bind UDP socket: $error');
|
||||||
});
|
});
|
||||||
@ -1145,7 +1131,7 @@ class StartChartManage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void reSetDefaultTalkExpect() {
|
void reSetDefaultTalkExpect() {
|
||||||
_defaultTalkExpect = TalkConstant.ImageExpect;
|
_defaultTalkExpect = TalkConstant.H264Expect;
|
||||||
}
|
}
|
||||||
|
|
||||||
TalkExpectReq getDefaultTalkExpect() {
|
TalkExpectReq getDefaultTalkExpect() {
|
||||||
@ -1163,12 +1149,27 @@ class StartChartManage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 修改预期接收到的数据
|
/// 修改预期接收到的数据
|
||||||
void sendImageVideoAndG711AudioTalkExpectData() {
|
void sendOnlyH264VideoTalkExpectData() {
|
||||||
final talkExpectReq = TalkConstant.ImageExpect;
|
final talkExpectReq = TalkExpectReq(
|
||||||
|
videoType: [VideoTypeE.H264],
|
||||||
|
audioType: [],
|
||||||
|
);
|
||||||
changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(
|
changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(
|
||||||
talkExpect: talkExpectReq);
|
talkExpect: talkExpectReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 修改预期接收到的数据
|
||||||
|
void sendImageVideoAndG711AudioTalkExpectData() {
|
||||||
|
changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(
|
||||||
|
talkExpect: TalkConstant.ImageExpect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 修改预期接收到的数据
|
||||||
|
void sendH264VideoAndG711AudioTalkExpectData() {
|
||||||
|
changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(
|
||||||
|
talkExpect: TalkConstant.H264Expect);
|
||||||
|
}
|
||||||
|
|
||||||
/// 发送远程开锁
|
/// 发送远程开锁
|
||||||
void sendRemoteUnLockMessage({
|
void sendRemoteUnLockMessage({
|
||||||
required String bluetoothDeviceName,
|
required String bluetoothDeviceName,
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import 'package:star_lock/main/lockMian/entity/lockListInfo_entity.dart';
|
|||||||
import 'package:star_lock/network/api_repository.dart';
|
import 'package:star_lock/network/api_repository.dart';
|
||||||
import 'package:star_lock/talk/call/g711.dart';
|
import 'package:star_lock/talk/call/g711.dart';
|
||||||
import 'package:star_lock/talk/starChart/constant/talk_status.dart';
|
import 'package:star_lock/talk/starChart/constant/talk_status.dart';
|
||||||
|
import 'package:star_lock/talk/starChart/handle/other/talk_data_model.dart';
|
||||||
import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
|
||||||
import 'package:star_lock/talk/starChart/proto/talk_expect.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/talk_expect.pb.dart';
|
||||||
import 'package:star_lock/talk/starChart/star_chart_manage.dart';
|
import 'package:star_lock/talk/starChart/star_chart_manage.dart';
|
||||||
@ -96,31 +97,15 @@ class TalkViewLogic extends BaseGetXController {
|
|||||||
|
|
||||||
// 监听音视频数据流
|
// 监听音视频数据流
|
||||||
void _startListenTalkData() {
|
void _startListenTalkData() {
|
||||||
state.talkDataRepository.talkDataStream.listen((TalkData talkData) async {
|
state.talkDataRepository.talkDataStream
|
||||||
final contentType = talkData.contentType;
|
.listen((TalkDataModel talkDataModel) async {
|
||||||
|
final talkData = talkDataModel.talkData;
|
||||||
|
final contentType = talkData!.contentType;
|
||||||
final currentTime = DateTime.now().millisecondsSinceEpoch;
|
final currentTime = DateTime.now().millisecondsSinceEpoch;
|
||||||
|
|
||||||
// 判断数据类型,进行分发处理
|
// 判断数据类型,进行分发处理
|
||||||
switch (contentType) {
|
switch (contentType) {
|
||||||
case TalkData_ContentTypeE.G711:
|
case TalkData_ContentTypeE.G711:
|
||||||
// // 第一帧到达时记录开始时间
|
|
||||||
// if (_isFirstAudioFrame) {
|
|
||||||
// _startAudioTime = currentTime;
|
|
||||||
// _isFirstAudioFrame = false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 计算音频延迟
|
|
||||||
final expectedTime = _startAudioTime + talkData.durationMs;
|
|
||||||
final audioDelay = currentTime - expectedTime;
|
|
||||||
|
|
||||||
// 如果延迟太大,清空缓冲区并直接播放
|
|
||||||
if (audioDelay > 500) {
|
|
||||||
state.audioBuffer.clear();
|
|
||||||
if (state.isOpenVoice.value) {
|
|
||||||
_playAudioFrames();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (state.audioBuffer.length >= audioBufferSize) {
|
if (state.audioBuffer.length >= audioBufferSize) {
|
||||||
state.audioBuffer.removeAt(0); // 丢弃最旧的数据
|
state.audioBuffer.removeAt(0); // 丢弃最旧的数据
|
||||||
}
|
}
|
||||||
@ -195,7 +180,6 @@ class TalkViewLogic extends BaseGetXController {
|
|||||||
// _frameCount = 0;
|
// _frameCount = 0;
|
||||||
// _lastFpsUpdateTime = currentTime;
|
// _lastFpsUpdateTime = currentTime;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// AppLog.log('⚠️ 帧未找到缓存 - Key: $cacheKey');
|
// AppLog.log('⚠️ 帧未找到缓存 - Key: $cacheKey');
|
||||||
state.videoBuffer.removeAt(oldestIndex); // 移除无法播放的帧
|
state.videoBuffer.removeAt(oldestIndex); // 移除无法播放的帧
|
||||||
@ -497,7 +481,6 @@ class TalkViewLogic extends BaseGetXController {
|
|||||||
_initAudioRecorder();
|
_initAudioRecorder();
|
||||||
|
|
||||||
requestPermissions();
|
requestPermissions();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -25,7 +25,9 @@ import 'package:star_lock/network/api_repository.dart';
|
|||||||
import 'package:star_lock/talk/call/g711.dart';
|
import 'package:star_lock/talk/call/g711.dart';
|
||||||
import 'package:star_lock/talk/starChart/constant/talk_status.dart';
|
import 'package:star_lock/talk/starChart/constant/talk_status.dart';
|
||||||
import 'package:star_lock/talk/starChart/handle/other/packet_loss_statistics.dart';
|
import 'package:star_lock/talk/starChart/handle/other/packet_loss_statistics.dart';
|
||||||
|
import 'package:star_lock/talk/starChart/handle/other/talk_data_model.dart';
|
||||||
import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
|
||||||
|
import 'package:star_lock/talk/starChart/proto/talk_data_h264_frame.pb.dart';
|
||||||
import 'package:star_lock/talk/starChart/proto/talk_expect.pb.dart';
|
import 'package:star_lock/talk/starChart/proto/talk_expect.pb.dart';
|
||||||
import 'package:star_lock/talk/starChart/star_chart_manage.dart';
|
import 'package:star_lock/talk/starChart/star_chart_manage.dart';
|
||||||
import 'package:star_lock/talk/starChart/views/talkView/talk_view_state.dart';
|
import 'package:star_lock/talk/starChart/views/talkView/talk_view_state.dart';
|
||||||
@ -44,6 +46,9 @@ class H264WebViewLogic extends BaseGetXController {
|
|||||||
// 添加模拟数据相关变量
|
// 添加模拟数据相关变量
|
||||||
static const int CHUNK_SIZE = 4096;
|
static const int CHUNK_SIZE = 4096;
|
||||||
Timer? _mockDataTimer;
|
Timer? _mockDataTimer;
|
||||||
|
int _startAudioTime = 0; // 开始播放时间戳
|
||||||
|
int audioBufferSize = 2; // 音频默认缓冲2帧
|
||||||
|
|
||||||
// 定义音频帧缓冲和发送函数
|
// 定义音频帧缓冲和发送函数
|
||||||
final List<int> _bufferedAudioFrames = <int>[];
|
final List<int> _bufferedAudioFrames = <int>[];
|
||||||
final Queue<List<int>> _frameBuffer = Queue<List<int>>();
|
final Queue<List<int>> _frameBuffer = Queue<List<int>>();
|
||||||
@ -51,7 +56,6 @@ class H264WebViewLogic extends BaseGetXController {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
|
||||||
// 初始化 WebView 控制器
|
// 初始化 WebView 控制器
|
||||||
state.webViewController = WebViewController()
|
state.webViewController = WebViewController()
|
||||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||||
@ -63,18 +67,40 @@ class H264WebViewLogic extends BaseGetXController {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
state.isShowLoading.value = true;
|
super.onInit();
|
||||||
// 加载本地 HTML
|
|
||||||
_loadLocalHtml();
|
|
||||||
// 创建流数据监听
|
// 创建流数据监听
|
||||||
_createFramesStreamListen();
|
_createFramesStreamListen();
|
||||||
// playLocalTestVideo();
|
|
||||||
_startListenTalkStatus();
|
_startListenTalkStatus();
|
||||||
state.talkStatus.value = state.startChartTalkStatus.status;
|
state.talkStatus.value = state.startChartTalkStatus.status;
|
||||||
// 初始化音频播放器
|
// 初始化音频播放器
|
||||||
_initFlutterPcmSound();
|
_initFlutterPcmSound();
|
||||||
|
|
||||||
// 初始化录音控制器
|
// 初始化录音控制器
|
||||||
_initAudioRecorder();
|
_initAudioRecorder();
|
||||||
|
|
||||||
|
// 加载本地 HTML
|
||||||
|
_loadLocalHtml();
|
||||||
|
|
||||||
|
// playLocalTestVideo();
|
||||||
|
|
||||||
|
requestPermissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> requestPermissions() async {
|
||||||
|
// 申请存储权限
|
||||||
|
var storageStatus = await Permission.storage.request();
|
||||||
|
// 申请录音权限
|
||||||
|
var microphoneStatus = await Permission.microphone.request();
|
||||||
|
|
||||||
|
if (storageStatus.isGranted && microphoneStatus.isGranted) {
|
||||||
|
print("Permissions granted");
|
||||||
|
} else {
|
||||||
|
print("Permissions denied");
|
||||||
|
// 如果权限被拒绝,可以提示用户或跳转到设置页面
|
||||||
|
if (await Permission.storage.isPermanentlyDenied) {
|
||||||
|
openAppSettings(); // 跳转到应用设置页面
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 初始化音频录制器
|
/// 初始化音频录制器
|
||||||
@ -96,16 +122,37 @@ class H264WebViewLogic extends BaseGetXController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _createFramesStreamListen() async {
|
void _createFramesStreamListen() async {
|
||||||
state.talkDataRepository.talkDataStream.listen((TalkData event) async {
|
state.talkDataRepository.talkDataStream
|
||||||
// 添加新帧到缓冲区
|
.listen((TalkDataModel talkDataModel) async {
|
||||||
_frameBuffer.add(event.content);
|
final talkData = talkDataModel.talkData;
|
||||||
|
final contentType = talkData!.contentType;
|
||||||
|
final currentTime = DateTime.now().millisecondsSinceEpoch;
|
||||||
|
|
||||||
// 当缓冲区超过最大容量时,发送最早的帧并移除
|
// 判断数据类型,进行分发处理
|
||||||
while (_frameBuffer.length > FRAME_BUFFER_SIZE) {
|
switch (contentType) {
|
||||||
if (_frameBuffer.isNotEmpty) {
|
case TalkData_ContentTypeE.G711:
|
||||||
final frame = _frameBuffer.removeFirst();
|
if (state.audioBuffer.length >= audioBufferSize) {
|
||||||
await _sendBufferedData(frame);
|
state.audioBuffer.removeAt(0); // 丢弃最旧的数据
|
||||||
}
|
}
|
||||||
|
state.audioBuffer.add(talkData); // 添加新数据
|
||||||
|
// 添加音频播放逻辑,与视频类似
|
||||||
|
_playAudioFrames();
|
||||||
|
break;
|
||||||
|
case TalkData_ContentTypeE.H264:
|
||||||
|
// // 添加新帧到缓冲区
|
||||||
|
_frameBuffer.add(talkData.content);
|
||||||
|
|
||||||
|
// 当缓冲区超过最大容量时,发送最早的帧并移除
|
||||||
|
while (_frameBuffer.length > FRAME_BUFFER_SIZE) {
|
||||||
|
if (_frameBuffer.isNotEmpty) {
|
||||||
|
final frame = _frameBuffer.removeFirst();
|
||||||
|
await _sendBufferedData(frame);
|
||||||
|
}
|
||||||
|
if (state.isShowLoading.isTrue) {
|
||||||
|
state.isShowLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -134,6 +181,51 @@ class H264WebViewLogic extends BaseGetXController {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// 新增:音频帧播放逻辑
|
||||||
|
void _playAudioFrames() {
|
||||||
|
// 如果缓冲区为空或未达到目标大小,不进行播放
|
||||||
|
// 音频缓冲区要求更小,以减少延迟
|
||||||
|
if (state.audioBuffer.isEmpty ||
|
||||||
|
state.audioBuffer.length < audioBufferSize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找出时间戳最小的音频帧
|
||||||
|
TalkData? oldestFrame;
|
||||||
|
int oldestIndex = -1;
|
||||||
|
for (int i = 0; i < state.audioBuffer.length; i++) {
|
||||||
|
if (oldestFrame == null ||
|
||||||
|
state.audioBuffer[i].durationMs < oldestFrame.durationMs) {
|
||||||
|
oldestFrame = state.audioBuffer[i];
|
||||||
|
oldestIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保找到了有效帧
|
||||||
|
if (oldestFrame != null && oldestIndex != -1) {
|
||||||
|
if (state.isOpenVoice.value) {
|
||||||
|
// 播放音频
|
||||||
|
_playAudioData(oldestFrame);
|
||||||
|
}
|
||||||
|
state.audioBuffer.removeAt(oldestIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 播放音频数据
|
||||||
|
void _playAudioData(TalkData talkData) async {
|
||||||
|
if (state.isOpenVoice.value) {
|
||||||
|
final list =
|
||||||
|
G711().decodeAndDenoise(talkData.content, true, 8000, 300, 150);
|
||||||
|
// // 将 PCM 数据转换为 PcmArrayInt16
|
||||||
|
final PcmArrayInt16 fromList = PcmArrayInt16.fromList(list);
|
||||||
|
FlutterPcmSound.feed(fromList);
|
||||||
|
if (!state.isPlaying.value) {
|
||||||
|
FlutterPcmSound.play();
|
||||||
|
state.isPlaying.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 加载html文件
|
/// 加载html文件
|
||||||
Future<void> _loadLocalHtml() async {
|
Future<void> _loadLocalHtml() async {
|
||||||
// 加载 HTML 文件内容
|
// 加载 HTML 文件内容
|
||||||
@ -186,10 +278,10 @@ class H264WebViewLogic extends BaseGetXController {
|
|||||||
Timer.periodic(const Duration(seconds: 1), (Timer t) {
|
Timer.periodic(const Duration(seconds: 1), (Timer t) {
|
||||||
if (state.isShowLoading.isFalse) {
|
if (state.isShowLoading.isFalse) {
|
||||||
state.oneMinuteTime.value++;
|
state.oneMinuteTime.value++;
|
||||||
if (state.oneMinuteTime.value >= 60) {
|
// if (state.oneMinuteTime.value >= 60) {
|
||||||
t.cancel(); // 取消定时器
|
// t.cancel(); // 取消定时器
|
||||||
state.oneMinuteTime.value = 0;
|
// state.oneMinuteTime.value = 0;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
@ -321,7 +413,7 @@ class H264WebViewLogic extends BaseGetXController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 首先应用固定增益提升基础音量
|
// 首先应用固定增益提升基础音量
|
||||||
List<int> amplifiedFrame = _applyGain(frame, 1.6);
|
List<int> amplifiedFrame = _applyGain(frame, 1.8);
|
||||||
// 编码为G711数据
|
// 编码为G711数据
|
||||||
List<int> encodedData = G711Tool.encode(amplifiedFrame, 0); // 0表示A-law
|
List<int> encodedData = G711Tool.encode(amplifiedFrame, 0); // 0表示A-law
|
||||||
_bufferedAudioFrames.addAll(encodedData);
|
_bufferedAudioFrames.addAll(encodedData);
|
||||||
@ -409,7 +501,7 @@ class H264WebViewLogic extends BaseGetXController {
|
|||||||
});
|
});
|
||||||
|
|
||||||
final LockSetInfoEntity lockSetInfoEntity =
|
final LockSetInfoEntity lockSetInfoEntity =
|
||||||
await ApiRepository.to.getLockSettingInfoData(
|
await ApiRepository.to.getLockSettingInfoData(
|
||||||
lockId: lockId.toString(),
|
lockId: lockId.toString(),
|
||||||
);
|
);
|
||||||
if (lockSetInfoEntity.errorCode!.codeIsSuccessful) {
|
if (lockSetInfoEntity.errorCode!.codeIsSuccessful) {
|
||||||
@ -427,7 +519,6 @@ class H264WebViewLogic extends BaseGetXController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
// _mockDataTimer?.cancel();
|
// _mockDataTimer?.cancel();
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import 'package:flutter_voice_processor/flutter_voice_processor.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:star_lock/talk/starChart/constant/talk_status.dart';
|
import 'package:star_lock/talk/starChart/constant/talk_status.dart';
|
||||||
import 'package:star_lock/talk/starChart/handle/other/talk_data_repository.dart';
|
import 'package:star_lock/talk/starChart/handle/other/talk_data_repository.dart';
|
||||||
|
import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart';
|
||||||
import 'package:star_lock/talk/starChart/status/star_chart_talk_status.dart';
|
import 'package:star_lock/talk/starChart/status/star_chart_talk_status.dart';
|
||||||
import 'package:star_lock/talk/starChart/views/talkView/talk_view_state.dart';
|
import 'package:star_lock/talk/starChart/views/talkView/talk_view_state.dart';
|
||||||
import 'package:webview_flutter/webview_flutter.dart';
|
import 'package:webview_flutter/webview_flutter.dart';
|
||||||
@ -49,4 +50,6 @@ class H264WebViewState {
|
|||||||
RxInt rotateAngle = 0.obs; // 旋转角度(以弧度为单位)
|
RxInt rotateAngle = 0.obs; // 旋转角度(以弧度为单位)
|
||||||
RxBool hasAudioData = false.obs; // 是否有音频数据
|
RxBool hasAudioData = false.obs; // 是否有音频数据
|
||||||
RxInt lastAudioTimestamp = 0.obs; // 最后接收到的音频数据的时间戳
|
RxInt lastAudioTimestamp = 0.obs; // 最后接收到的音频数据的时间戳
|
||||||
|
List<TalkData> audioBuffer = <TalkData>[].obs;
|
||||||
|
RxBool isPlaying = false.obs; // 是否开始播放
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user