From e1922bbc2cc23a61759f996086ecc3d564bfcb35 Mon Sep 17 00:00:00 2001 From: xhxu Date: Fri, 14 Apr 2023 20:41:03 +0800 Subject: [PATCH] //bug --- .../com/iformall/enums/EnumVideoType.java | 17 ++- .../sm/impl/UserMouldVideoServiceImpl.java | 95 ++++++++++++--- .../java/com/iformall/sm/AiVideoHelper.java | 51 +++++--- .../java/com/iformall/sm/AiVideoParam.java | 59 ++++++++++ .../java/com/iformall/utils/Base64Util.java | 85 +++++++++++++- .../java/com/iformall/utils/HttpUtil.java | 109 +++++++++--------- 6 files changed, 329 insertions(+), 87 deletions(-) create mode 100644 suimangService/src/main/java/com/iformall/sm/AiVideoParam.java diff --git a/suimangService/src/main/java/com/iformall/enums/EnumVideoType.java b/suimangService/src/main/java/com/iformall/enums/EnumVideoType.java index 990471d..6e74c3b 100644 --- a/suimangService/src/main/java/com/iformall/enums/EnumVideoType.java +++ b/suimangService/src/main/java/com/iformall/enums/EnumVideoType.java @@ -11,8 +11,8 @@ public enum EnumVideoType { // 1:竖版 // 2:横版 - VERTICAL_PLATE(1, "竖版"), - HORIZONTAL_PLATE(2, "横版"), + VERTICAL_PLATE(1, "竖版", "vertical"), + HORIZONTAL_PLATE(2, "横版", "horizontal"), ; public static EnumVideoType getEnum(Integer code) { @@ -34,10 +34,21 @@ public enum EnumVideoType { private Integer code; private String message; + private String type; - EnumVideoType(Integer code, String message) { + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + EnumVideoType(Integer code, String message, String type) { this.code = code; this.message = message; + this.type = type; } public Integer getCode() { diff --git a/suimangService/src/main/java/com/iformall/service/sm/impl/UserMouldVideoServiceImpl.java b/suimangService/src/main/java/com/iformall/service/sm/impl/UserMouldVideoServiceImpl.java index a4ef8d5..b10677a 100644 --- a/suimangService/src/main/java/com/iformall/service/sm/impl/UserMouldVideoServiceImpl.java +++ b/suimangService/src/main/java/com/iformall/service/sm/impl/UserMouldVideoServiceImpl.java @@ -11,17 +11,16 @@ import com.iformall.domain.po.sm.MaterialMould; import com.iformall.domain.po.sm.PersonMould; import com.iformall.domain.po.sm.UserMouldVideo; import com.iformall.domain.po.sm.VoiceMould; -import com.iformall.enums.EnumMouldPatchType; -import com.iformall.enums.EnumVideoStatus; -import com.iformall.enums.EnumVideoType; -import com.iformall.enums.EnumVoiceType; +import com.iformall.enums.*; import com.iformall.mapper.UserMouldVideoMapper; import com.iformall.service.sm.MaterialMouldService; import com.iformall.service.sm.PersonMouldService; import com.iformall.service.sm.UserMouldVideoService; import com.iformall.service.sm.VoiceMouldService; import com.iformall.sm.AiVideoHelper; +import com.iformall.sm.AiVideoParam; import com.iformall.sm.AiVideoResult; +import com.iformall.utils.Base64Util; import com.iformall.video.VideoFactory; import com.iformall.video.entity.VideUploadResult; import org.apache.commons.lang3.StringUtils; @@ -106,8 +105,19 @@ public class UserMouldVideoServiceImpl implements UserMouldVideoService { JSONObject personObject = JSONObject.parseObject(record.getPersonJson()); if(personObject != null && !personObject.isEmpty()){ isPerson = true; + Long id = personObject.getLong("id"); + Integer type = personObject.getInteger("type"); + String material = personObject.getString("material"); + int x = personObject.getIntValue("x"); + int y = personObject.getIntValue("y"); + int z = personObject.getIntValue("z"); + float w = personObject.getFloatValue("w"); + float h = personObject.getFloatValue("h"); } - }catch(Exception e){} + }catch(Exception e){ + e.printStackTrace(); + return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(),"数字人层级数据错误"); + } //给数字人默认属性 if(!isPerson){ JSONObject personObject = new JSONObject(); @@ -126,8 +136,8 @@ public class UserMouldVideoServiceImpl implements UserMouldVideoService { personObject.put("y",y); } personObject.put("z",0); - personObject.put("w","1");//比例系数(2位小数) - personObject.put("h","1");//比例系数(2位小数) + personObject.put("w",1.0f);//比例系数(2位小数) + personObject.put("h",1.0f);//比例系数(2位小数) record.setPersonJson(personObject.toJSONString()); } //默认背景 @@ -196,11 +206,11 @@ public class UserMouldVideoServiceImpl implements UserMouldVideoService { materialIds.add(id); } String material = jsonObject.getString("material"); - Integer x = jsonObject.getInteger("x"); - Integer y = jsonObject.getInteger("y"); - Integer z = jsonObject.getInteger("z"); - String w = jsonObject.getString("w"); - String h = jsonObject.getString("h"); + int x = jsonObject.getIntValue("x"); + int y = jsonObject.getIntValue("y"); + int z = jsonObject.getIntValue("z"); + float w = jsonObject.getFloatValue("w"); + float h = jsonObject.getFloatValue("h"); } } record.setMaterialIds(JSONArray.toJSONString(materialIds)); @@ -258,12 +268,21 @@ public class UserMouldVideoServiceImpl implements UserMouldVideoService { } String voiceMouldSmId = null; + String voiceType = "default";//默认 if(mouldVideo.getVoiceMouldId() == null){ msg = "未选择声音模板"; }else{ try{ JSONObject personMouldObject = JSONObject.parseObject(mouldVideo.getVoiceMouldSm()); voiceMouldSmId = personMouldObject.getString("mouldSmId"); + Integer speakType = personMouldObject.getInteger("speakType"); + Integer personType = personMouldObject.getInteger("personType"); + if(speakType != null && speakType > 0){ + voiceType = EnumSpeakType.getEnum(speakType).getMessage(); + }else if(personType != null && personType > 0){ + voiceType = EnumPersonType.getEnum(personType).getMessage(); + } + }catch(Exception e){} if(StringUtils.isBlank(voiceMouldSmId)){ msg = "参数错误,未找到声音模板数据"; @@ -284,8 +303,58 @@ public class UserMouldVideoServiceImpl implements UserMouldVideoService { return new AsyncResult<>(0); } + Long backgroundId = mouldVideo.getBackgroundId(); + if(backgroundId == null){ + videoUpd.setVideoStatus(EnumVideoStatus.fail.getCode()); + videoUpd.setVideoMsg("未选择背景"); + this.saveOrUpdate(videoUpd); + return new AsyncResult<>(0); + } + try{ - AiVideoResult video = AiVideoHelper.createVideo(personMouldSmId, voiceMouldSmId, paperwork); + AiVideoParam videoParam = new AiVideoParam(); + videoParam.setGen_txt(paperwork); + videoParam.setVideo_template_id(personMouldSmId); + videoParam.setVoice_id(voiceMouldSmId); + videoParam.setVoice_style(voiceType); + AiVideoParam.VideoFiles videoFiles = new AiVideoParam.VideoFiles(); + AiVideoParam.BackGround backGround = new AiVideoParam.BackGround(); + backGround.setType(EnumVideoType.getEnum(mouldVideo.getVideoType()).getType()); + JSONObject backgroundObject = JSONObject.parseObject(mouldVideo.getBackgroundSm()); + backGround.setImage(Base64Util.imageUrlToBase64(backgroundObject.getString("material"))); + videoFiles.setBack_ground(backGround); + AiVideoParam.Material digitalHuman = new AiVideoParam.Material(); + JSONObject personObject = JSONObject.parseObject(mouldVideo.getPersonJson()); + int[] digitalHumanCoord = new int[]{personObject.getIntValue("x"),personObject.getIntValue("y")}; + digitalHuman.setCoord(digitalHumanCoord); + digitalHuman.setLevel(personObject.getIntValue("z")); + digitalHuman.setRatio(personObject.getFloatValue("w")); + videoFiles.setDigital_human(digitalHuman); + + if(StringUtils.isNotBlank(mouldVideo.getMaterialAllJson())){ + JSONArray materialAllArray = JSONArray.parseArray(mouldVideo.getMaterialAllJson()); + if(materialAllArray != null && !materialAllArray.isEmpty()){ + List materialList = new ArrayList<>(); + for(int i = 0;i < materialAllArray.size();i++) { + JSONObject materialObject = materialAllArray.getJSONObject(i); + if(EnumMouldPatchType.material_mould.getCode().equals(materialObject.getInteger("type"))){ + AiVideoParam.Material material = new AiVideoParam.Material(); + int[] materialCoord = new int[]{materialObject.getIntValue("x"),materialObject.getIntValue("y")}; + material.setCoord(materialCoord); + material.setImage(Base64Util.imageUrlToBase64(materialObject.getString("material"))); + material.setLevel(materialObject.getIntValue("z")); + material.setRatio(materialObject.getFloatValue("w")); + materialList.add(material); + } + } + if(materialList.size() > 0){ + videoFiles.setMaterial(materialList); + } + } + } + videoParam.setVideo_files(videoFiles); + + AiVideoResult video = AiVideoHelper.createVideo(videoParam); if(video.isSuccess()){ videoUpd.setVideoPath(video.getUrl()); videoUpd.setVideoTime(video.getDuration()+""); diff --git a/suimangService/src/main/java/com/iformall/sm/AiVideoHelper.java b/suimangService/src/main/java/com/iformall/sm/AiVideoHelper.java index 0d13298..a3850fa 100644 --- a/suimangService/src/main/java/com/iformall/sm/AiVideoHelper.java +++ b/suimangService/src/main/java/com/iformall/sm/AiVideoHelper.java @@ -1,6 +1,7 @@ package com.iformall.sm; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.iformall.common.ErrorCode; import com.iformall.douyin.pay.orderQuery.OrderQueryResult; @@ -8,8 +9,11 @@ import com.iformall.douyin.pay.orderQuery.QueryMerchantResult; import com.iformall.douyin.pay.orderQuery.QueryRefundResult; import com.iformall.douyin.pay.orderQuery.QuerySettleResult; import com.iformall.douyin.pay.preOrder.*; +import com.iformall.enums.EnumMouldPatchType; import com.iformall.enums.EnumPayStatus; +import com.iformall.enums.EnumVideoType; import com.iformall.exception.MallinkException; +import com.iformall.utils.Base64Util; import com.iformall.utils.HttpUtil; import com.iformall.utils.sign.SignUtils; import lombok.extern.slf4j.Slf4j; @@ -25,21 +29,15 @@ public class AiVideoHelper { public static String uri = "http://222.128.9.132:22266"; - public static String doPost(String url, Map params) { - return HttpUtil.doPost(url,params); + public static String doPost(String url, String params) { + return HttpUtil.doAiVideoPost(url,params); } - public static AiVideoResult createVideo(String video_template_id,String voice_id,String gen_txt) { - Map params = new HashMap<>(); - params.put("video_template_id",video_template_id); - if(StringUtils.isBlank(voice_id)){ - voice_id = "default"; - } - params.put("voice_id",voice_id); - params.put("gen_txt",gen_txt); - log.info("生成视频start request:" + JSONObject.toJSONString(params)); - String response = doPost(uri+"/gen_dh_video", params); + public static AiVideoResult createVideo(AiVideoParam videoParam) { + + log.info("生成视频start request:" + JSONObject.toJSONString(videoParam)); + String response = doPost(uri+"/gen_dh_video", JSONObject.toJSONString(videoParam)); log.info("生成视频end response:"+response); AiVideoResult result = new AiVideoResult(); @@ -50,12 +48,16 @@ public class AiVideoHelper { return result; } - JSONObject jsonObject = JSON.parseObject(response); JSONObject status = jsonObject.getJSONObject("status"); Integer code = status.getInteger("code"); + if(code == null){ + result.setSuccess(false); + result.setMsg("请求生成视频异常,请稍后重试"); + return result; + } - if(null != code && code.intValue() == 1000){ + if(code.intValue() == 1000){ JSONObject data = jsonObject.getJSONObject("data"); JSONObject video = data.getJSONObject("video"); result.setSuccess(true); @@ -93,8 +95,25 @@ public class AiVideoHelper { } public static void main(String[] args) { - createVideo("16739389169485046_nVi875Ej","default", - "恭喜发财"); + AiVideoParam videoParam = new AiVideoParam(); + videoParam.setGen_txt("我写了一篇小说,你帮我看看。"); + videoParam.setVideo_template_id("16776650495633934_PgNAW8Sm"); + videoParam.setVoice_id("zh-CN-XiaohanNeural"); + videoParam.setVoice_style("default"); + AiVideoParam.VideoFiles videoFiles = new AiVideoParam.VideoFiles(); + AiVideoParam.BackGround backGround = new AiVideoParam.BackGround(); + backGround.setType("vertical"); + backGround.setImage(Base64Util.imageUrlToBase64("https://suimang.oss-accelerate.aliyuncs.com/builtin/background/grace/1080.jpg")); + videoFiles.setBack_ground(backGround); + AiVideoParam.Material digitalHuman = new AiVideoParam.Material(); + int[] digitalHumanCoord = new int[]{0,0}; + digitalHuman.setCoord(digitalHumanCoord); + digitalHuman.setLevel(0); + digitalHuman.setRatio(1.0f); + videoFiles.setDigital_human(digitalHuman); + videoParam.setVideo_files(videoFiles); + + AiVideoResult video = AiVideoHelper.createVideo(videoParam); } } diff --git a/suimangService/src/main/java/com/iformall/sm/AiVideoParam.java b/suimangService/src/main/java/com/iformall/sm/AiVideoParam.java new file mode 100644 index 0000000..226b546 --- /dev/null +++ b/suimangService/src/main/java/com/iformall/sm/AiVideoParam.java @@ -0,0 +1,59 @@ +package com.iformall.sm; + +import lombok.Data; + +import java.util.List; + +@Data +public class AiVideoParam { + /** + * | 参数 | 必选 | 类型 | 说明 | + * | ----------------- | ---- | ------- | ------------------------------------------------------------ | + * | gen_txt | 是 | string | 需要生成的文字内容 | + * | video_template_id | 是 | string | 使用的视频模板ID | + * | voice_id | 是 | string | 音色ID,如:"zh-CN-YunxiNeural"。如果使用“default”,表示不指定具体的,由后端服务自动匹配 | + * | voice_style | 是 | string | TTS语音风格,如:”angry“。如果使用“default”,表示默认风格 | + * | video_files | 否 | array[] | 字典类型,包含背景、数字人、素材信息。缺省,使用默认模板。 | + * | + back_ground | 否 | array[] | 字典类型,背景信息 | + * | ++ image | 是 | string | 背景图片,base64编辑后的字符串类型数据 | + * | ++ type | 是 | string | 背景图片类型,共两种。horizontal 表示横版,vertical 表示竖版 | + * | + digital_human | 否 | array[] | 字典类型,数字人信息 | + * | ++ coord | 是 | array[] | 集合类型,表示相对于左上角的位置,如[100, 200],表示相对于左边缘100像素,相对于上边缘200相素 | + * | ++ level | 是 | uint32 | 数字人图片的层级,值越大表示越高层,0表示最底层 | + * | ++ ratio | 是 | float32 | 相对于原数字人图片大小的缩放比例,如0.5表示宽高均变为原来的一半 | + * | + material | 否 | array[] | 字典类型,素材信息。具体的值是集合类型,内部由每个素材信息(素材信息是字典类型)组成,如"material":[{素材1的信息},{素材2的信息},{素材3的信息}] | + * | ++ | 否 | array[] | 集合类型,每个素材信息(素材信息是字典类型)组成 | + * | +++ coord | 是 | array[] | 集合类型,表示相对于左上角的位置,如[100, 200],表示相对于左边缘100像素,相对于上边缘200相素 | + * | +++ image | 是 | string | 素材图片,base64编辑后的字符串类型数据 | + * | +++ level | 是 | uint32 | 素材图片的层级,值越大表示越高层,0表示最底层 | + * | +++ ratio | 是 | float32 | 相对于原素材图片大小的缩放比例,如0.5表示宽高均变为原来的一半 | + */ + + private String gen_txt; + private String video_template_id; + private String voice_id; + private String voice_style; + private VideoFiles video_files; + + @Data + public static class VideoFiles { + private BackGround back_ground; + private Material digital_human; + private List material; + } + + @Data + public static class BackGround { + private String image; + private String type; + } + + @Data + public static class Material { + private int[] coord; + private String image; + private int level; + private float ratio; + } + +} diff --git a/suimangService/src/main/java/com/iformall/utils/Base64Util.java b/suimangService/src/main/java/com/iformall/utils/Base64Util.java index 9ce83af..a41780f 100644 --- a/suimangService/src/main/java/com/iformall/utils/Base64Util.java +++ b/suimangService/src/main/java/com/iformall/utils/Base64Util.java @@ -1,8 +1,12 @@ package com.iformall.utils; -import java.io.IOException; -import java.io.OutputStream; -import java.io.Writer; +import sun.misc.BASE64Encoder; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class Base64Util { private static final char S_BASE64CHAR[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', @@ -309,4 +313,79 @@ public class Base64Util { } } + /** + * 图片URL转Base64编码 + * @param imgUrl 图片URL + * @return Base64编码 + */ + public static String imageUrlToBase64(String imgUrl) { + URL url = null; + InputStream is = null; + ByteArrayOutputStream outStream = null; + HttpURLConnection httpUrl = null; + + try { + url = new URL(imgUrl); + httpUrl = (HttpURLConnection) url.openConnection(); + httpUrl.connect(); + httpUrl.getInputStream(); + + is = httpUrl.getInputStream(); + outStream = new ByteArrayOutputStream(); + + //创建一个Buffer字符串 + byte[] buffer = new byte[1024]; + //每次读取的字符串长度,如果为-1,代表全部读取完毕 + int len = 0; + //使用输入流从buffer里把数据读取出来 + while( (len = is.read(buffer)) != -1 ){ + //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度 + outStream.write(buffer, 0, len); + } + + // 对字节数组Base64编码 + return encode(outStream.toByteArray()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if(is != null) { + is.close(); + } + if(outStream != null) { + outStream.close(); + } + if(httpUrl != null) { + httpUrl.disconnect(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + return null; + } + +// /** +// * 图片转字符串 +// * @param image 图片Buffer +// * @return Base64编码 +// */ +// public static String encode(byte[] image){ +// BASE64Encoder decoder = new BASE64Encoder(); +// return replaceEnter(decoder.encode(image)); +// } +// +// /** +// * 字符替换 +// * @param str 字符串 +// * @return 替换后的字符串 +// */ +// public static String replaceEnter(String str){ +// String reg ="[\n-\r]"; +// Pattern p = Pattern.compile(reg); +// Matcher m = p.matcher(str); +// return m.replaceAll(""); +// } + } diff --git a/suimangService/src/main/java/com/iformall/utils/HttpUtil.java b/suimangService/src/main/java/com/iformall/utils/HttpUtil.java index 9b7d2d7..f13f7bb 100644 --- a/suimangService/src/main/java/com/iformall/utils/HttpUtil.java +++ b/suimangService/src/main/java/com/iformall/utils/HttpUtil.java @@ -133,13 +133,8 @@ public class HttpUtil { // 实例化HTTP方法 HttpPost request = new HttpPost(); - request.setURI(new URI(url)); - request.setConfig(RequestConfig.custom() - .setConnectionRequestTimeout(5000) - .setConnectTimeout(300000) - .setSocketTimeout(300000) - .build()); + //设置参数 List nvps = new ArrayList(); for (Iterator iter = params.keySet().iterator(); iter.hasNext();) { @@ -382,52 +377,6 @@ public class HttpUtil { return null; } -// /** -// * post请求(用于请求json格式的参数) -// * @param url -// * @param params -// * @return -// */ -// public static String doPost(String url, String params) throws Exception { -// -// CloseableHttpClient httpclient = HttpClients.createDefault(); -// HttpPost httpPost = new HttpPost(url);// 创建httpPost -// httpPost.setHeader("Accept", "application/json"); -// httpPost.setHeader("Content-Type", "application/json"); -// String charSet = "UTF-8"; -// StringEntity entity = new StringEntity(params, charSet); -// httpPost.setEntity(entity); -// CloseableHttpResponse response = null; -// -// try { -// response = httpclient.execute(httpPost); -// StatusLine status = response.getStatusLine(); -// int state = status.getStatusCode(); -// if (state == HttpStatus.SC_OK) { -// HttpEntity responseEntity = response.getEntity(); -// String jsonString = EntityUtils.toString(responseEntity); -// return jsonString; -// } -// else{ -// logger.info("请求返回:"+state+"("+url+")"); -// } -// } -// finally { -// if (response != null) { -// try { -// response.close(); -// } catch (IOException e) { -// logger.error(e.getMessage()); -// } -// } -// try { -// httpclient.close(); -// } catch (IOException e) { -// logger.error(e.getMessage()); -// } -// } -// return null; -// } /** * post请求(用于请求json格式的参数) @@ -646,5 +595,61 @@ public class HttpUtil { // // } + /** + * post请求(用于请求json格式的参数) + * @param url + * @param params + * @return + */ + public static String doAiVideoPost(String url, String params){ + + CloseableHttpClient httpclient = HttpClients.createDefault(); + HttpPost httpPost = new HttpPost(url);// 创建httpPost + httpPost.setConfig(RequestConfig.custom() + .setConnectionRequestTimeout(5000) + .setConnectTimeout(3000000) + .setSocketTimeout(3000000) + .build()); + httpPost.setHeader("Accept", "application/json"); + httpPost.setHeader("Content-Type", "application/json"); + String charSet = "UTF-8"; + StringEntity entity = new StringEntity(params, charSet); + httpPost.setEntity(entity); + CloseableHttpResponse response = null; + + try { + response = httpclient.execute(httpPost); + StatusLine status = response.getStatusLine(); + int state = status.getStatusCode(); + if (state == HttpStatus.SC_OK) { + HttpEntity responseEntity = response.getEntity(); + String jsonString = EntityUtils.toString(responseEntity); + return jsonString; + } + else{ + logger.info("请求返回:"+state+"("+url+")"); + } + } + catch(Exception e){ + logger.error(e.getMessage()); + return null; + } + finally { + if (response != null) { + try { + response.close(); + } catch (IOException e) { + logger.error(e.getMessage()); + } + } + try { + httpclient.close(); + } catch (IOException e) { + logger.error(e.getMessage()); + } + } + return null; + } + }