You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

292 lines
9.4 KiB

  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'dart:typed_data';
  4. import 'package:audio_waveforms/audio_waveforms.dart';
  5. import 'package:demo001/scenes/translate/TranslateState.dart';
  6. import 'package:demo001/tools/audio_tool.dart';
  7. import 'package:demo001/xunfei/phonetic_dictation/phonetic_dictaion_model/w.dart';
  8. import 'package:demo001/xunfei/recognition_result/recognition_content/recognition_content.dart';
  9. import 'package:demo001/xunfei/streamtrans_result/trans_content/trans_content.dart';
  10. import 'package:demo001/xunfei/xunfei_translate.dart';
  11. import 'package:get/get.dart';
  12. import 'package:logger/logger.dart';
  13. import 'package:path_provider/path_provider.dart';
  14. import 'package:permission_handler/permission_handler.dart';
  15. import 'package:record/record.dart';
  16. class TranslateLogic extends GetxController {
  17. late Directory savedirectory;
  18. final state = TranslateState();
  19. late XunFeiTranslate xunfei;
  20. late AudioRecorder _recorder;
  21. @override
  22. void onInit() {
  23. super.onInit();
  24. _requestPermissions();
  25. _recorder = AudioRecorder();
  26. xunfei = XunFeiTranslate(
  27. appId: "137dc132",
  28. apiKey: "1c1891a475e71250ecd1320303ad6545",
  29. apiSecret: "MjZhNDA1NTI1NWZkZDQxOTMxYzMyN2Yw",
  30. onRecognitionResult: _handleRecognaitionData,
  31. onStreamtransResult: _handleTranslateData,
  32. onAudioResult: _handleAudioData);
  33. }
  34. // 初始化录音器
  35. void _initRecorder() async {
  36. try {
  37. // 获取外部存储目录路径
  38. savedirectory = (await getExternalStorageDirectory())!;
  39. state.isRecorderReady.value = true;
  40. _log('录音器初始化成功');
  41. } catch (e) {
  42. _log('初始化录音器失败: $e');
  43. state.isRecorderReady.value = false;
  44. }
  45. }
  46. // 请求麦克风权限
  47. void _requestPermissions() async {
  48. try {
  49. if (await Permission.microphone.request().isGranted) {
  50. _log('麦克风权限已授予');
  51. } else {
  52. _log('麦克风权限被拒绝');
  53. }
  54. if (await Permission.storage.request().isGranted) {
  55. // 权限已授予
  56. } else {
  57. _log('存储功能未相授权,无法保存录音文件!!!');
  58. }
  59. } catch (e) {
  60. _log('请求麦克风权限失败: $e');
  61. }
  62. }
  63. // 切换按钮状态
  64. void toggleCallStatus() {
  65. if (!state.isRecording.value) {
  66. //开始通话
  67. _startRecorder();
  68. } else {
  69. //结束通话
  70. _stopRecorder();
  71. }
  72. state.isRecording.value = !state.isRecording.value;
  73. }
  74. //开始录音
  75. void _startRecorder() async {
  76. try {
  77. if (!state.isRecorderReady.value) {
  78. _initRecorder();
  79. }
  80. if (state.isRecording.value) return; // 防止重复调用
  81. Stream<Uint8List> dataStream = await _recorder.startStream(RecordConfig(
  82. sampleRate: 16000, encoder: AudioEncoder.pcm16bits, numChannels: 1));
  83. xunfei.starttranslate(dataStream);
  84. state.isRecording.value = true;
  85. _log('录音开始');
  86. } catch (e) {
  87. _log('录音开始 异常: $e');
  88. }
  89. }
  90. //结束录音
  91. void _stopRecorder() async {
  92. try {
  93. if (!state.isRecording.value) return; // 防止重复调用
  94. await _recorder.stop();
  95. await _recorder.cancel();
  96. xunfei.stoptranslate();
  97. state.isRecorderReady.value = false;
  98. state.isRecording.value = false;
  99. _log('录音停止');
  100. } catch (e) {
  101. _log('录音停止 异常: $e');
  102. }
  103. }
  104. void _handleRecognaitionData(result) {
  105. KDXFSentenceModel model;
  106. String text = "";
  107. try {
  108. final index = state.kdxfSentenceList.indexWhere((KDXFSentenceModel e) {
  109. return e.sid == result.header?.sid;
  110. });
  111. if (index != -1) {
  112. model = state.kdxfSentenceList[index];
  113. final recogContextStr = utf8.decode(
  114. base64Decode(result.payload?.recognitionResults?.text ?? ''));
  115. final ctx = RecognitionContent.fromJson(jsonDecode(recogContextStr));
  116. if (ctx.pgs == 'apd') {
  117. String text = state.kdxfSentenceList[index].content;
  118. state.kdxfSentenceList[index].contentList.add(ctx);
  119. ctx.ws!.forEach((e) {
  120. e.cw?.forEach((e2) {
  121. text = text + (e2.w ?? '');
  122. });
  123. });
  124. if (text.trim() == '') return;
  125. state.kdxfSentenceList[index].content = text;
  126. state.kdxfSentenceList.refresh();
  127. } else if (ctx.pgs == 'rpl') {
  128. String text = '';
  129. for (var i = ctx.rg?[0]; i! <= ctx.rg![1]; i++) {
  130. state.kdxfSentenceList[index].contentList.removeWhere((ee) {
  131. return ee.sn == i;
  132. });
  133. }
  134. state.kdxfSentenceList[index].contentList.add(ctx);
  135. state.kdxfSentenceList[index].contentList.forEach((e) {
  136. e.ws?.forEach((ee) {
  137. ee.cw?.forEach((e2) {
  138. text = text + (e2.w ?? '');
  139. });
  140. });
  141. });
  142. if (text.trim() == '') return;
  143. print("添加到对象列表中 $text ");
  144. state.kdxfSentenceList[index].content = text;
  145. state.kdxfSentenceList.refresh();
  146. // }
  147. }
  148. } else {
  149. final recogContextStr = utf8.decode(
  150. base64Decode(result.payload?.recognitionResults?.text ?? ''));
  151. final ctx = RecognitionContent.fromJson(jsonDecode(recogContextStr));
  152. ctx.ws!.forEach((e) {
  153. e.cw?.forEach((e2) {
  154. text = text + (e2.w ?? '');
  155. });
  156. });
  157. if (text == '') return;
  158. print("添加到对象列表中 $text ");
  159. model = KDXFSentenceModel(
  160. content: text,
  161. sid: result.header?.sid ?? '',
  162. transResult: '',
  163. audioPath: '',
  164. perviousWs: ctx.ws ?? [],
  165. );
  166. state.kdxfSentenceList.add(model);
  167. state.kdxfSentenceList.refresh();
  168. }
  169. } catch (e) {
  170. print("接收识别结果异常 $e");
  171. }
  172. }
  173. void _handleTranslateData(result) {
  174. KDXFSentenceModel model;
  175. String text = "";
  176. try {
  177. final index = state.kdxfSentenceList.indexWhere((KDXFSentenceModel e) {
  178. return e.sid == result.header?.sid;
  179. });
  180. if (index != -1) {
  181. model = state.kdxfSentenceList[index];
  182. final transStr = utf8.decode(
  183. base64Decode(result.payload?.streamtransResults?.text ?? ''));
  184. final trctx = TransContent.fromJson(jsonDecode(transStr));
  185. if (trctx.isFinal == 0) {
  186. //更新
  187. String text = '';
  188. model.isFinalTransString.forEach((e) {
  189. text = text + e;
  190. });
  191. text = text + (trctx.dst ?? '');
  192. model.transResult = text;
  193. state.kdxfSentenceList.refresh();
  194. } else if (trctx.isFinal == 1) {
  195. model.isFinalTransString.add(trctx.dst ?? '');
  196. String text = '';
  197. model.isFinalTransString.forEach((e) {
  198. text = text + e;
  199. });
  200. model.transResult = text;
  201. state.kdxfSentenceList.refresh();
  202. }
  203. } else {
  204. final transStr = utf8.decode(
  205. base64Decode(result.payload?.streamtransResults?.text ?? ''));
  206. final textModel = TransContent.fromJson(jsonDecode(transStr));
  207. text = textModel.dst ?? '';
  208. final model = KDXFSentenceModel(
  209. content: '',
  210. sid: result.header?.sid ?? '',
  211. transResult: text,
  212. audioPath: '',
  213. perviousWs: []);
  214. state.kdxfSentenceList.add(model);
  215. state.kdxfSentenceList.refresh();
  216. }
  217. } catch (e) {
  218. print("接收识别结果异常 $e");
  219. }
  220. }
  221. //处理音频数据
  222. void _handleAudioData(AudioModel audo) {
  223. KDXFSentenceModel model;
  224. AudioTool.share.addAudioChunk(
  225. model: audo,
  226. onPlaying: () {},
  227. onPlayEnd: () {},
  228. onPath: (path) async {
  229. final file = File(path);
  230. if (file.existsSync()) {
  231. print("File exists");
  232. } else {
  233. print("File does not exist");
  234. }
  235. if (state.kdxfSentenceList.isNotEmpty) {
  236. try {
  237. print("收到音频数据:$path --------------------------");
  238. final index =
  239. state.kdxfSentenceList.indexWhere((KDXFSentenceModel e) {
  240. return e.sid == audo.sid;
  241. });
  242. model = state.kdxfSentenceList[index];
  243. model.audioPath = path;
  244. print("初始化和播放器 !");
  245. await model.playerController.preparePlayer(path: path);
  246. int duration = (await model.playerController.getDuration());
  247. model.audioDuration = duration;
  248. print("设置播放模式 !");
  249. model.playerController
  250. .setFinishMode(finishMode: FinishMode.pause);
  251. if (!xunfei.isspeaking) {
  252. print("可以播放:$path --------------------------");
  253. xunfei.isRecording = false;
  254. //为说话 可以播放
  255. await model.playerController.startPlayer();
  256. model.playerController.onCompletion.listen((_) {
  257. model.playerController.seekTo(0);
  258. xunfei.isRecording = true;
  259. });
  260. }
  261. state.kdxfSentenceList.refresh();
  262. } catch (e) {
  263. print("播放音频异常:$e");
  264. }
  265. }
  266. });
  267. }
  268. void kdxfPlayAudio(KDXFSentenceModel model) async {
  269. if (!xunfei.isspeaking) {
  270. model.playerController.startPlayer();
  271. }
  272. }
  273. void _log(String msg) {
  274. Logger().f("LIWEI---------------:$msg");
  275. }
  276. }