123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889 |
- package com.backendsys.service.SDKService.SDKTencent;
- import cn.hutool.core.util.StrUtil;
- import cn.hutool.json.JSONObject;
- import cn.hutool.json.JSONUtil;
- import com.backendsys.aspect.HttpRequestAspect;
- import com.backendsys.entity.Ai.Aiivh.*;
- import com.backendsys.entity.Ai.Aiivh.AiivhAsset.AiivhAssetQuotaStatisticsDTO;
- import com.backendsys.entity.Ai.Aiivh.AiivhMakeBroadcastTask.SpeechParamDTO;
- import com.backendsys.entity.Ai.Aiivh.AiivhMakeBroadcastTask.VideoParamAnchorParamDTO;
- import com.backendsys.entity.Ai.Aiivh.AiivhMakeBroadcastTask.VideoParamDTO;
- import com.backendsys.entity.Ai.Aiivh.AiivhMakeBroadcastTask.VideoParamLogoParamDTO;
- import com.backendsys.entity.Tencent.*;
- import com.backendsys.enums.IvhQuotaActiveEvent;
- import com.backendsys.exception.CustException;
- import com.backendsys.mapper.Ai.Aiivh.AiivhQuotaHistoryMapper;
- import com.backendsys.mapper.Ai.Aiivh.AiivhQuotaMapper;
- import com.backendsys.service.Ai.Aiivh.AiivhAssetService;
- import com.backendsys.service.Ai.Aiivh.AiivhMakeVirtualmanTaskService;
- import com.backendsys.utils.ListUtil;
- import com.backendsys.utils.MapUtil;
- import org.redisson.api.*;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Lazy;
- import org.springframework.core.ParameterizedTypeReference;
- import org.springframework.http.HttpHeaders;
- import org.springframework.http.HttpMethod;
- import org.springframework.http.MediaType;
- import org.springframework.messaging.handler.annotation.Payload;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.web.reactive.function.client.WebClient;
- import org.springframework.web.util.UriComponentsBuilder;
- import java.lang.reflect.Field;
- import java.net.URI;
- import java.time.LocalDateTime;
- import java.time.format.DateTimeFormatter;
- import java.util.*;
- import java.util.concurrent.TimeUnit;
- import java.util.stream.Collectors;
- @Service
- public class SDKTencentAiVirtualmanServiceImpl implements SDKTencentAiVirtualmanService {
- @Lazy
- @Autowired
- RedissonClient redissonClient;
- @Autowired
- private HttpRequestAspect httpRequestAspect;
- @Autowired
- private SDKTencentService sdkTencentService;
- @Autowired
- private AiivhMakeVirtualmanTaskService aiivhMakeVirtualmanTaskService;
- @Autowired
- private AiivhAssetService aiivhAssetService;
- @Autowired
- private AiivhQuotaMapper aiivhQuotaMapper;
- @Autowired
- private AiivhQuotaHistoryMapper aiivhQuotaHistoryMapper;
- @Value("${tencent.ivh.app-key}")
- private String appKey;
- @Value("${tencent.ivh.access-token}")
- private String accessToken;
- @Value("${tencent.ivh.empty-app-key}")
- private String emptyAppKey;
- @Value("${tencent.ivh.empty-access-token}")
- private String emptyAccessToken;
- /**
- * [腾讯-数智人] 初始化 定制数智人列表 (使用公司账号)
- */
- @Transactional
- public Map<String, Object> initCustomVirtualman(Integer pageIndex, Integer pageSize) {
- Map<String, Object> payload = new HashMap<>();
- payload.put("VirtualmanTypeCode", "small_sample_2d");
- // payload.put("AnchorCodes", "Array of [string]");
- payload.put("PageIndex", pageIndex);
- payload.put("PageSize", pageSize);
- Map<String, Object> resultMap = Collections.singletonMap("Payload", payload);
- String bodyData = JSONUtil.toJsonStr(resultMap);
- // -- Http Request --------------------------------------------
- /**
- * 这里使用我自己的空白密钥,因为只有未创建自定义形象的账号,才能返回全部形象
- */
- Map<String, Object> signature = sdkTencentService.getSignature(appKey, accessToken); // 获得 Signature 签名
- String url = "https://gw.tvs.qq.com/v2/ivh/crmserver/customerassetservice/describesmallsampleimage";
- URI uriWithParams = UriComponentsBuilder.fromUriString(url)
- .queryParam("appkey", signature.get("appkey"))
- .queryParam("signature", "{signature}")
- .queryParam("timestamp", signature.get("timestamp"))
- .build(signature.get("signature"));
- // Http 远程调用
- Map<String, Object> resp = WebClient.create()
- .method(HttpMethod.POST)
- .uri(uriWithParams)
- .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
- .bodyValue(bodyData.toString())
- .retrieve().bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
- })
- .block();
- return resp;
- }
- /**
- * [腾讯-数智人] 初始化公共数智人列表 (使用空白账号)
- * 注:有效期:2024/03/25-2024/04/08 过期后能否继续查询?
- */
- @Transactional
- public Map<String, Object> initPublicVirtualman(Integer pageIndex, Integer pageSize) {
- Map<String, Object> payload = new HashMap<>();
- payload.put("VirtualmanTypeCode", "small_sample_2d");
- // payload.put("AnchorCodes", "Array of [string]");
- payload.put("PageIndex", pageIndex);
- payload.put("PageSize", pageSize);
- Map<String, Object> resultMap = Collections.singletonMap("Payload", payload);
- String bodyData = JSONUtil.toJsonStr(resultMap);
- // -- Http Request --------------------------------------------
- /**
- * 这里使用我自己的空白密钥,因为只有未创建自定义形象的账号,才能返回全部形象
- */
- Map<String, Object> signature = sdkTencentService.getSignature(emptyAppKey, emptyAccessToken); // 获得 Signature 签名
- String url = "https://gw.tvs.qq.com/v2/ivh/crmserver/customerassetservice/describesmallsampleimage";
- URI uriWithParams = UriComponentsBuilder.fromUriString(url)
- .queryParam("appkey", signature.get("appkey"))
- .queryParam("signature", "{signature}")
- .queryParam("timestamp", signature.get("timestamp"))
- .build(signature.get("signature"));
- // Http 远程调用
- Map<String, Object> resp = WebClient.create()
- .method(HttpMethod.POST)
- .uri(uriWithParams)
- .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
- .bodyValue(bodyData.toString())
- .retrieve().bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
- })
- .block();
- return resp;
- }
-
-
- /**
- * 基于实体类,将 anchor_name 转换为 AnchorName (将下划线转为大驼峰)
- *
- * Map<String, Object> resultMap = new HashMap<>();
- * convertObjectToMap(tencentCustomserviceDTO, resultMap);
- * System.out.println(resultMap);
- */
- public static void convertObjectToMap(Object obj, Map<String, Object> resultMap) throws IllegalAccessException {
- Class<?> clazz = obj.getClass();
- Field[] fields = clazz.getDeclaredFields();
- for (Field field : fields) {
- field.setAccessible(true);
- Object value = field.get(obj);
- String fieldName = field.getName();
- String convertedFieldName = StrUtil.upperFirst(StrUtil.toCamelCase(fieldName));
- if (value != null) {
- /**
- * 注意:需要手动填写实体类
- */
- if (value instanceof List) {
- // 如果值是列表类型,则遍历列表中的每个对象
- List<Object> list = (List<Object>)value;
- Map<String, Object> nestedMap = new HashMap<>();
- List<Map<String, Object>> nestedList = new ArrayList<>();
- for (Object item : list) {
- Map<String, Object> itemMap = new HashMap<>();
- convertObjectToMap(item, itemMap);
- nestedList.add(itemMap);
- }
- resultMap.put(convertedFieldName, nestedList);
- } else if (value.getClass().isAssignableFrom(VideoParamAnchorParamDTO.class) ||
- value.getClass().isAssignableFrom(VideoParamLogoParamDTO.class) ||
- value.getClass().isAssignableFrom(VideoParamDTO.class) ||
- value.getClass().isAssignableFrom(SpeechParamDTO.class) ||
- value.getClass().isAssignableFrom(TencentCustomservicePayloadDTO.class) ||
- value.getClass().isAssignableFrom(TencentCustomserviceConfirmPlayloadDTO.class) ||
- value.getClass().isAssignableFrom(TencentCustomserviceHeaderDTO.class) ||
- value.getClass().isAssignableFrom(Payload.class)) {
- // If the value is a nested object, recursively convert it to map
- Map<String, Object> nestedMap = new HashMap<>();
- convertObjectToMap(value, nestedMap);
- //
- fieldName = field.getName();
- convertedFieldName = StrUtil.upperFirst(StrUtil.toCamelCase(fieldName));
- resultMap.put(convertedFieldName, nestedMap);
- } else {
- fieldName = field.getName();
- convertedFieldName = StrUtil.upperFirst(StrUtil.toCamelCase(fieldName));
- resultMap.put(convertedFieldName, value);
- }
- }
- }
- }
- private String getAnchorNameView(String anchor_name) {
- LocalDateTime now = LocalDateTime.now();
- String timestamp = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
- return anchor_name + "_" + timestamp;
- }
- /**
- * [腾讯-数智人] 创建形象/音色定制任务
- */
- @Transactional
- public Map<String, Object> makeVirtualTask(TencentCustomserviceDTO tencentCustomserviceDTO) {
- RLock lock = redissonClient.getLock("makeVirtualTask");
- try { lock.tryLock(3, TimeUnit.SECONDS);
- // 参数校验:
- // - IdentityWrittenCosUrl 二选一或二者都传
- // - IdentityCosUrl 二选一或二者都传
- // 基于实体类,将 anchor_name 转换为 AnchorName (将下划线转为大驼峰)
- Map<String, Object> resultMap = new HashMap<>();
- // 生成: AnchorName 数智人名称_时间戳 (使接口值唯一,本地数据不唯一)
- // - anchor_name 唯一
- // - anchor_name_view 不唯一
- TencentCustomservicePayloadDTO payload = tencentCustomserviceDTO.getPayload();
- payload.setAnchor_name_view(getAnchorNameView(payload.getAnchor_name()));
- tencentCustomserviceDTO.setPayload(payload);
- convertObjectToMap(tencentCustomserviceDTO, resultMap);
- String bodyData = JSONUtil.toJsonStr(resultMap);
- // System.out.println("resultMap:");
- // System.out.println(resultMap);
- // System.out.println("-----------------------------------------");
- // System.out.println("bodyData:");
- // System.out.println(bodyData);
- // System.out.println("-----------------------------------------");
- // -- Http Request --------------------------------------------
- Map<String, Object> signature = sdkTencentService.getSignature(appKey, accessToken); // 获得 Signature 签名
- String url = "https://gw.tvs.qq.com/v2/ivh/assetmanager/customservice/make";
- URI uriWithParams = UriComponentsBuilder.fromUriString(url)
- .queryParam("appkey", signature.get("appkey"))
- .queryParam("signature", "{signature}")
- .queryParam("timestamp", signature.get("timestamp"))
- .build(signature.get("signature"));
- // Http 远程调用
- Map<String, Object> resp = WebClient.create()
- .method(HttpMethod.POST)
- .uri(uriWithParams)
- .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
- .bodyValue(bodyData)
- .retrieve().bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
- })
- .block();
- System.out.println(resp);
- //// 临时数据 (模拟成功)
- //Map<String, Object> tempPayload = new LinkedHashMap<>();
- //String uuid = String.valueOf(UUID.randomUUID());
- //tempPayload.put("TaskId", uuid);
- //resp.put("Payload", tempPayload);
- /**
- * 创建任务 (远程)
- */
- // 判断 任务是否创建成功 (是,则创建数据库记录)
- Integer respHeaderCode = (Integer) MapUtil.get(resp, "Header.Code");
- if (respHeaderCode == 0) {
- /**
- * 创建任务 (本地)
- */
- TencentCustomservicePayloadDTO tencentCustomservicePayloadDTO = tencentCustomserviceDTO.getPayload();
- String make_type = tencentCustomservicePayloadDTO.getMake_type();
- // -- [Post] 创建数智人任务 --------------------------------------------------------
- AiPersonDTO aiPersonDTO = new AiPersonDTO();
- // [查询] 自身 UserId
- Long user_id = httpRequestAspect.getUserId();
- aiPersonDTO.setUser_id(user_id);
- //
- aiPersonDTO.setRequest_id((String) MapUtil.get(resp, "Header.RequestID"));
- aiPersonDTO.setTask_id((String) MapUtil.get(resp, "Payload.TaskId"));
- aiPersonDTO.setAnchor_name(tencentCustomservicePayloadDTO.getAnchor_name_view());
- aiPersonDTO.setAnchor_name_view(tencentCustomservicePayloadDTO.getAnchor_name());
- aiPersonDTO.setMake_type(make_type);
- aiPersonDTO.setIdentity_cos_url(tencentCustomservicePayloadDTO.getIdentity_cos_url());
- aiPersonDTO.setIdentity_written_cos_url(tencentCustomservicePayloadDTO.getIdentity_written_cos_url());
- aiPersonDTO.setMaterial_cos_url(tencentCustomservicePayloadDTO.getMaterial_cos_url());
- aiPersonDTO.setIs_remove_background(tencentCustomservicePayloadDTO.getIs_remove_background());
- aiPersonDTO.setSex_type(tencentCustomservicePayloadDTO.getSex_type());
- aiPersonDTO.setNotes(tencentCustomservicePayloadDTO.getNotes());
- aiPersonDTO.setText_driver(tencentCustomservicePayloadDTO.getText_driver());
- aiPersonDTO.setVoice_driver_cos_file(tencentCustomservicePayloadDTO.getVoice_driver_cos_file());
- aiivhMakeVirtualmanTaskService.insertAiivhMakeVirtualmanTask(aiPersonDTO);
- /**
- * 创建任务之后,此时是 { "Stage": EXAMINE } 状态,还未生成任务,
- * 大概1分钟内才会更变状态
- *
- * 创建任务成功后,创建一个临时 [形象] 记录,主要是记录 user_id 和 anchor_name 字段
- * 等待用户访问查询详情接口之后,再更新 [形象详情]
- */
- if(make_type.equals("IMAGE_GENERAL")) {
- // 定制形象 (创建临时记录)
- AiivhAnchorDTO aiivhAnchorDTO = new AiivhAnchorDTO();
- aiivhAnchorDTO.setAnchor_name(tencentCustomservicePayloadDTO.getAnchor_name_view());
- aiivhAnchorDTO.setAnchor_name_view(tencentCustomservicePayloadDTO.getAnchor_name());
- aiivhAnchorDTO.setUser_id(user_id);
- aiivhMakeVirtualmanTaskService.insertAiivhAnchorCustom(aiivhAnchorDTO);
- }
- if(make_type.equals("VOICE")) {
- // 定制音色 (创建临时记录)
- AiPersonTimbreCustomDTO aiPersonTimbreCustomDTO = new AiPersonTimbreCustomDTO();
- aiPersonTimbreCustomDTO.setTimbre_name(tencentCustomservicePayloadDTO.getAnchor_name_view());
- aiPersonTimbreCustomDTO.setTimbre_name_view(tencentCustomservicePayloadDTO.getAnchor_name());
- aiPersonTimbreCustomDTO.setUser_id(user_id);
- aiivhMakeVirtualmanTaskService.insertAiPersoneTimbreCustom(aiPersonTimbreCustomDTO);
- }
- }
- return resp;
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- } catch (InterruptedException e) { throw new RuntimeException(e);
- } finally { lock.unlock(); }
- }
- /**
- * [腾讯-数智人] 创建定制形象任务 (未提交远程)
- */
- @Transactional
- public Map<String, Object> insertVirtualmanTask(TencentCustomserviceDTO tencentCustomserviceDTO) {
- TencentCustomservicePayloadDTO tencentCustomservicePayloadDTO = tencentCustomserviceDTO.getPayload();
- // -- 将带 Payload 的参数进行格式化 --------------------------------------------------------
- AiPersonDTO aiPersonDTO = new AiPersonDTO();
- // [查询] 自身 UserId
- Long user_id = httpRequestAspect.getUserId();
- aiPersonDTO.setUser_id(user_id);
- //
- // aiPersonDTO.setRequest_id((String) MapUtil.get(resp, "Header.RequestID"));
- // aiPersonDTO.setTask_id((String) MapUtil.get(resp, "Payload.TaskId"));
- String anchor_name = tencentCustomservicePayloadDTO.getAnchor_name();
- aiPersonDTO.setAnchor_name(getAnchorNameView(anchor_name));
- aiPersonDTO.setAnchor_name_view(anchor_name);
- aiPersonDTO.setQuota_code(tencentCustomserviceDTO.getQueue_code());
- aiPersonDTO.setMake_type(tencentCustomserviceDTO.getPayload().getMake_type());
- aiPersonDTO.setIdentity_cos_url(tencentCustomservicePayloadDTO.getIdentity_cos_url());
- aiPersonDTO.setIdentity_written_cos_url(tencentCustomservicePayloadDTO.getIdentity_written_cos_url());
- aiPersonDTO.setMaterial_cos_url(tencentCustomservicePayloadDTO.getMaterial_cos_url());
- aiPersonDTO.setIs_remove_background(tencentCustomservicePayloadDTO.getIs_remove_background());
- aiPersonDTO.setSex_type(tencentCustomservicePayloadDTO.getSex_type());
- aiPersonDTO.setNotes(tencentCustomservicePayloadDTO.getNotes());
- aiPersonDTO.setText_driver(tencentCustomservicePayloadDTO.getText_driver());
- aiPersonDTO.setVoice_driver_cos_file(tencentCustomservicePayloadDTO.getVoice_driver_cos_file());
- aiPersonDTO.setTask_status("AUDIT");
- return aiivhMakeVirtualmanTaskService.insertAiivhMakeVirtualmanTask(aiPersonDTO);
- }
- /*
- // 排队机制(定时任务?)
- // 1.先查询排队表,如果为空,则提交,同时返回任务ID;如果前面有人,则排队,返回排队人数
- //
- // 2.数据插入定制数据人列表 (不执行),同时插入排队表 (包含提交的数据)
- // 4.用定时任务查询未完成记录 (查询成功或失败,则将排队表中的记录去除;同时将下一个任务自动提交)
- // 这一步还不用排队,要等运营人员点提交才有
- // // -- 使用 Redisson 排队 -----------------------------------------------------------------
- // RList<String> rList = redissonClient.getList("makeVirtualTaskQueue");
- // tencentCustomserviceDTO.setQueue_code(CommonUtil.generateUniqueRandomOrderCode("QUE"));
- // String jsonString = JSONUtil.toJsonStr(tencentCustomserviceDTO);
- // // 入队
- // rList.add(jsonString);
- */
- /**
- * [方法] 查询我的配额,并获得有效(类型匹配,状态可用,未过期),最近临期的那一条配额
- */
- private Map<String, Object> getEffectiveQuota(String quotaType, String makeType) {
- // [Get] 查询我的配额
- AiivhQuotaDTO aiivhQuotaDTO = new AiivhQuotaDTO();
- aiivhQuotaDTO.setUser_id(httpRequestAspect.getUserId());
- List<Map<String, Object>> myQuota = aiivhQuotaMapper.queryAiivhQuotaList(aiivhQuotaDTO);
- LocalDateTime now = LocalDateTime.now();
- String finalQuotaType = quotaType;
- myQuota = myQuota.stream().filter(map -> {
- String qType = (String) map.get("quota_type"); // 配额类型 (Anchor|Timbre)
- Integer qStatus = (Integer) map.get("quota_status"); // 配额状态 (1未使用|2使用中|3已使用)
- String expireDateString = (String) map.get("expire_date"); // 过期时间 (对比当前时间)
- LocalDateTime expireDate = LocalDateTime.parse(expireDateString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
- return (finalQuotaType.equals(qType)) && qStatus == 1 && !now.isAfter(expireDate);
- }).sorted(Comparator.comparing(map -> {
- String expireDateString = map.get("expire_date").toString(); // 按过期时间排序 (最早创建在最前面)
- return LocalDateTime.parse(expireDateString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
- })).collect(Collectors.toList());
- if (myQuota.size() == 0) {
- throw new CustException("(" + makeType + ") 配额不足");
- } else {
- // 获得最近临期的那一条配额
- Map<String, Object> targetQuota = myQuota.get(0);
- return targetQuota;
- }
- }
- /**
- * 在上面定制的基础上增加排队机制
- */
- @Transactional
- public Map<String, Object> makeVirtualTaskQueue(TencentCustomserviceDTO tencentCustomserviceDTO) {
- RLock lock = redissonClient.getLock("makeVirtualTask");
- try { lock.tryLock(3, TimeUnit.SECONDS);
- // [Get] 查询我的配额数量一览
- AiivhAssetQuotaStatisticsDTO aiivhAssetQuotaStatisticsDTO = aiivhAssetService.getMyOverview();
- // 判断配额是否足够
- Long quota_balance = null;
- String makeType = tencentCustomserviceDTO.getPayload().getMake_type();
- String quotaType = null;
- String activeType = null, activeTypeDescription = null;
- // [定制视频] 2D小样本-标准版(通用口型)形象定制
- if (makeType.equals("IMAGE_GENERAL")) {
- quota_balance = aiivhAssetQuotaStatisticsDTO.getAnchor_free_quota();
- quotaType = "Anchor";
- activeType = IvhQuotaActiveEvent.MAKE_ANCHOR.getCode();
- activeTypeDescription = IvhQuotaActiveEvent.MAKE_ANCHOR.getDescription();
- }
- // [定制音色] 2D小样本声音定制
- if (makeType.equals("VOICE")) {
- quota_balance = aiivhAssetQuotaStatisticsDTO.getTimbre_free_quota();
- quotaType = "Timbre";
- activeType = IvhQuotaActiveEvent.MAKE_TIMBRE.getCode();
- activeTypeDescription = IvhQuotaActiveEvent.MAKE_TIMBRE.getDescription();
- }
- if (quota_balance <= 0) {
- throw new CustException("(" + makeType + ") 配额不足");
- } else {
- // -- 1.查询我的配额,并获得有效(类型匹配,状态可用,未过期),最近临期的那一条配额 -----------------------------
- Map<String, Object> targetQuota = getEffectiveQuota(quotaType, makeType);
- String quotaCode = (String) targetQuota.get("quota_code");
- // -- 2.修改配额状态: 2使用中 ------------------------------------------------------------------------
- AiivhQuotaDTO aiivhQuotaDTO = new AiivhQuotaDTO();
- aiivhQuotaDTO.setQuota_code(quotaCode);
- aiivhQuotaDTO.setQuota_status(2);
- aiivhQuotaMapper.updateAiivhQuota(aiivhQuotaDTO);
- // -- 3.记录 ai_ivh_quota_history 操作 ------------------------------------------------------------
- List<AiivhQuotaHistoryDTO> list = new ArrayList<>();
- AiivhQuotaHistoryDTO aiivhQuotaHistoryDTO = new AiivhQuotaHistoryDTO();
- aiivhQuotaHistoryDTO.setUser_id(httpRequestAspect.getUserId());
- aiivhQuotaHistoryDTO.setActivity_type(activeType);
- aiivhQuotaHistoryDTO.setActivity_type_description(activeTypeDescription);
- aiivhQuotaHistoryDTO.setQuota_type(quotaType);
- aiivhQuotaHistoryDTO.setQuota_adjustment(-1);
- list.add(aiivhQuotaHistoryDTO);
- aiivhQuotaHistoryMapper.insertAiivhQuotaHistoryBatch(list);
- // 创建定制形象任务 (未提交)
- tencentCustomserviceDTO.setQueue_code(quotaCode);
- return insertVirtualmanTask(tencentCustomserviceDTO);
- }
- } catch (InterruptedException e) { throw new RuntimeException(e);
- } finally { lock.unlock(); }
- }
- /**
- * 发起任务 (填写 腾讯订单、备注,同时发起任务)
- */
- @Transactional
- public Map<String, Object> launchVirtualTaskQueue(VirtualmanLaunchDTO virtualmanLaunchDTO) {
- // 1.获得任务详情
- AiPersonDTO aiPersonDTO = new AiPersonDTO();
- aiPersonDTO.setQuota_code(virtualmanLaunchDTO.getQuota_code());
- Map<String, Object> taskDetail = aiivhMakeVirtualmanTaskService.queryAiivhMakeVirtualmanTaskDetail(aiPersonDTO);
- // 2.发起任务
- TencentCustomserviceDTO tencentCustomserviceDTO = new TencentCustomserviceDTO();
- TencentCustomservicePayloadDTO payloadDTO = new TencentCustomservicePayloadDTO();
- payloadDTO.setAnchor_name((String) taskDetail.get("anchor_name"));
- payloadDTO.setMake_type((String) taskDetail.get("make_type"));
- payloadDTO.setIdentity_cos_url((String) taskDetail.get("identity_cos_url"));
- payloadDTO.setIdentity_written_cos_url((String) taskDetail.get("identity_written_cos_url"));
- payloadDTO.setMaterial_cos_url((String) taskDetail.get("material_cos_url"));
- payloadDTO.setIs_remove_background((Integer) taskDetail.get("is_remove_background"));
- payloadDTO.setSex_type((String) taskDetail.get("sex_type"));
- payloadDTO.setNotes((String) taskDetail.get("notes"));
- payloadDTO.setText_driver((String) taskDetail.get("text_driver"));
- payloadDTO.setVoice_driver_cos_file((String) taskDetail.get("voice_driver_cos_file"));
- tencentCustomserviceDTO.setPayload(payloadDTO);
- System.out.println(tencentCustomserviceDTO);
- Map<String, Object> resp = makeVirtualTask(tencentCustomserviceDTO);
- System.out.println("--------------------------");
- System.out.println(resp);
- Integer respHeaderCode = (Integer) MapUtil.get(resp, "Header.Code");
- if (respHeaderCode != 0) {
- // {Header={RequestID=gz6c6d3da317138514464456410, SessionID=gz6c6d3da317138514464456411, DialogID=, Code=100008, Message=LimitExceeded:超过配额限制: AssetInsufficientError:无可用配额}}
- String message = (String) MapUtil.get(resp, "Header.Message");
- throw new CustException(message);
- } else {
- // 2.更新 任务ID、腾讯订单号、备注
- String task_id = (String) MapUtil.get(resp, "Payload.TaskId");
- aiPersonDTO.setTask_id(task_id);
- aiPersonDTO.setQuota_code(virtualmanLaunchDTO.getQuota_code());
- aiPersonDTO.setTencent_order_code(virtualmanLaunchDTO.getTencent_order_code());
- aiPersonDTO.setLaunch_note(virtualmanLaunchDTO.getLaunch_note());
- return aiivhMakeVirtualmanTaskService.updateAiivhMakeVirtualmanTask(aiPersonDTO);
- }
- }
- /**
- * [腾讯-数智人] 查询形象/音色定制进度
- */
- @Transactional
- public Map<String, Object> getProgressOfVirtualmanTask(String task_id) {
- // -- Http Request --------------------------------------------
- Map<String, Object> signature = sdkTencentService.getSignature(appKey, accessToken); // 获得 Signature 签名
- // System.out.println("signature: " + signature);
- String url = "https://gw.tvs.qq.com/v2/ivh/assetmanager/customservice/getprogress";
- URI uriWithParams = UriComponentsBuilder.fromUriString(url)
- .queryParam("appkey", signature.get("appkey"))
- .queryParam("signature", "{signature}")
- .queryParam("timestamp", signature.get("timestamp"))
- .build(signature.get("signature"));
- String jsonStr = "{\"Payload\": {\"TaskId\": \"" + task_id + "\"}}";
- JSONObject bodyData = new JSONObject(jsonStr);
- // System.out.println("task_id: " + task_id);
- // System.out.println("bodyData: " + bodyData);
- // Http 远程调用
- Map<String, Object> resp = WebClient.create()
- .method(HttpMethod.POST)
- .uri(uriWithParams)
- .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
- .bodyValue(bodyData.toString())
- .retrieve().bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})
- .block();
- // // 临时数据 (模拟成功)
- // Map<String, Object> tempPayload = new LinkedHashMap<>();
- // tempPayload.put("StageInfo", "{\"TrainResult\":[\"url1\",\"url2\"],\"RejectReason\":\"\",\"TrainRecord\":[{\"StartTime\":\"2023-11-01 23:00:17\",\"Record\":[\"url1\",\"url2\"]}]}");
- // tempPayload.put("Status", "MAKING");
- // tempPayload.put("StatusV2", "WAIT_PROCESS");
- // tempPayload.put("FailMessage", "");
- // tempPayload.put("StageV2", "CONFIRM");
- // resp.put("Payload", tempPayload);
- System.out.println("getProgressOfVirtualmanTask:");
- System.out.println(resp);
- // 判断 任务是否查询成功 (是,则更新数据库记录)
- Integer respHeaderCode = (Integer) MapUtil.get(resp, "Header.Code");
- if (respHeaderCode == 0) {
- // 任务失败
- String respPayloadStage = (String) MapUtil.get(resp, "Payload.Stage");
- String respPayloadStageInfo = (String) MapUtil.get(resp, "Payload.StageInfo");
- System.out.println("-- respPayloadStageInfo --------");
- System.out.println(respPayloadStageInfo);
- System.out.println("--------------------------------");
- // if (respPayloadStage.equals("END")) {
- // throw new RuntimeException(respPayloadStageInfo);
- // }
- String respPayloadStatus = (String) MapUtil.get(resp, "Payload.Status");
- // 定制任务完成后,
- // - 失败,记得把状态改为 1未使用
- // - 成功,记得把 quota 状态改为 3已使用
- AiivhQuotaDTO aiivhQuotaDTO = new AiivhQuotaDTO();
- if ("FAIL".equals(respPayloadStatus)) {
- aiivhQuotaDTO.setQuota_status(1);
- }
- if ("SUCCESS".equals(respPayloadStatus)) {
- aiivhQuotaDTO.setQuota_status(3);
- }
- aiivhQuotaMapper.updateAiivhQuota(aiivhQuotaDTO);
- // String respPayloadFailMessage = (String) MapUtil.get(resp, "Payload.FailMessage");
- /**
- * 更新任务
- */
- AiPersonDTO aiPersonDTO = new AiPersonDTO();
- // [查询] 自身 UserId
- Long user_id = httpRequestAspect.getUserId();
- aiPersonDTO.setUser_id(user_id);
- aiPersonDTO.setTask_id(task_id);
- aiPersonDTO.setTask_status(respPayloadStatus);
- aiPersonDTO.setTask_status_info(respPayloadStageInfo);
- aiPersonDTO.setStage_status(respPayloadStage); // 返回值 { Payload } 跟文档不一样,文档是 { StageV2 },实际上是返回 { Stage }
- // 返回值 { StageInfo } 跟文档不一样,文档是:
- // {\"TrainResult\":[\"url1\",\"url2\"],\"RejectReason\":\"\",\"TrainRecord\":[{\"StartTime\":\"2023-11-01 23:00:17\",\"Record\":[\"url1\",\"url2\"]}]}
- // 实际上是:
- // {"TrainResult":["https://videomaker-resources.ivh.qq.com/broadcast/Basic/video/78f7fb6c6fec4311921ede313f3c7cd5.mp4","https://videomaker-resources.ivh.qq.com/broadcast/Basic/video/259044134def40f69fdfdc1cd6c6c952.mp4"],"RejectReason":"","TrainRecord":[{"StartTime":"2024-03-21 18:06:59","Record":["https://videomaker-resources.ivh.qq.com/broadcast/Basic/video/78f7fb6c6fec4311921ede313f3c7cd5.mp4","https://videomaker-resources.ivh.qq.com/broadcast/Basic/video/259044134def40f69fdfdc1cd6c6c952.mp4"]}]}
- if (!respPayloadStageInfo.isEmpty()) {
- JSONObject StageInfoObject = JSONUtil.parseObj(respPayloadStageInfo);
- String result = JSONUtil.toJsonStr(StageInfoObject);
- aiPersonDTO.setResult(result);
- }
- System.out.println("aiPersonDTO:");
- System.out.println(aiPersonDTO);
- // [Post] 根据 Payload 返回的状态来更新
- aiivhMakeVirtualmanTaskService.updateAiivhMakeVirtualmanTask(aiPersonDTO);
- }
- return resp;
- }
- @Transactional
- public List<Map<String, Object>> getQueueOfVirtualmanTask(String task_id) {
- RList<String> rList = redissonClient.getList("makeVirtualTaskQueue");
- List<String> queueList = rList.readAll();
- List<Map<String, Object>> result = new ArrayList<>();
- if (queueList != null && queueList.size() > 0) {
- for (String queue : queueList) {
- result.add(JSONUtil.parseObj(queue));
- }
- }
- return result;
- }
- /**
- * [腾讯-数智人] 确认形象/音色定制效果
- */
- @Transactional
- public Map<String, Object> confirmVirtualmanTask(TencentCustomserviceConfirmDTO tencentCustomserviceConfirmDTO) {
- try {
- TencentCustomserviceConfirmPlayloadDTO payload = (TencentCustomserviceConfirmPlayloadDTO) tencentCustomserviceConfirmDTO.getPayload();
- // 基于实体类,将 anchor_name 转换为 AnchorName (将下划线转为大驼峰)
- Map<String, Object> resultMap = new HashMap<>();
- convertObjectToMap(tencentCustomserviceConfirmDTO, resultMap);
- String bodyData = JSONUtil.toJsonStr(resultMap);
- // -- Http Request --------------------------------------------
- Map<String, Object> signature = sdkTencentService.getSignature(appKey, accessToken); // 获得 Signature 签名
- String url = "https://gw.tvs.qq.com/v2/ivh/assetmanager/customservice/customerconfirm";
- URI uriWithParams = UriComponentsBuilder.fromUriString(url)
- .queryParam("appkey", signature.get("appkey"))
- .queryParam("signature", "{signature}")
- .queryParam("timestamp", signature.get("timestamp"))
- .build(signature.get("signature"));
- // Http 远程调用
- Map<String, Object> resp = WebClient.create()
- .method(HttpMethod.POST)
- .uri(uriWithParams)
- .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
- .bodyValue(bodyData)
- .retrieve().bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
- })
- .block();
- System.out.println(resp);
- // // 临时数据 (模拟成功)
- // Map<String, Object> tempPayload = new LinkedHashMap<>();
- // tempPayload.put("Operate", "AGREE");
- //// tempPayload.put("Operate", "REJECT");
- //// tempPayload.put("Reason", "REJECT 就是 拒绝");
- // resp.put("Payload", tempPayload);
- // 判断 任务是否确认成功 (是,则更新数据库记录)
- Integer respHeaderCode = (Integer) MapUtil.get(resp, "Header.Code");
- if (respHeaderCode == 0) {
- AiPersonDTO aiPersonDTO = new AiPersonDTO();
- // [查询] 自身 UserId
- Long user_id = httpRequestAspect.getUserId();
- aiPersonDTO.setUser_id(user_id);
- aiPersonDTO.setTask_id(payload.getTask_id());
- String Operate = (String) MapUtil.get(resp, "Payload.Operate");
- aiPersonDTO.setConfirm_status(Operate);
- aiPersonDTO.setConfirm_status_info((String) MapUtil.get(resp, "Payload.Reason"));
- /**
- * 更新定制数智人任务
- */
- aiivhMakeVirtualmanTaskService.updateAiivhMakeVirtualmanTask(aiPersonDTO);
- /**
- * 更新形象 (仅更新 stage_status)
- */
- if (Operate == "AGREE") {
- AiivhAnchorDTO aiivhAnchorDTO = new AiivhAnchorDTO();
- //Map<String, Object> detail = aiPersonMapper.queryAiPersonDetail(aiPersonDTO);
- Map<String, Object> detail = aiivhMakeVirtualmanTaskService.queryAiivhMakeVirtualmanTaskDetail(aiPersonDTO);
- aiivhAnchorDTO.setUser_id(user_id);
- aiivhAnchorDTO.setAnchor_name((String) detail.get("anchor_name"));
- aiivhAnchorDTO.setStage_status((String) detail.get("stage_status"));
- System.out.println(aiivhAnchorDTO);
- aiivhMakeVirtualmanTaskService.updateAiPersoneVirtualmanCustom(aiivhAnchorDTO);
- }
- }
- return resp;
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
- // /**
- // * 腾讯-数智人-个人资产管理-分页查询小样本形象列表接口
- // * https://cloud.tencent.com/document/product/1240/93404
- // */
- // @Transactional
- // public Map<String, Object> getCustomVirtualman(Integer pageNum, Integer pageSize) {
- // Map<String, Object> payload = new HashMap<>();
- // payload.put("VirtualmanTypeCode", "small_sample_2d");
- //// String[] anchor_codes = new String[]{"imagetrain_100035906086_3416"};
- //// payload.put("AnchorCodes", anchor_codes);
- // payload.put("PageIndex", pageNum);
- // payload.put("PageSize", pageSize);
- //
- //
- // Map<String, Object> resultMap = Collections.singletonMap("Payload", payload);
- // String bodyData = JSONUtil.toJsonStr(resultMap);
- //
- // // -- Http Request --------------------------------------------
- // /**
- // * 这里使用我自己的空白密钥,因为只有未创建自定义形象的账号,才能返回全部形象
- // */
- // Map<String, Object> signature = sdkTencentService.getSignature(appKey, accessToken); // 获得 Signature 签名
- //
- // String url = "https://gw.tvs.qq.com/v2/ivh/crmserver/customerassetservice/describesmallsampleimage";
- // URI uriWithParams = UriComponentsBuilder.fromUriString(url)
- // .queryParam("appkey", signature.get("appkey"))
- // .queryParam("signature", "{signature}")
- // .queryParam("timestamp", signature.get("timestamp"))
- // .build(signature.get("signature"));
- //
- // // Http 远程调用
- // Map<String, Object> resp = WebClient.create()
- // .method(HttpMethod.POST)
- // .uri(uriWithParams)
- // .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
- // .bodyValue(bodyData.toString())
- // .retrieve().bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
- // })
- // .block();
- //
- // Integer respHeaderCode = (Integer) MapUtil.get(resp, "Header.Code");
- // if (respHeaderCode == 0) {
- // List<Map<String, Object>> virtualmans = (List<Map<String, Object>>) MapUtil.get(resp, "Payload.Virtualmans");
- // Map<String, Object> response = new LinkedHashMap<>();
- // // 遍历 virtualmans 列表,并将 key 由大驼峰改为下划线命名
- // virtualmans = ListUtil.convertToUnderscoreCase(virtualmans);
- //
- //
- // // 分页查询
- // if (pageNum != null && pageSize != null) {
- // PageHelper.startPage(pageNum, pageSize);
- // PageHelper.getLocalPage().setPageSizeZero(true);
- // }
- // PageInfoResult pageInfoResult = new PageInfoResult(virtualmans);
- // return pageInfoResult.toMap();
- // }
- //
- // return resp;
- // }
-
- /**
- * 获得全部形象列表 (循环调用接口,至到获得全部数据)
- * List<Map<String, Object>> virtualmans = getAllVirtualman(pageIndex, pageSize);
- */
- private List<Map<String, Object>> getAllVirtualmanNoEmpty(Integer pageIndex, Integer pageSize) {
- // 初始化变量
- List<Map<String, Object>> timbre_assets = new ArrayList<>();
- // 第一次调用 initTimbre 方法,并将当前页的数据追加到 timbre_assets 列表中
- Map<String, Object> resp = initCustomVirtualman(pageIndex, pageSize);
- Integer total = (Integer) MapUtil.get(resp, "Payload.Total");
- timbre_assets.addAll((List<Map<String, Object>>) MapUtil.get(resp, "Payload.Virtualmans"));
- // 循环获取所有页的数据
- while (total != null && total > 0 && pageIndex * pageSize <= total) {
- // 准备下一次查询,页码加1
- pageIndex++;
- System.out.println("pageIndex: " + pageIndex);
- // 再次调用 initTimbre 方法获取下一页的数据,并将当前页的数据追加到 timbre_assets 列表中
- resp = initCustomVirtualman(pageIndex, pageSize);
- total = (Integer) MapUtil.get(resp, "Payload.Total");
- timbre_assets.addAll((List<Map<String, Object>>) MapUtil.get(resp, "Payload.Virtualmans"));
- }
- return timbre_assets;
- }
- /**
- * [内部服务] 获得形象详细信息 (通过音色名称)
- */
- @Transactional
- public Map<String, Object> getVirtualmanObject(String anchor_name) {
- // 循环获得数据列表,直到 total 小于 pageSize
- List<Map<String, Object>> virtualmans = getAllVirtualmanNoEmpty(1, 100);
- // 遍历 virtualmans 列表,并将 key 由大驼峰改为下划线命名
- virtualmans = ListUtil.convertToUnderscoreCase(virtualmans);
- // 遍历 匹配 anchor_name
- Map<String, Object> result = new LinkedHashMap<>();
- for (Map<String, Object> virtualman : virtualmans) {
- String virtualman_anchor_name = (String) virtualman.get("anchor_name");
- // System.out.println("virtualman_anchor_name: " + virtualman_anchor_name + ", anchor_name: " + anchor_name);
- if (virtualman_anchor_name.equals(anchor_name)) {
- result = virtualman;
- System.out.println(virtualman);
- }
- }
- return result;
- }
- }
|