diff --git a/suimangCApi/src/main/java/com/iformall/controller/UserLiveController.java b/suimangCApi/src/main/java/com/iformall/controller/UserLiveController.java index c755188..f2d5ce4 100644 --- a/suimangCApi/src/main/java/com/iformall/controller/UserLiveController.java +++ b/suimangCApi/src/main/java/com/iformall/controller/UserLiveController.java @@ -2,18 +2,29 @@ package com.iformall.controller; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.google.code.kaptcha.Producer; import com.iformall.annotation.AuthIgnore; import com.iformall.common.ErrorCode; import com.iformall.common.ResultData; import com.iformall.domain.po.WxCUserBasicInfo; +import com.iformall.domain.po.WxCVideoTable; +import com.iformall.domain.po.sm.PhotoSpeakVideo; +import com.iformall.domain.po.sm.PreviewParam; +import com.iformall.domain.po.sm.VoiceInfo; import com.iformall.domain.vo.WxCLiveLoginVo; +import com.iformall.enums.EnumVideoStatus; +import com.iformall.exception.MallinkException; import com.iformall.service.*; +import com.iformall.service.sm.VoiceInfoService; +import com.iformall.sm.AiPreviewParam; import com.iformall.utils.Constant; import com.iformall.utils.PasswordHelper; import com.iformall.utils.RedisCacheUtils; import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; +import lombok.SneakyThrows; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -26,9 +37,16 @@ import springfox.documentation.spring.web.json.Json; import javax.imageio.ImageIO; import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; +import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.*; @RestController @@ -59,6 +77,8 @@ public class UserLiveController extends BaseController { @Autowired private WxCUserAuthorityService wxCUserAuthorityService; + @Autowired + private VoiceInfoService voiceInfoService; @AuthIgnore @@ -251,4 +271,115 @@ public class UserLiveController extends BaseController { return wxCUserAuthorityService.getAuthor(id, code, type, resourceId); } + + + @AuthIgnore + @ApiOperation(value = "tts", notes = "{\"username\",\"string\",\"gen_txt\",\"string\",\"voice_id\",\"string\",\"voice_style\",\"string\",\"speed\",\"int\"}") + @PostMapping("/audiotts") + public Map voicePreview(@RequestBody Map params) { + logger.debug("[" + getIpAddr() + "] UserLiveController::voicePreview"); + + String phone = params.get("username"); + WxCUserBasicInfo infoByPhone = wxCUserBasicInfoService.findInfoByPhone(getTenantInfo(), phone); + Long id = infoByPhone.getId(); + AiPreviewParam param = new AiPreviewParam(); + if (params.get("voice_id") == null) { + Map status = new HashMap<>(); + status.put("code",ErrorCode.SYS_SERVER_ERROR.getCode()); + status.put("msg","音色ID不能为空"); + return status; + // return new ResultData(ErrorCode.SYS_SERVER_ERROR.getCode(), "音色ID不能为空"); + } + if (StringUtils.isBlank(params.get("gen_txt"))) { + Map status = new HashMap<>(); + status.put("code",ErrorCode.SYS_SERVER_ERROR.getCode()); + status.put("msg","需要生成的文字不能为空"); + return status; + //return new ResultData(ErrorCode.SYS_SERVER_ERROR.getCode(), "需要生成的文字不能为空"); + }if (Integer.parseInt(params.get("speed"))==-1){ + param.setSpeed(0); + } + param.setSpeed(Integer.parseInt(params.get("speed"))); + param.setVoice_id(params.get("voice_id")); + param.setVoice_style(params.get("voice_style")); + param.setGen_txt(params.get("gen_txt")); + Map resultMap = wxCVoiceService.voicePreview(param); + Map info = new HashMap<>(); + info.put("log_id",id); + info.put("server_type","audio tts"); + resultMap.put("info",info); + + return resultMap; + } + + + @AuthIgnore + @SneakyThrows + @ApiOperation(value = "tts", notes = "{\"username\",\"string\",\"gen_txt\",\"string\",\"voice_id\",\"string\",\"voice_style\",\"string\",\"speed\",\"int\"}") + @GetMapping("exportVideo") + public void exportVideo(@RequestBody Map params , HttpServletRequest request, HttpServletResponse response) { + logger.debug("[" + getIpAddr() + "] UserLiveController::exportVideo"); + + response.reset(); + + File tmpFile = null; + OutputStream outputStream = null; + WxCUserBasicInfo infoByPhone = wxCUserBasicInfoService.findInfoByPhone(getTenantInfo(), params.get("username")); + Long id = infoByPhone.getId(); + try { + outputStream = response.getOutputStream(); + } catch (IOException e) { + throw new MallinkException(ErrorCode.SYS_SERVER_ERROR); + } + + try{ + if(id == null){ + throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + WxCVideoTable videoTable = wxCVideoService.selectOne(id,Long.parseLong(params.get("resource_id"))); + + + + //获取响应的输出流 + InputStream inputStream = new URL(videoTable.getDemo()).openStream(); + + + response.setHeader("Content-Disposition", "attachment; filename=" + + URLEncoder.encode(videoTable.getId()+".mp4", "UTF-8")); + //解决编码问题 + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-Type","application/octet-stream"); + + byte[] cache = new byte[1024 * 300]; + int flag; + while ((flag = inputStream.read(cache))!=-1){ + outputStream.write(cache, 0, flag); + } +// } + + }catch(MallinkException e){ + ResultData resultData = new ResultData(e.getErrorCode(), e.getMessage()); + //解决编码问题 + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-Type","application/json"); + outputStream.write(JSONObject.toJSONString(resultData).getBytes(StandardCharsets.UTF_8)); + + }finally { + if (tmpFile != null) { + tmpFile.delete(); + } + outputStream.flush(); + outputStream.close(); + } + } + @AuthIgnore + @ApiOperation("选择声音选择风格") + @GetMapping("/chooseType") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + public ResultData chooseType(Long id) { + logger.debug("[" + getIpAddr() + "] MouldPatchController::chooseType"); + List voiceInfos = wxCVoiceService.chooseType(id); + System.out.println("voiceInfos = " + voiceInfos); + return new ResultData(wxCVoiceService.chooseType(id)); + } } diff --git a/suimangService/src/main/java/com/iformall/domain/po/WxCVoiceTable.java b/suimangService/src/main/java/com/iformall/domain/po/WxCVoiceTable.java index bca83b8..ef77eb6 100644 --- a/suimangService/src/main/java/com/iformall/domain/po/WxCVoiceTable.java +++ b/suimangService/src/main/java/com/iformall/domain/po/WxCVoiceTable.java @@ -5,7 +5,10 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.ToString; -@TableName(value = "wx_c_voice") +import java.util.ArrayList; +import java.util.List; + +@TableName(value = "voice_info") @Data @ToString(callSuper = true) public class WxCVoiceTable { @@ -23,17 +26,25 @@ public class WxCVoiceTable { @io.swagger.annotations.ApiModelProperty(value = "地区显示名称", name = "local_display_name") private String localDisPlayName; - @io.swagger.annotations.ApiModelProperty(value = "声纹ID", name = "voice_id") + @io.swagger.annotations.ApiModelProperty(value = "声纹ID", name = "id") private int voiceId; - @io.swagger.annotations.ApiModelProperty(value = "声纹名称(用于调微软接口)", name = "voice_name") + @io.swagger.annotations.ApiModelProperty(value = "声纹名称(用于调微软接口)", name = "local_name") private String voiceName; - @io.swagger.annotations.ApiModelProperty(value = "声纹展示名称", name = "voice_display_name") + @io.swagger.annotations.ApiModelProperty(value = "声纹展示名称", name = "display_name") private String voiceDisplayName; - @io.swagger.annotations.ApiModelProperty(value = "性别(男1 女0)", name = "gender") + @io.swagger.annotations.ApiModelProperty(value = "性别(男1 女0)", name = "sex") private int gender; @io.swagger.annotations.ApiModelProperty(value = "声纹类型 共享:0 定制:1", name = "class") private int voiceType; + @io.swagger.annotations.ApiModelProperty(value = "声纹列表", name = "mould_sm_id") + private String MouldSmId; + + @io.swagger.annotations.ApiModelProperty(value = "声纹列表", name = "style_list") + private String styleList ; + + + @io.swagger.annotations.ApiModelProperty(value = "声纹风格名称(用于微软接口)", name = "style_name") private String styleName; @io.swagger.annotations.ApiModelProperty(value = "声纹风格展示名称", name = "style_display_name") diff --git a/suimangService/src/main/java/com/iformall/domain/po/sm/PreviewParam.java b/suimangService/src/main/java/com/iformall/domain/po/sm/PreviewParam.java index 6dfd06b..c735934 100644 --- a/suimangService/src/main/java/com/iformall/domain/po/sm/PreviewParam.java +++ b/suimangService/src/main/java/com/iformall/domain/po/sm/PreviewParam.java @@ -8,4 +8,6 @@ public class PreviewParam { private String voiceId; private String voiceStyle; private String gender; -} \ No newline at end of file + private int speed; + +} diff --git a/suimangService/src/main/java/com/iformall/mapper/WxCVideoMapper.java b/suimangService/src/main/java/com/iformall/mapper/WxCVideoMapper.java index 9e111ed..bf39d90 100644 --- a/suimangService/src/main/java/com/iformall/mapper/WxCVideoMapper.java +++ b/suimangService/src/main/java/com/iformall/mapper/WxCVideoMapper.java @@ -12,5 +12,5 @@ public interface WxCVideoMapper extends CommonMapper { List getById(Long id); - + WxCVideoTable selectOne(Long id, long resource_id); } diff --git a/suimangService/src/main/java/com/iformall/service/WxCVideoService.java b/suimangService/src/main/java/com/iformall/service/WxCVideoService.java index 041d20f..3e4a6d2 100644 --- a/suimangService/src/main/java/com/iformall/service/WxCVideoService.java +++ b/suimangService/src/main/java/com/iformall/service/WxCVideoService.java @@ -9,4 +9,6 @@ public interface WxCVideoService { Map getById(Long id); + + WxCVideoTable selectOne(Long id, long resource_id); } diff --git a/suimangService/src/main/java/com/iformall/service/WxCVoiceService.java b/suimangService/src/main/java/com/iformall/service/WxCVoiceService.java index db9e69e..042e303 100644 --- a/suimangService/src/main/java/com/iformall/service/WxCVoiceService.java +++ b/suimangService/src/main/java/com/iformall/service/WxCVoiceService.java @@ -1,9 +1,16 @@ package com.iformall.service; import com.iformall.common.ResultData; +import com.iformall.domain.po.sm.VoiceInfo; +import com.iformall.sm.AiPreviewParam; +import java.util.List; import java.util.Map; public interface WxCVoiceService { Map getById(Long id); + + List chooseType(Long id); + + Map voicePreview(AiPreviewParam aiPreviewParam); } diff --git a/suimangService/src/main/java/com/iformall/service/impl/WxCVideoServiceImpl.java b/suimangService/src/main/java/com/iformall/service/impl/WxCVideoServiceImpl.java index 1521716..e66ced3 100644 --- a/suimangService/src/main/java/com/iformall/service/impl/WxCVideoServiceImpl.java +++ b/suimangService/src/main/java/com/iformall/service/impl/WxCVideoServiceImpl.java @@ -71,6 +71,12 @@ public class WxCVideoServiceImpl implements WxCVideoService,IExcelExportServer { return avatarVos; } + @Override + public WxCVideoTable selectOne(Long id, long resource_id) { + + return wxCVideoMapper.selectOne(id,resource_id); + } + @Override public List selectListForExcelExport(Object queryParams, int page) { WxCUserBasicInfo basicInfo = (WxCUserBasicInfo) queryParams; diff --git a/suimangService/src/main/java/com/iformall/service/impl/WxCVoiceServiceImpl.java b/suimangService/src/main/java/com/iformall/service/impl/WxCVoiceServiceImpl.java index bb20f1c..057a461 100644 --- a/suimangService/src/main/java/com/iformall/service/impl/WxCVoiceServiceImpl.java +++ b/suimangService/src/main/java/com/iformall/service/impl/WxCVoiceServiceImpl.java @@ -1,12 +1,26 @@ package com.iformall.service.impl; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.google.common.collect.Lists; +import com.iformall.common.ErrorCode; import com.iformall.common.ResultData; import com.iformall.domain.po.WxCVideoTable; import com.iformall.domain.po.WxCVoiceTable; +import com.iformall.domain.po.sm.VoiceInfo; +import com.iformall.domain.vo.VoiceInfoVo; +import com.iformall.enums.EnumClassType; +import com.iformall.enums.EnumSpeakType; +import com.iformall.mapper.VoiceMapper; import com.iformall.mapper.WxCVoiceMapper; import com.iformall.service.WxCVoiceService; +import com.iformall.sm.AiPreviewParam; +import com.iformall.sm.AiPreviewResult; +import com.iformall.sm.AiVideoHelper; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; import java.util.*; @@ -16,6 +30,13 @@ public class WxCVoiceServiceImpl implements WxCVoiceService { @Autowired WxCVoiceMapper wxCVoiceMapper; + @Autowired + VoiceMapper voiceMapper; + + private final static String str = "\uD83D\uDD57"; + private final static String url = "https://suimang.oss-accelerate.aliyuncs.com/builtin/tts_all_sample/"; + private final static String end = ".wav"; + @Override public Map getById(Long id) { @@ -28,7 +49,7 @@ public class WxCVoiceServiceImpl implements WxCVoiceService { for (WxCVoiceTable wxCVoiceTable : resultList) { HashMap audio = new HashMap<>(); HashMap voice = new HashMap<>(); - HashMap style = new HashMap<>(); + data.put("username", wxCVoiceTable.getUserName()); data.put("current_time", new Date(System.currentTimeMillis())); audioList.add(audio); @@ -43,17 +64,42 @@ public class WxCVoiceServiceImpl implements WxCVoiceService { voice.put("voiceid", wxCVoiceTable.getVoiceId()); voice.put("expire_time", wxCVoiceTable.getExpireTime()); voice.put("voicename", wxCVoiceTable.getVoiceName()); - voice.put("voicetype", wxCVoiceTable.getVoiceType()); + voice.put("voicetype", EnumClassType.SHARE.getCode()); voice.put("displayname", wxCVoiceTable.getVoiceDisplayName()); voice.put("gender", wxCVoiceTable.getGender()); List styleList = new ArrayList(); - styleList.add(style); + + + List strings = JSON.parseArray(wxCVoiceTable.getStyleList(), String.class); + for (String y : strings) { + // List list = new ArrayList<>(); + HashMap style = new HashMap<>(); + style.put("stylename", y); + style.put("displayname", EnumSpeakType.getEnum(y).getMessage()); + style.put("styledemo", url + wxCVoiceTable.getMouldSmId() + "_" + y + end); + //list.add(style); + styleList.add(style); + } + + + +// for (String s : Arrays.asList(wxCVoiceTable.getStyleList())) { +//// VoiceInfoVo infoVo = new VoiceInfoVo(); +//// infoVo.setName(EnumSpeakType.getEnum(s).getMessage()); +//// infoVo.setEngName(s); +//// infoVo.setUrl(url + wxCVoiceTable.getMouldSmId() + "_" + s + end); +// style.put("stylename", s); +// style.put("displayname", EnumSpeakType.getEnum(s).getMessage()); +// style.put("styledemo", url + wxCVoiceTable.getMouldSmId() + "_" + s + end); +// styleList.add(style); +// } + // styleList.add(style); voice.put("styleList", styleList); - style.put("stylename", wxCVoiceTable.getStyleName()); - style.put("displayname", wxCVoiceTable.getStyleDisplayName()); - style.put("styledemo", wxCVoiceTable.getStyleDemo()); +// style.put("stylename", wxCVoiceTable.getStyleName()); +// style.put("displayname", wxCVoiceTable.getStyleDisplayName()); +// style.put("styledemo", wxCVoiceTable.getStyleDemo()); } @@ -71,4 +117,75 @@ public class WxCVoiceServiceImpl implements WxCVoiceService { result.put("status",status); return result; } + + @Override + public Map voicePreview(AiPreviewParam aiPreviewParam) { + VoiceInfo voiceInfo = voiceMapper.selectOne(new LambdaQueryWrapper().eq(VoiceInfo::getIsDel, 0).eq(VoiceInfo::getId, aiPreviewParam.getVoice_id())); + if (ObjectUtils.isEmpty(voiceInfo)){ + Map status = new HashMap<>(); + status.put("code",ErrorCode.SYS_SERVER_ERROR.getCode()); + status.put("msg","声音信息不存在"); + return status; + // return new ResultData(ErrorCode.SYS_SERVER_ERROR.getCode(), "声音信息不存在"); + } + AiPreviewParam param = new AiPreviewParam(); + param.setGen_txt(aiPreviewParam.getGen_txt().replaceAll(str,"[*]")); + param.setVoice_id(voiceInfo.getMouldSmId()); + param.setVoice_style(StringUtils.isBlank(aiPreviewParam.getVoice_style()) ? EnumSpeakType.default_0.getMessage() : aiPreviewParam.getVoice_style()); + param.setGender(voiceInfo.getSex() == 1 ? "male" : "female"); + AiPreviewResult result = AiVideoHelper.voicePreview(param); +// if (result.isSuccess()){ +// Map status = new HashMap<>(); +// status.put("data",new ResultData(result.getTime())); +// +// return status; +// //return new ResultData(result.getTime()); +// } + Map resultMap = new HashMap<>(); + Map data = new HashMap<>(); + data.put("ttsurl",result.getUrl()); + + Map status = new HashMap<>(); + status.put("code",1000); + status.put("msg","success"); + resultMap.put("data",data); + resultMap.put("status",status); + return resultMap; + //return new ResultData(result.getCode(), result.getMsgInfo(result.getCode(),result.getMsg())); + } + + @Override + public List chooseType(Long id) { + List voiceInfos = voiceMapper.selectList( + new LambdaQueryWrapper().eq(VoiceInfo::getLanguageId, id).orderByAsc(VoiceInfo::getAgeType).orderByAsc(VoiceInfo::getDisplayName)); + voiceInfos.forEach(x -> { + if (StringUtils.isNotEmpty(x.getStyleList())) { + List strings = JSON.parseArray(x.getStyleList(), String.class); + List list = new ArrayList<>(); + strings.forEach(y->{ + VoiceInfoVo infoVo = new VoiceInfoVo(); + infoVo.setName(EnumSpeakType.getEnum(y).getMessage()); + infoVo.setEngName(y); + infoVo.setUrl(url + x.getMouldSmId() + "_" + y + end); + list.add(infoVo); + }); + + VoiceInfoVo infoVo = new VoiceInfoVo(); + infoVo.setName(EnumSpeakType.getEnum(0).getMessage()); + infoVo.setUrl(url + x.getMouldSmId() + "_" + "default" + end); + infoVo.setEngName("default"); + list.add(infoVo); + x.setStyle(list); + } else { + List list = Lists.newArrayList(); + VoiceInfoVo infoVo = new VoiceInfoVo(); + infoVo.setName(EnumSpeakType.getEnum(0).getMessage()); + infoVo.setEngName("default"); + infoVo.setUrl(url + x.getMouldSmId() + "_" + "default" + end); + list.add(infoVo); + x.setStyle(list); + } + }); + return voiceInfos; +} } diff --git a/suimangService/src/main/java/com/iformall/sm/AiPreviewParam.java b/suimangService/src/main/java/com/iformall/sm/AiPreviewParam.java index 29f11d6..dbaf272 100644 --- a/suimangService/src/main/java/com/iformall/sm/AiPreviewParam.java +++ b/suimangService/src/main/java/com/iformall/sm/AiPreviewParam.java @@ -8,5 +8,6 @@ public class AiPreviewParam { private String voice_id; private String voice_style; private String gender; + private int speed; } diff --git a/suimangService/src/main/resources/mapper/WxCVideoMapper.xml b/suimangService/src/main/resources/mapper/WxCVideoMapper.xml index 36298f1..bce9dd4 100644 --- a/suimangService/src/main/resources/mapper/WxCVideoMapper.xml +++ b/suimangService/src/main/resources/mapper/WxCVideoMapper.xml @@ -26,6 +26,12 @@ left join wx_c_avatar wcav on wcav.id =wca.resource_id where wca.resource_id in (select wca.resource_id from wx_c_author wca WHERE wca.user_id =#{id} AND wca.type = 0 ) + diff --git a/suimangService/src/main/resources/mapper/WxCVoiceMapper.xml b/suimangService/src/main/resources/mapper/WxCVoiceMapper.xml index 6f2827b..89e9e6e 100644 --- a/suimangService/src/main/resources/mapper/WxCVoiceMapper.xml +++ b/suimangService/src/main/resources/mapper/WxCVoiceMapper.xml @@ -5,13 +5,18 @@ - - - + + + - - - + + + + + + + + @@ -19,13 +24,21 @@ + + + + + + + +