|
@@ -0,0 +1,302 @@
|
|
|
+package com.backendsys.modules.sdk.baidu.bce.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.hutool.http.HttpUtil;
|
|
|
+import cn.hutool.json.JSONArray;
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
+import com.backendsys.modules.ai.media.entity.AiGenerateVideoDTO;
|
|
|
+import com.backendsys.modules.ai.media.entity.MediaParams.MediaParams;
|
|
|
+import com.backendsys.modules.sdk.baidu.bce.entity.AiGenerateVideoCustom.*;
|
|
|
+import com.backendsys.modules.sdk.baidu.bce.service.BaiduBceMediaService;
|
|
|
+import com.backendsys.modules.sdk.baidu.bce.utils.BaiduBceUtil;
|
|
|
+import com.backendsys.utils.CustomArrayUtil;
|
|
|
+import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.core.ParameterizedTypeReference;
|
|
|
+import org.springframework.http.HttpHeaders;
|
|
|
+import org.springframework.http.HttpMethod;
|
|
|
+import org.springframework.http.MediaType;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.web.reactive.function.client.WebClient;
|
|
|
+
|
|
|
+import java.net.URI;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * 百度AI成片
|
|
|
+ * https://ai.baidu.com/ai-doc/NLP/Zk7ylspjv
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class BaiduBceMediaServiceImpl implements BaiduBceMediaService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private BaiduBceUtil baiduBceUtil;
|
|
|
+
|
|
|
+
|
|
|
+ // [百度-AI成片] 封装拼接授权过的 AccessToken URL
|
|
|
+ private URI getUriWithParams(String url) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * [方法] 将接口入参 (AiGenerateVideoDTO) 转换为 符合SDK接口的格式 (AiGenerateVideoDTOResponse)
|
|
|
+ */
|
|
|
+ private AiGenerateVideoCustomDTO formatCustom(AiGenerateVideoDTO aiGenerateVideoDTO) {
|
|
|
+
|
|
|
+ System.out.println("----------------------------------");
|
|
|
+ System.out.println(aiGenerateVideoDTO);
|
|
|
+
|
|
|
+ AiGenerateVideoCustomDTO customDTO = new AiGenerateVideoCustomDTO();
|
|
|
+ SourceDTO sourceDTO = new SourceDTO();
|
|
|
+ ConfigDTO configDTO = new ConfigDTO();
|
|
|
+
|
|
|
+ // -- source ------------------------------------------------------------
|
|
|
+ String source = aiGenerateVideoDTO.getSource();
|
|
|
+ // \"structs\":[{\"type\":\"text\",\"text\":\"夕阳如红色绸带轻轻拂过天际,悄然间,大地沐浴在金色的温柔中。\"},{\"type\":\"image\",\"mediaSource\":{\"type\":3,\"url\":\"http://dev.manage.daoguyujia.com/assets/p1.jpg\"}}]
|
|
|
+ JSONObject sourceJSON = JSONUtil.parseObj(source);
|
|
|
+ JSONArray structs = (JSONArray) sourceJSON.get("structs");
|
|
|
+
|
|
|
+ List<SourceStructDTO> StructList = new ArrayList<>();
|
|
|
+ for (int i=0; i < structs.size(); i++) {
|
|
|
+ SourceStructDTO sourceStructDTO = new SourceStructDTO();
|
|
|
+ //
|
|
|
+ JSONObject obj = structs.getJSONObject(i);
|
|
|
+ String type = (String) obj.get("type");
|
|
|
+ sourceStructDTO.setType(type);
|
|
|
+ if (type.equals("text")) {
|
|
|
+ String text = (String) obj.get("text");
|
|
|
+ sourceStructDTO.setText(text);
|
|
|
+ }
|
|
|
+ if (type.equals("image")) {
|
|
|
+ MediaSourceVO mediaSourceVO = new MediaSourceVO();
|
|
|
+ JSONObject mediaSourceObj = (JSONObject) obj.get("mediaSource");
|
|
|
+ mediaSourceVO.setType(3);
|
|
|
+ mediaSourceVO.setUrl((String) mediaSourceObj.get("url"));
|
|
|
+
|
|
|
+ sourceStructDTO.setMediaSource(mediaSourceVO);
|
|
|
+ }
|
|
|
+ //
|
|
|
+ StructList.add(sourceStructDTO);
|
|
|
+ }
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
+ sourceDTO.setStructs(StructList);
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
+ customDTO.setSource(sourceDTO);
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
+
|
|
|
+ // -- config ---------------------------------------------------------------
|
|
|
+ configDTO.setResolution(aiGenerateVideoDTO.getResolution());
|
|
|
+ configDTO.setProductType(aiGenerateVideoDTO.getProduct_type());
|
|
|
+ configDTO.setTtsPer(aiGenerateVideoDTO.getTts_per());
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
+ // -- config.bgMusic.mediaSource (背景图) -----------------------------------
|
|
|
+ String bg_music_url = aiGenerateVideoDTO.getBg_music_url();
|
|
|
+ if (StrUtil.isNotBlank(bg_music_url)) {
|
|
|
+ ConfigBgMusicDTO bgMusicDTO = new ConfigBgMusicDTO();
|
|
|
+
|
|
|
+ MediaSourceVO mediaSourceVO = new MediaSourceVO();
|
|
|
+ mediaSourceVO.setType(3);
|
|
|
+ mediaSourceVO.setUrl(bg_music_url);
|
|
|
+ bgMusicDTO.setMediaSource(mediaSourceVO);
|
|
|
+
|
|
|
+ configDTO.setBgMusic(bgMusicDTO);
|
|
|
+ }
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
+ // -- config.videoBegin.mediaSource (片头) ----------------------------------
|
|
|
+ String video_begin_url = aiGenerateVideoDTO.getVideo_begin_url();
|
|
|
+ if (StrUtil.isNotBlank(video_begin_url)) {
|
|
|
+ ConfigVideoBeginDTO videoBeginDTO = new ConfigVideoBeginDTO();
|
|
|
+
|
|
|
+ MediaSourceVO mediaSourceVO = new MediaSourceVO();
|
|
|
+ mediaSourceVO.setType(3);
|
|
|
+ mediaSourceVO.setUrl(video_begin_url);
|
|
|
+ videoBeginDTO.setMediaSource(mediaSourceVO);
|
|
|
+
|
|
|
+ configDTO.setVideoBegin(videoBeginDTO);
|
|
|
+ }
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
+ // -- config.videoEnd.mediaSource (片尾) ------------------------------------
|
|
|
+ String video_end_url = aiGenerateVideoDTO.getVideo_end_url();
|
|
|
+ if (StrUtil.isNotBlank(video_end_url)) {
|
|
|
+ ConfigVideoEndDTO videoEndDTO = new ConfigVideoEndDTO();
|
|
|
+
|
|
|
+ MediaSourceVO mediaSourceVO = new MediaSourceVO();
|
|
|
+ mediaSourceVO.setType(3);
|
|
|
+ mediaSourceVO.setUrl(video_end_url);
|
|
|
+ videoEndDTO.setMediaSource(mediaSourceVO);
|
|
|
+
|
|
|
+ configDTO.setVideoEnd(videoEndDTO);
|
|
|
+ }
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
+ // -- config.videoLogo (LOGO) ----------------------------------------------
|
|
|
+ String video_logo_url = aiGenerateVideoDTO.getVideo_logo_url();
|
|
|
+ if (StrUtil.isNotBlank(video_logo_url)) {
|
|
|
+ ConfigVideoLogoDTO videoLogoDTO = new ConfigVideoLogoDTO();
|
|
|
+
|
|
|
+ MediaSourceVO mediaSourceVO = new MediaSourceVO();
|
|
|
+ mediaSourceVO.setType(3);
|
|
|
+ mediaSourceVO.setUrl(video_logo_url);
|
|
|
+ videoLogoDTO.setMediaSource(mediaSourceVO);
|
|
|
+
|
|
|
+ String video_logo_location = aiGenerateVideoDTO.getVideo_logo_location();
|
|
|
+ Integer video_logo_margin = aiGenerateVideoDTO.getVideo_logo_margin();
|
|
|
+ if (StrUtil.isNotBlank(video_logo_location)) {
|
|
|
+ videoLogoDTO.setLocation(video_logo_location);
|
|
|
+ }
|
|
|
+ if (video_logo_margin != null) {
|
|
|
+ videoLogoDTO.setMargin(video_logo_margin);
|
|
|
+ }
|
|
|
+ configDTO.setVideoLogo(videoLogoDTO);
|
|
|
+ }
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
+ System.out.println("configDTO:");
|
|
|
+ System.out.println(configDTO);
|
|
|
+
|
|
|
+ customDTO.setConfig(configDTO);
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
+
|
|
|
+ return customDTO;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * [百度-AI成片] 定制成片任务
|
|
|
+ * https://ai.baidu.com/ai-doc/NLP/Zk7ylspjv
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public JSONObject makeGenerateVideo(MediaParams mediaParams) throws JsonProcessingException {
|
|
|
+
|
|
|
+// // structs: 文本、图片素材内容,文字内容必填,structs中文本总长度在20-800字符之间
|
|
|
+// // mediaSource: 若内容类型type=image,该字段描述图片内容,支持jpg/jpeg/png格式的图片
|
|
|
+// // type: 内容类型,支持image(图片)、text(文字)、video(视频)
|
|
|
+// String imageUrl = "http://43.138.151.228:3001/2.jpg";
|
|
|
+// // 传入图片、视频的url地址,图片、视频总数量不得超过20个,视频总大小不超过1G
|
|
|
+// String text = "夕阳如红色绸带轻轻拂过天际,悄然间,大地沐浴在金色的温柔中。"; // 若内容类型type=text,该字段描述文本内容
|
|
|
+
|
|
|
+ String source = mediaParams.getSource();
|
|
|
+
|
|
|
+ // config: 视频生产配置
|
|
|
+ String productType = mediaParams.getProduct_type();
|
|
|
+ Integer ttsPer = mediaParams.getTts_per();
|
|
|
+ String resolution = CustomArrayUtil.convertToString(mediaParams.getResolution());
|
|
|
+
|
|
|
+// String productType = "video"; // 视频产出结果形式,支持产出为mp4和json格式。可选项为video、timeline。video: 产出结果为mp4视频;timeline: 产出结果为json时间轴信息;
|
|
|
+// Integer ttsPer = 4144; // 支持基础音库、甄选音库,默认4144:度姗姗-女;【基础音库】0:度小美-女、1:度小宇-男、3:度小云-男、4:度小丫-女童、5:度小娇-女、103:度小朵-女童、106:度小博-男、110:度小童-男童、111:度小萌-女、5003:度小遥-男、5118:度小婷-女、4003:度小耀-男、4100:度小雯-女、4103:度小米-男童、4105:度小灵-女、4106:度小文-男、4115:度小贤-男、4117:度小乔-女、4119:度小鹿-女;【甄选音库】4144:度姗姗-女、4140:度小新-女、4143:度清风-男、4129:度小彦-男、4278:度小贝-女、4254:度小清-女、4149:度星河-男
|
|
|
+// String resolution = "[1024,576]"; // 分辨率,横屏支持[1920,1080]、[1280,720]、[1024,576]、竖屏支持[1080,1920]、[720,1280]、[576,1024]
|
|
|
+
|
|
|
+ String templateId = ""; // 视频模板id,不传则智能匹配,横屏模板支持:"30","41","42","43","44","45","46","47","48","49",竖屏模板支持:"40","28","29","31","32","33","34","35","36","37","38","39","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70","71"
|
|
|
+
|
|
|
+ // bgMusic: 背景音乐,支持使用mp3格式,文件大小不超过10M
|
|
|
+ String bgMusicUrl = "";
|
|
|
+ // videoBegin: 视频片头,大小限制50M,格式为mp4或mov
|
|
|
+ String videoBeginUrl = "";
|
|
|
+ String videoEndUrl = "";
|
|
|
+
|
|
|
+ // caption: 字幕显示设置
|
|
|
+ String marginBottom = "170px"; // 字幕距离视频底部的位置,单位px,支持选择0-500。横屏默认值为70px;竖屏[1080,1920]默认为270px、[720,1280]默认为180px、[576,1024]默认为170px
|
|
|
+ String fontColor = "ffffff"; // 字体颜色,支持传入颜色的十六进制,默认:ffffff
|
|
|
+ Integer fontAlpha = 100; // 字体透明度,范围:0-100,从透明到不透明,默认:100
|
|
|
+ String bgColor = "927070"; // 字幕背景颜色,支持传入颜色的十六进制,默认:927070
|
|
|
+ Integer bgAlpha = 32; // 字幕背景透明度,范围:0-100,从透明到不透明,默认32
|
|
|
+
|
|
|
+ String location = ""; // 角标位置,支持:top-left(左上)、top-right(右上),默认为 top-left
|
|
|
+ Integer margin = 20; // 角标边缘距离,单位px,支持0-100,默认为 20
|
|
|
+
|
|
|
+ String params = "{" +
|
|
|
+ "\"source\":" + source + "," +
|
|
|
+// "\"source\":{" +
|
|
|
+// "\"structs\":[" +
|
|
|
+// "{" +
|
|
|
+// "\"type\":\"image\"," +
|
|
|
+// "\"mediaSource\":{" +
|
|
|
+// "\"type\":3," +
|
|
|
+// "\"url\":\"" + imageUrl + "\"" +
|
|
|
+// "}" +
|
|
|
+// "}," +
|
|
|
+// "{" +
|
|
|
+// "\"type\":\"text\"," +
|
|
|
+// "\"text\":\"" + text + "\"" +
|
|
|
+// "}" +
|
|
|
+// "]" +
|
|
|
+// "}," +
|
|
|
+ "\"config\":{" +
|
|
|
+ "\"productType\":\"" + productType + "\"," +
|
|
|
+ "\"ttsPer\":" + ttsPer + "," +
|
|
|
+ "\"resolution\":" + resolution + "" +
|
|
|
+
|
|
|
+// "\"resolution\":" + resolution + "," +
|
|
|
+// "\"templateId\":\"" + templateId + "\"" +
|
|
|
+// "\"bgMusic\":{" +
|
|
|
+// "\"mediaSource\":{" +
|
|
|
+// "\"type\":3," +
|
|
|
+// "\"url\":\"" + bgMusicUrl + "\"" +
|
|
|
+// "}"+
|
|
|
+// "}," +
|
|
|
+// "\"videoBegin\":{" +
|
|
|
+// "\"mediaSource\":{" +
|
|
|
+// "\"type\":3," +
|
|
|
+// "\"url\":\"" + videoBeginUrl + "\"" +
|
|
|
+// "}"+
|
|
|
+// "},"+
|
|
|
+// "\"videoEnd\":{" +
|
|
|
+// "\"mediaSource\":{" +
|
|
|
+// "\"type\":3," +
|
|
|
+// "\"url\":\"" + videoEndUrl + "\"" +
|
|
|
+// "}"+
|
|
|
+// "},"+
|
|
|
+// "\"caption\":{" +
|
|
|
+// "\"marginBottom\":\"" + marginBottom + "\"," +
|
|
|
+// "\"fontColor\":\"" + fontColor + "\"," +
|
|
|
+// "\"fontAlpha\":" + fontAlpha + "," +
|
|
|
+// "\"bgColor\":\"" + bgColor + "\"," +
|
|
|
+// "\"bgAlpha\":" + bgAlpha + "" +
|
|
|
+// "},"+
|
|
|
+// "\"videoLogo\":{" +
|
|
|
+// "\"mediaSource\":{" +
|
|
|
+// "\"type\":3," +
|
|
|
+// "\"url\":\"" + videoEndUrl + "\"" +
|
|
|
+// "},"+
|
|
|
+// "\"location\":\"" + location + "\"," +
|
|
|
+// "\"margin\":" + margin + "" +
|
|
|
+// "}"+
|
|
|
+ "}" +
|
|
|
+ "}";
|
|
|
+
|
|
|
+ System.out.println("-------------------------------------------");
|
|
|
+ System.out.println(params);
|
|
|
+ System.out.println("-------------------------------------------");
|
|
|
+
|
|
|
+ String access_token = baiduBceUtil.getAccessToken();
|
|
|
+ String result = HttpUtil.post("https://aip.baidubce.com/rpc/2.0/brain/creative/ttv/material?access_token=" + access_token, params);
|
|
|
+ JSONObject resultJSON = JSONUtil.parseObj(result);
|
|
|
+ return resultJSON;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * [百度-AI成片] 查询成片任务进度
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> getGenerateVideoProgress(Long jobId) {
|
|
|
+ // Body 参数
|
|
|
+ Map<String, Object> resultMap = new LinkedHashMap<>();
|
|
|
+ resultMap.put("jobId", jobId);
|
|
|
+ String bodyData = JSONUtil.toJsonStr(resultMap);
|
|
|
+
|
|
|
+ // Http 远程调用
|
|
|
+ URI uriWithParams = getUriWithParams("https://aip.baidubce.com/rpc/2.0/brain/creative/ttv/query");
|
|
|
+ Map<String, Object> resp = WebClient.create()
|
|
|
+ .method(HttpMethod.POST)
|
|
|
+ .uri(uriWithParams)
|
|
|
+ .bodyValue(bodyData.toString())
|
|
|
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
|
|
+ .retrieve().bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
|
|
|
+ })
|
|
|
+ .block();
|
|
|
+
|
|
|
+ System.out.println("getGenerateVideoProgress resp:");
|
|
|
+ System.out.println(resp);
|
|
|
+ return resp;
|
|
|
+ }
|
|
|
+}
|