|
|
@ -10,7 +10,7 @@ import '../../../core/utils/logger.dart'; |
|
|
import '../../../core/utils/synchrodata.dart'; |
|
|
import '../../../core/utils/synchrodata.dart'; |
|
|
import '../deapsound_ai_service.dart'; |
|
|
import '../deapsound_ai_service.dart'; |
|
|
import 'meeting_upload_service.dart'; |
|
|
import 'meeting_upload_service.dart'; |
|
|
import 'meeting_task_service.dart'; |
|
|
// 移除标准版服务桥接,改为通过聚合器对外暴露统一状态 |
|
|
import 'summary_task_service.dart'; |
|
|
import 'summary_task_service.dart'; |
|
|
|
|
|
|
|
|
//火山引擎录音文件识别大模型-极速版 |
|
|
//火山引擎录音文件识别大模型-极速版 |
|
|
@ -140,43 +140,31 @@ class MeetingTaskService2 extends GetxService { |
|
|
taskFinishList.add({'id': id, 'tasktype': 1}); |
|
|
taskFinishList.add({'id': id, 'tasktype': 1}); |
|
|
_storage.write("meeting_task_list_v2", _taskList); |
|
|
_storage.write("meeting_task_list_v2", _taskList); |
|
|
_storage.write("meeting_task_finish_list_v2", taskFinishList); |
|
|
_storage.write("meeting_task_finish_list_v2", taskFinishList); |
|
|
try { |
|
|
// 由聚合器统一对外呈现状态,不直接写入标准版列表 |
|
|
final s1 = Get.find<MeetingTaskService>(); |
|
|
|
|
|
Map taskFinishData1 = s1.taskFinishList.firstWhere( |
|
|
|
|
|
(element) => element['id'] == id, |
|
|
|
|
|
orElse: () => {}, |
|
|
|
|
|
); |
|
|
|
|
|
if (taskFinishData1.isNotEmpty) { |
|
|
|
|
|
taskFinishData1['tasktype'] = 3; |
|
|
|
|
|
s1.taskFinishList.refresh(); |
|
|
|
|
|
} |
|
|
|
|
|
_storage.write("meeting_task_finish_list", s1.taskFinishList); |
|
|
|
|
|
} catch (_) {} |
|
|
|
|
|
_executeTask(); |
|
|
_executeTask(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void _executeTask() async { |
|
|
void _executeTask() async { |
|
|
if (_isTask) return; |
|
|
if (_isTask) return; |
|
|
_isTask = true; |
|
|
_isTask = true; |
|
|
Logger.debug('Starting task execution. Task count: ${_taskList.length}'); |
|
|
Logger.debug('开始执行任务,任务数量:${_taskList.length}'); |
|
|
|
|
|
|
|
|
while (_taskList.isNotEmpty) { |
|
|
while (_taskList.isNotEmpty) { |
|
|
Logger.debug('Task execution loop. Remaining tasks: ${_taskList.length}'); |
|
|
Logger.debug('任务循环执行,剩余任务:${_taskList.length}'); |
|
|
await Future.delayed(const Duration(seconds: 2)); |
|
|
await Future.delayed(const Duration(seconds: 2)); |
|
|
|
|
|
|
|
|
// 创建任务列表的副本,避免在迭代过程中修改原列表 |
|
|
// 创建任务列表的副本,避免在迭代过程中修改原列表 |
|
|
List tasksCopy = List.from(_taskList); |
|
|
List tasksCopy = List.from(_taskList); |
|
|
|
|
|
|
|
|
for (var element in tasksCopy) { |
|
|
for (var element in tasksCopy) { |
|
|
Logger.debug( |
|
|
Logger.debug('处理任务:${element['id']},音频:${element['audiourl']}'); |
|
|
'Processing task: ${element['id']} with audio: ${element['audiourl']}'); |
|
|
|
|
|
|
|
|
|
|
|
// 检查任务是否仍在列表中(可能已被其他地方移除) |
|
|
// 检查任务是否仍在列表中(可能已被其他地方移除) |
|
|
if (_taskList.any((task) => task['id'] == element['id'])) { |
|
|
if (_taskList.any((task) => task['id'] == element['id'])) { |
|
|
try { |
|
|
try { |
|
|
await _fileRecognize(element); |
|
|
await _fileRecognize(element); |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
Logger.error('Failed to process task ${element['id']}: $e'); |
|
|
Logger.error('处理任务失败:${element['id']},错误:$e'); |
|
|
// 确保失败的任务被移除,避免无限循环 |
|
|
// 确保失败的任务被移除,避免无限循环 |
|
|
_taskList.removeWhere((task) => task['id'] == element['id']); |
|
|
_taskList.removeWhere((task) => task['id'] == element['id']); |
|
|
_storage.write("meeting_task_list_v2", _taskList); |
|
|
_storage.write("meeting_task_list_v2", _taskList); |
|
|
@ -185,22 +173,19 @@ class MeetingTaskService2 extends GetxService { |
|
|
await SqfliteApi.editMeeting(element['id'], {'tasktype': 0}); |
|
|
await SqfliteApi.editMeeting(element['id'], {'tasktype': 0}); |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
Logger.debug( |
|
|
Logger.debug('任务 ${element['id']} 已从任务列表移除'); |
|
|
'Task ${element['id']} was already removed from task list'); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 如果没有任务被处理,避免无限循环 |
|
|
// 如果没有任务被处理,避免无限循环 |
|
|
if (_taskList.length == tasksCopy.length) { |
|
|
if (_taskList.length == tasksCopy.length) { |
|
|
Logger.warning( |
|
|
Logger.warning('本次循环未处理任何任务,为避免无限执行终止循环'); |
|
|
'No tasks were processed in this iteration. Breaking loop to avoid infinite execution.'); |
|
|
|
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
_isTask = false; |
|
|
_isTask = false; |
|
|
Logger.debug( |
|
|
Logger.debug('任务执行完成,剩余任务:${_taskList.length}'); |
|
|
'Task execution completed. Remaining tasks: ${_taskList.length}'); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void removeTask(int id, {bool isDeleteTask = false}) { |
|
|
void removeTask(int id, {bool isDeleteTask = false}) { |
|
|
@ -260,9 +245,9 @@ class MeetingTaskService2 extends GetxService { |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
// 记录请求详情 |
|
|
// 记录请求详情 |
|
|
Logger.debug('API Request URL: $_serviceUrl'); |
|
|
Logger.debug('API 请求地址:$_serviceUrl'); |
|
|
Logger.debug('API Request Headers: $requestHeaders'); |
|
|
Logger.debug('API 请求头:$requestHeaders'); |
|
|
Logger.debug('API Request Body: $requestBody'); |
|
|
Logger.debug('API 请求体:$requestBody'); |
|
|
|
|
|
|
|
|
final response = await http.post( |
|
|
final response = await http.post( |
|
|
Uri.parse(_serviceUrl), |
|
|
Uri.parse(_serviceUrl), |
|
|
@ -270,30 +255,27 @@ class MeetingTaskService2 extends GetxService { |
|
|
body: requestBody, |
|
|
body: requestBody, |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
Logger.debug('API Response Status: ${response.statusCode}'); |
|
|
Logger.debug('API 响应状态码:${response.statusCode}'); |
|
|
Logger.debug('API Response Headers: ${response.headers}'); |
|
|
Logger.debug('API 响应头:${response.headers}'); |
|
|
|
|
|
|
|
|
if (response.statusCode != 200) { |
|
|
if (response.statusCode != 200) { |
|
|
Logger.error( |
|
|
Logger.error('识别失败,状态码:${response.statusCode},响应体:${response.body}'); |
|
|
'Recognition failed with status: ${response.statusCode}, body: ${response.body}'); |
|
|
throw Exception('识别失败,状态码:${response.statusCode}'); |
|
|
throw Exception( |
|
|
|
|
|
'Recognition failed with status: ${response.statusCode}'); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
final respDic = jsonDecode(response.body); |
|
|
final respDic = jsonDecode(response.body); |
|
|
Logger.debug('Recognition response: $respDic'); |
|
|
Logger.debug('识别接口响应:$respDic'); |
|
|
|
|
|
|
|
|
// 检查响应中是否包含资源相关信息 |
|
|
// 检查响应中是否包含资源相关信息 |
|
|
if (respDic.containsKey('resource_id') || respDic.containsKey('model')) { |
|
|
if (respDic.containsKey('resource_id') || respDic.containsKey('model')) { |
|
|
|
|
|
Logger.debug('资源校验 - 使用的资源ID:volc.bigasr.auc_turbo'); |
|
|
Logger.debug( |
|
|
Logger.debug( |
|
|
'Resource verification - Resource ID used: volc.bigasr.auc_turbo'); |
|
|
'响应中的资源信息:${respDic['resource_id'] ?? respDic['model'] ?? '响应未包含'}'); |
|
|
Logger.debug( |
|
|
|
|
|
'Response resource info: ${respDic['resource_id'] ?? respDic['model'] ?? 'Not specified in response'}'); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return respDic; |
|
|
return respDic; |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
Logger.error('Recognition error: ${e.toString()}'); |
|
|
Logger.error('识别请求异常:${e.toString()}'); |
|
|
rethrow; |
|
|
rethrow; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -315,19 +297,18 @@ class MeetingTaskService2 extends GetxService { |
|
|
double parsed = double.parse(timeValue); |
|
|
double parsed = double.parse(timeValue); |
|
|
return parsed.round(); |
|
|
return parsed.round(); |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
Logger.error('Failed to parse time value: $timeValue'); |
|
|
Logger.error('时间值解析失败:$timeValue'); |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
Logger.error( |
|
|
Logger.error('未知的时间值类型:${timeValue.runtimeType},值:$timeValue'); |
|
|
'Unknown time value type: ${timeValue.runtimeType}, value: $timeValue'); |
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Future<void> _fileRecognize(Map item) async { |
|
|
Future<void> _fileRecognize(Map item) async { |
|
|
try { |
|
|
try { |
|
|
Logger.debug('Starting recognition for audio: ${item['audiourl']}'); |
|
|
Logger.debug('开始识别音频:${item['audiourl']}'); |
|
|
// 识别语言选取:若设置了目标输出语言且与录音语言一致,优先让ASR自动识别,避免错配 |
|
|
// 识别语言选取:若设置了目标输出语言且与录音语言一致,优先让ASR自动识别,避免错配 |
|
|
final String tplLang = |
|
|
final String tplLang = |
|
|
(((item['template'] ?? {})['language']) ?? '').toString(); |
|
|
(((item['template'] ?? {})['language']) ?? '').toString(); |
|
|
@ -344,8 +325,8 @@ class MeetingTaskService2 extends GetxService { |
|
|
language: asrLanguage, |
|
|
language: asrLanguage, |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
Logger.debug('Full API response structure: ${respDic.toString()}'); |
|
|
Logger.debug('API 全量响应结构:${respDic.toString()}'); |
|
|
Logger.debug('Response keys: ${respDic.keys.toList()}'); |
|
|
Logger.debug('响应包含的键:${respDic.keys.toList()}'); |
|
|
|
|
|
|
|
|
// 检查响应格式并提取utterances |
|
|
// 检查响应格式并提取utterances |
|
|
List utterances = []; |
|
|
List utterances = []; |
|
|
@ -354,77 +335,67 @@ class MeetingTaskService2 extends GetxService { |
|
|
if (respDic['result'] != null && |
|
|
if (respDic['result'] != null && |
|
|
respDic['result']['utterances'] != null) { |
|
|
respDic['result']['utterances'] != null) { |
|
|
utterances = respDic['result']['utterances']; |
|
|
utterances = respDic['result']['utterances']; |
|
|
Logger.debug( |
|
|
Logger.debug('在 result.utterances 中找到 ${utterances.length} 条语句'); |
|
|
'Found utterances in result.utterances: ${utterances.length} items'); |
|
|
|
|
|
} else if (respDic['resp'] != null && |
|
|
} else if (respDic['resp'] != null && |
|
|
respDic['resp']['utterances'] != null) { |
|
|
respDic['resp']['utterances'] != null) { |
|
|
utterances = respDic['resp']['utterances']; |
|
|
utterances = respDic['resp']['utterances']; |
|
|
Logger.debug( |
|
|
Logger.debug('在 resp.utterances 中找到 ${utterances.length} 条语句'); |
|
|
'Found utterances in resp.utterances: ${utterances.length} items'); |
|
|
|
|
|
} else if (respDic['utterances'] != null) { |
|
|
} else if (respDic['utterances'] != null) { |
|
|
utterances = respDic['utterances']; |
|
|
utterances = respDic['utterances']; |
|
|
Logger.debug( |
|
|
Logger.debug('在根级 utterances 中找到 ${utterances.length} 条语句'); |
|
|
'Found utterances in root.utterances: ${utterances.length} items'); |
|
|
|
|
|
} else if (respDic['data'] != null && |
|
|
} else if (respDic['data'] != null && |
|
|
respDic['data']['utterances'] != null) { |
|
|
respDic['data']['utterances'] != null) { |
|
|
utterances = respDic['data']['utterances']; |
|
|
utterances = respDic['data']['utterances']; |
|
|
Logger.debug( |
|
|
Logger.debug('在 data.utterances 中找到 ${utterances.length} 条语句'); |
|
|
'Found utterances in data.utterances: ${utterances.length} items'); |
|
|
|
|
|
} else if (respDic['response'] != null && |
|
|
} else if (respDic['response'] != null && |
|
|
respDic['response']['utterances'] != null) { |
|
|
respDic['response']['utterances'] != null) { |
|
|
utterances = respDic['response']['utterances']; |
|
|
utterances = respDic['response']['utterances']; |
|
|
Logger.debug( |
|
|
Logger.debug('在 response.utterances 中找到 ${utterances.length} 条语句'); |
|
|
'Found utterances in response.utterances: ${utterances.length} items'); |
|
|
|
|
|
} else { |
|
|
} else { |
|
|
// 检查是否有错误信息 |
|
|
// 检查是否有错误信息 |
|
|
if (respDic['error'] != null) { |
|
|
if (respDic['error'] != null) { |
|
|
Logger.error('API returned error: ${respDic['error']}'); |
|
|
Logger.error('接口返回错误:${respDic['error']}'); |
|
|
} else if (respDic['message'] != null) { |
|
|
} else if (respDic['message'] != null) { |
|
|
Logger.error('API returned message: ${respDic['message']}'); |
|
|
Logger.error('接口返回消息:${respDic['message']}'); |
|
|
} else { |
|
|
} else { |
|
|
Logger.error( |
|
|
Logger.error('未知的响应格式。可用键:${respDic.keys.toList()}'); |
|
|
'Unknown response format. Available keys: ${respDic.keys.toList()}'); |
|
|
|
|
|
// 尝试查找任何包含文本的字段 |
|
|
// 尝试查找任何包含文本的字段 |
|
|
respDic.forEach((key, value) { |
|
|
respDic.forEach((key, value) { |
|
|
Logger.debug( |
|
|
Logger.debug('键:$key,值类型:${value.runtimeType},值:$value'); |
|
|
'Key: $key, Value type: ${value.runtimeType}, Value: $value'); |
|
|
|
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (utterances.isNotEmpty) { |
|
|
if (utterances.isNotEmpty) { |
|
|
Logger.debug('Processing ${utterances.length} utterances'); |
|
|
Logger.debug('开始处理 ${utterances.length} 条语句'); |
|
|
await _addTextList(item['id'], utterances, item['template']); |
|
|
await _addTextList(item['id'], utterances, item['template']); |
|
|
// 从任务列表中移除已完成的任务 |
|
|
// 从任务列表中移除已完成的任务 |
|
|
_taskList.removeWhere((element) => element['id'] == item['id']); |
|
|
_taskList.removeWhere((element) => element['id'] == item['id']); |
|
|
_storage.write("meeting_task_list_v2", _taskList); |
|
|
_storage.write("meeting_task_list_v2", _taskList); |
|
|
Logger.debug( |
|
|
Logger.debug('音频识别成功,会议ID:${item['id']}'); |
|
|
'Recognition completed successfully for item ${item['id']}'); |
|
|
|
|
|
|
|
|
|
|
|
// 更新UI状态 - 如果是当前会议,触发UI更新 |
|
|
// 更新UI状态 - 如果是当前会议,触发UI更新 |
|
|
if (item['id'] == meetingId) { |
|
|
if (item['id'] == meetingId) { |
|
|
tasktype.value = 2; // 转写完成,进入分析阶段 |
|
|
tasktype.value = 2; // 转写完成,进入分析阶段 |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
Logger.error( |
|
|
Logger.error('响应中未发现语句。完整响应:$respDic'); |
|
|
"No utterances found in response. Full response: $respDic"); |
|
|
Logger.debug('未检测到语句,开始执行无声音频检查'); |
|
|
print( |
|
|
Logger.debug('无声音频检测调试信息'); |
|
|
'🔥🔥🔥 NO UTTERANCES FOUND - STARTING SILENT AUDIO CHECK 🔥🔥🔥'); |
|
|
Logger.debug('响应键列表:${respDic.keys.toList()}'); |
|
|
print('=== DEBUGGING SILENT AUDIO DETECTION ==='); |
|
|
Logger.debug('响应代码:${respDic['code']}'); |
|
|
print('Response keys: ${respDic.keys.toList()}'); |
|
|
Logger.debug('响应消息:${respDic['message']}'); |
|
|
print('Response code: ${respDic['code']}'); |
|
|
|
|
|
print('Response message: ${respDic['message']}'); |
|
|
|
|
|
|
|
|
|
|
|
// 检查是否为无声音频 |
|
|
// 检查是否为无声音频 |
|
|
bool isSilentAudio = _checkIfSilentAudio(respDic); |
|
|
bool isSilentAudio = _checkIfSilentAudio(respDic); |
|
|
print('Silent audio detection result: $isSilentAudio'); |
|
|
Logger.debug('无声检测结果:$isSilentAudio'); |
|
|
|
|
|
|
|
|
if (isSilentAudio) { |
|
|
if (isSilentAudio) { |
|
|
print('=== SILENT AUDIO DETECTED - SETTING TASKTYPE TO -1 ==='); |
|
|
Logger.debug('检测到无声音频,设置任务类型为 -1'); |
|
|
// 设置无声音频状态 (使用特殊值 -1) |
|
|
// 设置无声音频状态 (使用特殊值 -1) |
|
|
await SqfliteApi.editMeeting(item['id'], {'tasktype': -1}); |
|
|
await SqfliteApi.editMeeting(item['id'], {'tasktype': -1}); |
|
|
if (item['id'] == meetingId) { |
|
|
if (item['id'] == meetingId) { |
|
|
print('Setting tasktype.value to -1 for current meeting'); |
|
|
Logger.debug('当前会议设置 tasktype.value 为 -1'); |
|
|
tasktype.value = -1; // 无声音频 |
|
|
tasktype.value = -1; // 无声音频 |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -438,32 +409,10 @@ class MeetingTaskService2 extends GetxService { |
|
|
taskFinishList.refresh(); |
|
|
taskFinishList.refresh(); |
|
|
} |
|
|
} |
|
|
_storage.write("meeting_task_finish_list_v2", taskFinishList); |
|
|
_storage.write("meeting_task_finish_list_v2", taskFinishList); |
|
|
try { |
|
|
// 由聚合器统一对外呈现状态,不直接写入标准版列表 |
|
|
final s1 = Get.find<MeetingTaskService>(); |
|
|
// 由聚合器统一对外呈现状态,不直接写入标准版列表 |
|
|
Map taskFinishData1 = s1.taskFinishList.firstWhere( |
|
|
|
|
|
(element) => element['id'] == item['id'], |
|
|
|
|
|
orElse: () => {}, |
|
|
|
|
|
); |
|
|
|
|
|
if (taskFinishData1.isNotEmpty) { |
|
|
|
|
|
taskFinishData1['tasktype'] = 0; |
|
|
|
|
|
s1.taskFinishList.refresh(); |
|
|
|
|
|
} |
|
|
|
|
|
_storage.write("meeting_task_finish_list", s1.taskFinishList); |
|
|
|
|
|
} catch (_) {} |
|
|
|
|
|
try { |
|
|
|
|
|
final s1 = Get.find<MeetingTaskService>(); |
|
|
|
|
|
Map taskFinishData1 = s1.taskFinishList.firstWhere( |
|
|
|
|
|
(element) => element['id'] == item['id'], |
|
|
|
|
|
orElse: () => {}, |
|
|
|
|
|
); |
|
|
|
|
|
if (taskFinishData1.isNotEmpty) { |
|
|
|
|
|
taskFinishData1['tasktype'] = -1; |
|
|
|
|
|
s1.taskFinishList.refresh(); |
|
|
|
|
|
} |
|
|
|
|
|
_storage.write("meeting_task_finish_list", s1.taskFinishList); |
|
|
|
|
|
} catch (_) {} |
|
|
|
|
|
} else { |
|
|
} else { |
|
|
Logger.error('Recognition failed for unknown reason'); |
|
|
Logger.error('识别失败,原因未知'); |
|
|
// 识别失败,更新数据库状态为失败 |
|
|
// 识别失败,更新数据库状态为失败 |
|
|
await SqfliteApi.editMeeting(item['id'], {'tasktype': 0}); |
|
|
await SqfliteApi.editMeeting(item['id'], {'tasktype': 0}); |
|
|
if (item['id'] == meetingId) { |
|
|
if (item['id'] == meetingId) { |
|
|
@ -487,14 +436,14 @@ class MeetingTaskService2 extends GetxService { |
|
|
_storage.write("meeting_task_list_v2", _taskList); |
|
|
_storage.write("meeting_task_list_v2", _taskList); |
|
|
} |
|
|
} |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
Logger.error('Error occurred in _fileRecognize: ${e.toString()}'); |
|
|
Logger.error('文件识别流程发生异常:${e.toString()}'); |
|
|
Logger.error('Stack trace: ${StackTrace.current}'); |
|
|
Logger.error('堆栈信息:${StackTrace.current}'); |
|
|
|
|
|
|
|
|
// 更新数据库状态为失败 |
|
|
// 更新数据库状态为失败 |
|
|
try { |
|
|
try { |
|
|
await SqfliteApi.editMeeting(item['id'], {'tasktype': 0}); |
|
|
await SqfliteApi.editMeeting(item['id'], {'tasktype': 0}); |
|
|
} catch (dbError) { |
|
|
} catch (dbError) { |
|
|
Logger.error('Failed to update meeting status in database: $dbError'); |
|
|
Logger.error('数据库更新会议状态失败:$dbError'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 出错时也要从任务列表中移除,避免无限重试 |
|
|
// 出错时也要从任务列表中移除,避免无限重试 |
|
|
@ -510,7 +459,7 @@ class MeetingTaskService2 extends GetxService { |
|
|
|
|
|
|
|
|
/// 检查是否为无声音频 |
|
|
/// 检查是否为无声音频 |
|
|
bool _checkIfSilentAudio(Map<String, dynamic> response) { |
|
|
bool _checkIfSilentAudio(Map<String, dynamic> response) { |
|
|
print('Checking if silent audio, response: ${response.toString()}'); |
|
|
Logger.debug('检查是否为无声音频,响应:${response.toString()}'); |
|
|
|
|
|
|
|
|
// 检查API响应中的错误信息或状态码 |
|
|
// 检查API响应中的错误信息或状态码 |
|
|
// 根据实际API响应格式调整检测逻辑 |
|
|
// 根据实际API响应格式调整检测逻辑 |
|
|
@ -518,7 +467,7 @@ class MeetingTaskService2 extends GetxService { |
|
|
// 检查是否有错误码表示无声音频 |
|
|
// 检查是否有错误码表示无声音频 |
|
|
if (response['code'] != null) { |
|
|
if (response['code'] != null) { |
|
|
int code = response['code']; |
|
|
int code = response['code']; |
|
|
print('Found response code: $code'); |
|
|
Logger.debug('检测到响应代码:$code'); |
|
|
// 常见的无声音频错误码 |
|
|
// 常见的无声音频错误码 |
|
|
if (code == 40001 || |
|
|
if (code == 40001 || |
|
|
code == 40002 || |
|
|
code == 40002 || |
|
|
@ -526,7 +475,7 @@ class MeetingTaskService2 extends GetxService { |
|
|
code == 50001 || |
|
|
code == 50001 || |
|
|
code == 50002 || |
|
|
code == 50002 || |
|
|
code == 50003) { |
|
|
code == 50003) { |
|
|
print('Detected silent audio by error code: $code'); |
|
|
Logger.debug('根据错误码判断为无声音频:$code'); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -534,7 +483,7 @@ class MeetingTaskService2 extends GetxService { |
|
|
// 检查错误消息 |
|
|
// 检查错误消息 |
|
|
if (response['message'] != null) { |
|
|
if (response['message'] != null) { |
|
|
String message = response['message'].toString().toLowerCase(); |
|
|
String message = response['message'].toString().toLowerCase(); |
|
|
print('Found response message: $message'); |
|
|
Logger.debug('检测到响应消息:$message'); |
|
|
if (message.contains('silent') || |
|
|
if (message.contains('silent') || |
|
|
message.contains('no audio') || |
|
|
message.contains('no audio') || |
|
|
message.contains('无声') || |
|
|
message.contains('无声') || |
|
|
@ -543,7 +492,7 @@ class MeetingTaskService2 extends GetxService { |
|
|
message.contains('no speech') || |
|
|
message.contains('no speech') || |
|
|
message.contains('audio too short') || |
|
|
message.contains('audio too short') || |
|
|
message.contains('insufficient audio')) { |
|
|
message.contains('insufficient audio')) { |
|
|
print('Detected silent audio by message: $message'); |
|
|
Logger.debug('根据消息判断为无声音频:$message'); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -551,7 +500,7 @@ class MeetingTaskService2 extends GetxService { |
|
|
// 检查result中的错误信息 |
|
|
// 检查result中的错误信息 |
|
|
if (response['result'] != null && response['result']['error'] != null) { |
|
|
if (response['result'] != null && response['result']['error'] != null) { |
|
|
String error = response['result']['error'].toString().toLowerCase(); |
|
|
String error = response['result']['error'].toString().toLowerCase(); |
|
|
print('Found result error: $error'); |
|
|
Logger.debug('检测到 result.error:$error'); |
|
|
if (error.contains('silent') || |
|
|
if (error.contains('silent') || |
|
|
error.contains('no audio') || |
|
|
error.contains('no audio') || |
|
|
error.contains('无声') || |
|
|
error.contains('无声') || |
|
|
@ -559,7 +508,7 @@ class MeetingTaskService2 extends GetxService { |
|
|
error.contains('empty audio') || |
|
|
error.contains('empty audio') || |
|
|
error.contains('no speech') || |
|
|
error.contains('no speech') || |
|
|
error.contains('audio too short')) { |
|
|
error.contains('audio too short')) { |
|
|
print('Detected silent audio by result error: $error'); |
|
|
Logger.debug('根据 result.error 判断为无声音频:$error'); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -567,10 +516,10 @@ class MeetingTaskService2 extends GetxService { |
|
|
// 检查是否有音频时长信息且时长为0或极短 |
|
|
// 检查是否有音频时长信息且时长为0或极短 |
|
|
if (response['result'] != null && response['result']['duration'] != null) { |
|
|
if (response['result'] != null && response['result']['duration'] != null) { |
|
|
double duration = (response['result']['duration'] as num).toDouble(); |
|
|
double duration = (response['result']['duration'] as num).toDouble(); |
|
|
print('Found audio duration: $duration seconds'); |
|
|
Logger.debug('检测到音频时长:$duration 秒'); |
|
|
if (duration <= 0.5) { |
|
|
if (duration <= 0.5) { |
|
|
// 音频时长小于0.5秒认为是无声 |
|
|
// 音频时长小于0.5秒认为是无声 |
|
|
print('Detected silent audio by short duration: $duration'); |
|
|
Logger.debug('根据时长过短判断为无声音频:$duration'); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -618,10 +567,10 @@ class MeetingTaskService2 extends GetxService { |
|
|
1000; // 转换为秒 |
|
|
1000; // 转换为秒 |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
print('Found empty text content, audio duration: $audioDuration seconds'); |
|
|
Logger.debug('文本内容为空,音频时长:$audioDuration 秒'); |
|
|
if (audioDuration > 1.0) { |
|
|
if (audioDuration > 1.0) { |
|
|
// 音频时长大于1秒但没有文本内容,认为是无声音频 |
|
|
// 音频时长大于1秒但没有文本内容,认为是无声音频 |
|
|
print('Detected silent audio: empty text with sufficient duration'); |
|
|
Logger.debug('判断为无声音频:文本为空且时长充足'); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -637,25 +586,25 @@ class MeetingTaskService2 extends GetxService { |
|
|
|
|
|
|
|
|
// 如果有成功状态码但没有utterances,很可能是无声音频 |
|
|
// 如果有成功状态码但没有utterances,很可能是无声音频 |
|
|
if (hasSuccessCode) { |
|
|
if (hasSuccessCode) { |
|
|
print('Detected silent audio: success code but no utterances'); |
|
|
Logger.debug('判断为无声音频:成功状态码但无语句'); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
print('Not detected as silent audio'); |
|
|
Logger.debug('未判定为无声音频'); |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Future<void> _addTextList(int id, List utterances, |
|
|
Future<void> _addTextList(int id, List utterances, |
|
|
[Map? templateData]) async { |
|
|
[Map? templateData]) async { |
|
|
Logger.debug('Processing ${utterances.length} utterances for meeting $id'); |
|
|
Logger.debug('处理会议 $id 的 ${utterances.length} 条语句'); |
|
|
String text = ''; |
|
|
String text = ''; |
|
|
String personnel = ''; |
|
|
String personnel = ''; |
|
|
List<Map<String, Object?>> list = []; |
|
|
List<Map<String, Object?>> list = []; |
|
|
|
|
|
|
|
|
for (int i = 0; i < utterances.length; i++) { |
|
|
for (int i = 0; i < utterances.length; i++) { |
|
|
var element = utterances[i]; |
|
|
var element = utterances[i]; |
|
|
Logger.debug('Processing utterance $i: ${element.toString()}'); |
|
|
Logger.debug('处理第 $i 条语句:${element.toString()}'); |
|
|
|
|
|
|
|
|
String speaker = ''; |
|
|
String speaker = ''; |
|
|
String content = ''; |
|
|
String content = ''; |
|
|
@ -681,7 +630,7 @@ class MeetingTaskService2 extends GetxService { |
|
|
} else if (element['transcript'] != null) { |
|
|
} else if (element['transcript'] != null) { |
|
|
content = element['transcript'].toString(); |
|
|
content = element['transcript'].toString(); |
|
|
} else { |
|
|
} else { |
|
|
Logger.error('No text content found in utterance: $element'); |
|
|
Logger.error('语句中未找到文本内容:$element'); |
|
|
continue; |
|
|
continue; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -718,11 +667,10 @@ class MeetingTaskService2 extends GetxService { |
|
|
}); |
|
|
}); |
|
|
text += '$content\n'; |
|
|
text += '$content\n'; |
|
|
|
|
|
|
|
|
Logger.debug( |
|
|
Logger.debug('已添加语句:说话人=$speaker,内容=$content,开始=$startTime,结束=$endTime'); |
|
|
'Added utterance: speaker=$speaker, content=$content, start=$startTime, end=$endTime'); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Logger.debug('Total processed utterances: ${list.length}'); |
|
|
Logger.debug('处理完成的语句总数:${list.length}'); |
|
|
var result = await SqfliteApi.insertMeetingSpeaker(list); |
|
|
var result = await SqfliteApi.insertMeetingSpeaker(list); |
|
|
if (result != null) { |
|
|
if (result != null) { |
|
|
// 初始用于总结/概览的文本,先用原始拼接文本作为默认值 |
|
|
// 初始用于总结/概览的文本,先用原始拼接文本作为默认值 |
|
|
@ -748,7 +696,7 @@ class MeetingTaskService2 extends GetxService { |
|
|
// 保持在“正在转写”状态,先进行翻译为目标语言 |
|
|
// 保持在“正在转写”状态,先进行翻译为目标语言 |
|
|
await _translateTextList(id, targetLanguage); |
|
|
await _translateTextList(id, targetLanguage); |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
Logger.error('Translate transcript failed: ${e.toString()}'); |
|
|
Logger.error('转写文本翻译失败:${e.toString()}'); |
|
|
} |
|
|
} |
|
|
// 翻译完成后再写入 personnel、设置已完成并刷新 UI |
|
|
// 翻译完成后再写入 personnel、设置已完成并刷新 UI |
|
|
await SqfliteApi.editMeeting( |
|
|
await SqfliteApi.editMeeting( |
|
|
@ -763,38 +711,8 @@ class MeetingTaskService2 extends GetxService { |
|
|
textList = newSpeakerList; |
|
|
textList = newSpeakerList; |
|
|
tasktype.value = 2; |
|
|
tasktype.value = 2; |
|
|
} |
|
|
} |
|
|
try { |
|
|
// 由聚合器统一对外呈现状态,不直接写入标准版列表 |
|
|
final s1 = Get.find<MeetingTaskService>(); |
|
|
// 由聚合器统一对外呈现状态,不直接写入标准版列表 |
|
|
if (id == s1.meetingId) { |
|
|
|
|
|
s1.textList = newSpeakerList; |
|
|
|
|
|
s1.tasktype.value = 2; |
|
|
|
|
|
} |
|
|
|
|
|
Map taskFinishData1 = s1.taskFinishList.firstWhere( |
|
|
|
|
|
(element) => element['id'] == id, |
|
|
|
|
|
orElse: () => {}, |
|
|
|
|
|
); |
|
|
|
|
|
if (taskFinishData1.isNotEmpty) { |
|
|
|
|
|
taskFinishData1['tasktype'] = 2; |
|
|
|
|
|
s1.taskFinishList.refresh(); |
|
|
|
|
|
} |
|
|
|
|
|
_storage.write("meeting_task_finish_list", s1.taskFinishList); |
|
|
|
|
|
} catch (_) {} |
|
|
|
|
|
try { |
|
|
|
|
|
final s1 = Get.find<MeetingTaskService>(); |
|
|
|
|
|
if (id == s1.meetingId) { |
|
|
|
|
|
s1.textList = newSpeakerList; |
|
|
|
|
|
s1.tasktype.value = 2; |
|
|
|
|
|
} |
|
|
|
|
|
Map taskFinishData1 = s1.taskFinishList.firstWhere( |
|
|
|
|
|
(element) => element['id'] == id, |
|
|
|
|
|
orElse: () => {}, |
|
|
|
|
|
); |
|
|
|
|
|
if (taskFinishData1.isNotEmpty) { |
|
|
|
|
|
taskFinishData1['tasktype'] = 2; |
|
|
|
|
|
s1.taskFinishList.refresh(); |
|
|
|
|
|
} |
|
|
|
|
|
_storage.write("meeting_task_finish_list", s1.taskFinishList); |
|
|
|
|
|
} catch (_) {} |
|
|
|
|
|
// 用最新(已翻译)的文本重建总结/概览输入 |
|
|
// 用最新(已翻译)的文本重建总结/概览输入 |
|
|
summarySourceText = ''; |
|
|
summarySourceText = ''; |
|
|
for (var element in newSpeakerList) { |
|
|
for (var element in newSpeakerList) { |
|
|
@ -967,7 +885,7 @@ class MeetingTaskService2 extends GetxService { |
|
|
final obj = jsonDecode(translated); |
|
|
final obj = jsonDecode(translated); |
|
|
arr = (obj is Map && obj['data'] is List) ? (obj['data'] as List) : []; |
|
|
arr = (obj is Map && obj['data'] is List) ? (obj['data'] as List) : []; |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
Logger.error('Parse translation JSON failed: ${e.toString()}'); |
|
|
Logger.error('翻译结果 JSON 解析失败:${e.toString()}'); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|