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.

175 lines
5.2 KiB

import 'dart:io';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import '../../../core/utils/logger.dart';
import '../../../core/utils/upload_oss.dart';
import '../usage_stats_service.dart';
import '../db/sqflite_api.dart';
import 'meeting_task_service.dart';
import 'meeting_task_service2.dart';
/// 管理会议音频文件上传服务
class MeetingUploadService extends GetxService {
final _taskService = Get.find<MeetingTaskService>();
final GetStorage _storage = GetStorage();
RxInt meetingId = 0.obs;
RxDouble uploadProgress = 0.0.obs;
RxList uploadList = [].obs;
bool _isUpload = false;
int _handled = 0; //队列处理指针,表示当前循环语句处理的任务数量
@override
void onInit() {
super.onInit();
_getUploadList();
}
void cancelUpload() {
_isUpload = false;
_handled = 0;
uploadList.clear();
_storage.remove("meeting_upload_list");
}
void _getUploadList() {
uploadList.value = _storage.read("meeting_upload_list") ?? [];
executeUpload();
}
/// 添加待上传的音频文件
void addUpload(
int id,
String filePath,
String rootDir, {
bool isUpload = true,
}) async {
bool flash = false;
int fileSize = 0;
try {
fileSize = await File(filePath).length(); //获取文件大小
final details = await SqfliteApi.getMeetingDetails(id);
final int seconds = (details['seconds'] ?? 0) as int;
flash = seconds > 0 && seconds <= 7200;
} catch (_) {}
_storage.write("meeting_service_type_$id", flash ? 'fast' : 'standard');
uploadList.add({
'id': id,
'filepath': filePath,
'rootdir': rootDir,
'audiourl': '',
'isTask': false,
'isSpeaker': true,
'language': '',
'prompt': '',
'outline': '',
'useFlashASR': flash,
'fileSizeBytes': fileSize,
});
_storage.write("meeting_upload_list", uploadList);
if (isUpload) {
executeUpload();
}
}
void executeUpload() async {
if (_isUpload) return;
_isUpload = true;
_handled = 0;
while (_handled < uploadList.length) {
Map element = uploadList[_handled];
_handled++;
if (element['audiourl'].isEmpty) {
meetingId.value = element['id'];
try {
int _sent = 0;
int _total = 0;
final audiourl = await UploadOss.upload(
filepath: element['filepath'],
rootDir: element['rootdir'],
onSendProgress: (int count, int total) {
// uploadProgress.value = count / total;
_sent = count;
_total = total;
uploadProgress.value = total > 0 ? count / total : 0.0;
},
);
await SqfliteApi.editMeetingTitle(
element['id'],
{'audiourl': audiourl},
);
try {
// 记录对象存储用量
final svc = Get.isRegistered<UsageStatsService>()
? Get.find<UsageStatsService>()
: Get.put(UsageStatsService(), permanent: true);
int fileSizeBytes = 0;
try {
fileSizeBytes = element['fileSizeBytes'] ?? 0;
} catch (_) {}
final transferred = _total > 0 ? _total : fileSizeBytes;
svc.recordMeetingObjectStorage(
meetingId: element['id'],
storageUrl: audiourl,
storageBytes: fileSizeBytes,
transferBytes: transferred,
uploadTimestamp: DateTime.now().millisecondsSinceEpoch,
);
} catch (e) {
Logger.w('MeetingOSrecord', '对象存储用量记录失败: ' + e.toString());
}
if (element['isTask']) {
if (element['useFlashASR'] == true) {
final service2 = Get.find<MeetingTaskService2>();
await service2.addTaskList(
element['id'],
audiourl,
isSpeaker: element['isSpeaker'],
language: element['language'],
targetLanguage: '',
prompt: element['prompt'],
outline: element['outline'],
);
} else {
await _taskService.addTaskList(
element['id'],
audiourl,
'',
element['isSpeaker'],
element['language'],
element['prompt'],
element['outline'],
);
}
}
element['audiourl'] = audiourl;
uploadProgress.value = 0.0;
_storage.write("meeting_upload_list", uploadList);
} catch (e) {
Logger.error('Upload failed: $e');
}
}
}
meetingId.value = 0;
_isUpload = false;
}
void removeUpload(int id, {bool isDeleteTask = false}) {
Map uploadData = uploadList.firstWhere(
(element) => element['id'] == id,
orElse: () => {},
);
if (uploadData.isNotEmpty) {
if (isDeleteTask || uploadData['audiourl'].isNotEmpty) {
uploadList.remove(uploadData);
_storage.write("meeting_upload_list", uploadList);
if (uploadList.isEmpty) {
_handled = 0;
}
}
}
}
}