import 'dart:convert'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:http/http.dart' as http; import '../../../core/utils/logger.dart'; import '../../../core/utils/synchrodata.dart'; import '../../models/appconfig.dart'; import '../db/sqflite_api.dart'; import '../deapsound_ai_service.dart'; import 'meeting_upload_service.dart'; class MeetingTaskService extends GetxService { final GetStorage _storage = GetStorage(); MeetingUploadService get _uploadService => Get.find(); List _taskList = []; RxList taskFinishList = [].obs; bool _isTask = false; String _systemPrompt = ''; String _userId = ''; final String _appid = '2316081933'; final String _token = 'mcJTh6OelBqU_L78lgGd77Nyrc_-5-En'; final String _cluster = 'volc_auc_tele_flash'; final String _serviceUrl = 'https://openspeech.bytedance.com/api/v1/auc'; Map _headers = {}; int meetingId = 0; RxInt tasktype = 1.obs; List textList = []; String summary = ''; String overview = ''; @override void onInit() { super.onInit(); _headers = { 'Authorization': 'Bearer; $_token', 'Content-Type': 'application/json', }; _getAgent(); _getTaskList(); } void _getAgent() async { Map userInfo = _storage.read("user_info"); _userId = userInfo['user']['uid']; _systemPrompt = AppConfig.agentsystemPrompt("meet_assistant") ?? ''; } void _getTaskList() { _taskList = _storage.read("meeting_task_list") ?? []; taskFinishList.value = _storage.read("meeting_task_finish_list") ?? []; _executeTask(); } Future addTask(int id, String audiourl, String taskid) async { if (audiourl.isEmpty) { Map uploadData = _uploadService.uploadList.firstWhere( (element) => element['id'] == id, orElse: () => {}, ); if (uploadData.isNotEmpty) { if (uploadData['audiourl'].isEmpty) { uploadData['isTask'] = true; } else { await addTaskList(id, uploadData['audiourl'], taskid); } } } else { await addTaskList(id, audiourl, taskid); } } Future addTaskList(int id, String audiourl, String taskId) async { if (taskId.isEmpty) { taskId = await _submitTask(audiourl); } await SqfliteApi.editMeeting(id, {'tasktype': 1, 'taskid': taskId}); _taskList.add({ 'id': id, 'taskid': taskId, 'tasktype': 1, }); taskFinishList.add({ 'id': id, 'tasktype': 1, }); _storage.write("meeting_task_list", _taskList); _storage.write("meeting_task_finish_list", taskFinishList); _executeTask(); } void _executeTask() async { if (_isTask) return; _isTask = true; while (_taskList.isNotEmpty) { await Future.delayed(const Duration(seconds: 2)); for (var element in List.from(_taskList)) { await _fileRecognize(element); } } _isTask = false; } void removeTask(int id, {bool isDeleteTask = false}) { Map taskFinishData = taskFinishList.firstWhere( (element) => element['id'] == id, orElse: () => {}, ); if (taskFinishData.isNotEmpty) { if (isDeleteTask || taskFinishData['tasktype'] >= 3) { taskFinishList.remove(taskFinishData); _storage.write("meeting_task_finish_list", taskFinishList); } } if (isDeleteTask) { _taskList.removeWhere((element) => element['id'] == id); _storage.write("meeting_task_list", _taskList); } } Future _submitTask(String audiourl) async { String format = _getFileType(audiourl); final requestBody = jsonEncode({ "app": { "appid": _appid, "token": _token, "cluster": _cluster, }, "user": { "uid": _userId, }, "audio": { "format": format, "url": audiourl, }, "additions": { "with_speaker_info": "True", } }); try { final response = await http.post( Uri.parse('$_serviceUrl/submit'), headers: _headers, body: requestBody, ); if (response.statusCode != 200) { throw Exception('Submit failed with status: ${response.statusCode}'); } final respDic = jsonDecode(response.body); final taskId = respDic['resp']['id'] as String; Logger.debug('taskId: $taskId'); return taskId; } catch (e) { Logger.error('Submit error: ${e.toString()}'); rethrow; } } String _getFileType(String path) { List array = path.split('.'); return array[array.length - 1]; } Future> _queryTask(String taskId) async { final queryBody = jsonEncode({ "appid": _appid, "token": _token, "id": taskId, "cluster": _cluster, }); try { final response = await http.post( Uri.parse('$_serviceUrl/query'), headers: _headers, body: queryBody, ); if (response.statusCode != 200) { throw Exception('Query failed with status: ${response.statusCode}'); } final respDic = jsonDecode(response.body); return respDic; } catch (e) { Logger.error('Query error: ${e.toString()}'); rethrow; } } Future _fileRecognize(Map item) async { try { var respDic = await _queryTask(item['taskid']); var code = respDic['resp']['code'] as int; if (code == 1000) { await _addTextList(item['id'], respDic['resp']['utterances']); return; } else if (code < 2000) { Logger.debug("FileRecognize failed"); return; } } catch (e) { Logger.error('Error occurred: ${e.toString()}'); } } Future _addTextList(int id, List utterances) async { String text = ''; String personnel = ''; List> list = []; for (var element in utterances) { String speaker = ''; if (element['additions'].isNotEmpty) { speaker = 'Speaker ${element['additions']['speaker']}'; text += '[$speaker]: '; if (!personnel.contains(speaker)) { personnel += '[$speaker] '; } } list.add({ 'meetingid': id, 'content': element['text'], 'starttime': element['start_time'], 'endtime': element['end_time'], 'speaker': speaker, }); text += '${element['text']}\n'; } var result = await SqfliteApi.insertMeetingSpeaker(list); if (result != null) { await SqfliteApi.editMeeting( id, {'tasktype': 2, 'personnel': personnel}, ); List speakerList = await SqfliteApi.getMeetingSpeaker(id); List newSpeakerList = List.from(speakerList); Synchrodata.saveOperationRecord('update', { 'original': jsonEncode(newSpeakerList), 'id': id, }); if (id == meetingId) { textList = newSpeakerList; tasktype.value = 2; } _taskList.removeWhere((element) => element['id'] == id); Map taskFinishData = taskFinishList.firstWhere( (element) => element['id'] == id, orElse: () => {}, ); if (taskFinishData.isNotEmpty) { taskFinishData['tasktype'] = 2; taskFinishList.refresh(); } _storage.write("meeting_task_list", _taskList); _storage.write("meeting_task_finish_list", taskFinishList); } aiServiceMessage(id, text); } void aiServiceMessage(int id, String text) { int awaitQuantity = 0; String summaryText = ''; String overviewText = ''; DeapsoundAIService().sendMessage( messages: [ { 'role': 'system', 'content': '您将扮演一名会议总结专家,拥有超强的信息归纳与细分能力。不仅能高效处理各类通用场景会议,精准提炼会议核心内容,为后续思维导图生成奠定坚实基础。若涉及人员,人员名称保留[]。并根据内容只输出对应语言。', }, {'role': 'user', 'content': text}, ], ).then((value) { awaitQuantity++; summaryText = value; if (awaitQuantity >= 2) { _aiServiceValue(id, summaryText, overviewText); } }); DeapsoundAIService().sendMessage( messages: [ { 'role': 'system', 'content': '您将扮演一名会议事件归纳专家,能准确抓住会议中事件的关键点,并每个事件只需一句话精简总结。', }, {'role': 'user', 'content': text}, ], ).then((value) { awaitQuantity++; overviewText = value; if (awaitQuantity >= 2) { _aiServiceValue(id, summaryText, overviewText); } }); } void _aiServiceValue(int id, String summaryText, String overviewText) { SqfliteApi.editMeeting(id, { 'tasktype': 3, 'summary': summaryText, 'overview': overviewText, }); if (id == meetingId) { summary = summaryText; overview = overviewText; tasktype.value = 3; } Map taskFinishData = taskFinishList.firstWhere( (element) => element['id'] == id, orElse: () => {}, ); if (taskFinishData.isNotEmpty) { taskFinishData['tasktype'] = 3; taskFinishList.refresh(); } _storage.write("meeting_task_finish_list", taskFinishList); } }