本文为您介绍如何使用SubmitBatchMediaProducingJob - 批量智能一键成片来完成批量一键成片及批量个性化混剪。
场景介绍
进入5G时代,越来越多的商家选择短视频平台做营销推广,将广告制作成短视频投放在多个KOL或营销号。由于各大短视频平台有去重机制(防止视频盗用),内容相同的营销视频会被屏蔽处理,这就要求投放在不同账号的视频,在内容、结构上要有差别。
本文中的示例代码是常见的批量混剪流程,即通过少量的素材和一段口播,通过不同的组合合成出多段不一样的视频成片:
方案一和方案二是通过批量合成接口一次合成多个成片,简单易用。
方案三是通过Timeline的方式,开发者可以对视频进行更多的调整。
使用说明
将多个视频、音频、图片素材进行智能混剪,一键批量合成视频接口说明,请参见SubmitBatchMediaProducingJob - 批量智能一键成片。
获取批量智能一键成片作业的详细信息,请参见GetBatchMediaProducingJob - 获取批量智能一键成片任务信息。
批量智能一键成片参数InputConfig详情,请参见InputConfig 参数说明。
前提条件
您已安装IMS服务端SDK,详情请参见准备工作。
方案一:批量脚本化一键成片
结果示例
竖屏 | 横屏 |
SDK调用示例
展开查看代码示例
package com.example;
import java.util.*;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.ice20201109.Client;
import com.aliyun.ice20201109.models.*;
import com.aliyun.teaopenapi.models.Config;
/**
* 需要maven引入二方包依赖:
* <dependency>
* <groupId>com.aliyun</groupId>
* <artifactId>ice20201109</artifactId>
* <version>2.3.0</version>
* </dependency>
* <dependency>
* <groupId>com.alibaba</groupId>
* <artifactId>fastjson</artifactId>
* <version>1.2.9</version>
* </dependency>
*/
public class ScriptBatchEditingService {
static final String regionId = "<service-region>"; // 智能图文匹配支持cn-shanghai,cn-beijing,cn-hangzhou
static final String bucket = "<your-bucket>";
private Client iceClient;
public static void main(String[] args) throws Exception {
ScriptBatchEditingService scriptBatchEditingService = new ScriptBatchEditingService();
scriptBatchEditingService.initClient();
scriptBatchEditingService.runExample();
}
public void initClient() throws Exception {
// 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
// 本示例以将AccessKey ID和 AccessKey Secret保存在环境变量为例说明。配置方法请参见:https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-access-credentials?spm=a2c4g.11186623.0.0.423350fbOTFdOB#2a38e5c14b4em
com.aliyun.credentials.Client credentialClient = new com.aliyun.credentials.Client();
Config config = new Config();
config.setCredential(credentialClient);
// 如需硬编码AccessKey ID和AccessKey Secret,代码如下,但强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
// config.accessKeyId = <第二步创建的AccessKey ID>;
// config.accessKeySecret = <第二步创建的AccessKey Secret>;
config.endpoint = "ice." + regionId + ".aliyuncs.com";
config.regionId = regionId;
iceClient = new Client(config);
}
public void runExample() throws Exception {
// 视频素材
JSONObject mediaGroup1 = new JSONObject();
mediaGroup1.put("GroupName", "start");
mediaGroup1.put("MediaArray", Arrays.asList(
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/lgh/lgh-start-1.mp4"
));
JSONObject mediaGroup2 = new JSONObject();
mediaGroup2.put("GroupName", "middle");
mediaGroup2.put("MediaArray", Arrays.asList(
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/lgh/lgh-m-1.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/lgh/lgh-m-2.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/lgh/lgh-m-3.mp4"
));
JSONObject mediaGroup3 = new JSONObject();
mediaGroup3.put("GroupName", "end");
mediaGroup3.put("MediaArray", Arrays.asList(
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/lgh/lgh-end-1.mp4"
));
JSONArray mediaGroupArray = new JSONArray();
mediaGroupArray.add(mediaGroup1);
mediaGroupArray.add(mediaGroup2);
mediaGroupArray.add(mediaGroup3);
// 口播文案
List<String> speechTextArray = Arrays.asList(
"假期纠结去哪儿玩?云南泸沽湖邀您共赴一场与自然的约会。湛蓝湖水如镜,映照着摩梭女儿国的独特风情,如诗如画。泛舟湖心,感受猪槽船摇曳的岁月静好;仰望女神山,倾听古老神秘的故事传说。还在等什么,快来泸沽湖共享这一份静谧而迷人的湖光山色吧!",
"假期规划还在犹豫不决?何不考虑赴一场云南泸沽湖的自然盛宴。那湛蓝如镜的湖面,映射出摩梭女儿国独特的民俗风情,如诗如画,引人入胜。您可在湖心悠然泛舟,体验猪槽船摇曳间的宁静岁月;也可抬头瞻仰神圣女神山,倾听那穿越千年的古老神秘传说。快来泸沽湖,共享这片静谧而迷人的湖光山色所带来的无尽诗意吧!"
);
// 视频标题
List<String> titleArray = Arrays.asList(
"泸沽湖:湖光山色中的摩梭风情",
"探寻秘境泸沽湖",
"沉浸式体验泸沽湖"
);
JSONObject inputConfig = new JSONObject();
inputConfig.put("MediaGroupArray", mediaGroupArray);
inputConfig.put("SpeechTextArray", speechTextArray);
inputConfig.put("TitleArray", titleArray);
// 生成的成片数
int produceCount = 4;
// 成片宽高,生成竖屏文件
//int outputWidth = 1080;
//int outputHeight = 1920;
//// 成片宽高,生成横屏文件
int outputWidth = 1920;
int outputHeight = 1080;
// 成片oss地址,需包含{index} 占位符
String mediaUrl = "http://" + bucket + ".oss-" + regionId + ".aliyuncs.com/script/output_{index}_w.mp4";
JSONObject outputConfig = new JSONObject();
outputConfig.put("MediaURL", mediaUrl);
outputConfig.put("Count", produceCount);
outputConfig.put("Width", outputWidth);
outputConfig.put("Height", outputHeight);
// 提交一键成片任务
SubmitBatchMediaProducingJobRequest request = new SubmitBatchMediaProducingJobRequest();
request.setInputConfig(inputConfig.toJSONString());
request.setOutputConfig(outputConfig.toJSONString());
SubmitBatchMediaProducingJobResponse response = iceClient.submitBatchMediaProducingJob(request);
String jobId = response.getBody().getJobId();
System.out.println("Start script batch job, batchJobId: " + jobId);
// 轮询任务状态直到全部结束
System.out.println("Waiting job finished...");
int maxTry = 3000;
int i = 0;
while (i < maxTry) {
Thread.sleep(3000);
i++;
GetBatchMediaProducingJobRequest getRequest = new GetBatchMediaProducingJobRequest();
getRequest.setJobId(jobId);
GetBatchMediaProducingJobResponse getResponse = iceClient.getBatchMediaProducingJob(getRequest);
String status = getResponse.getBody().getEditingBatchJob().getStatus();
System.out.println("BatchJobId: " + jobId + ", status:" + status);
if ("Failed".equals(status)) {
System.out.println("Batch job failed. JobInfo: " + JSONObject.toJSONString(getResponse.getBody().getEditingBatchJob()));
throw new Exception("Produce failed. BatchJobId: " + jobId);
}
if ("Finished".equals(status)) {
System.out.println("Batch job finished. JobInfo: " + JSONObject.toJSONString(getResponse.getBody().getEditingBatchJob()));
break;
}
}
}
}
API调用入参详情
展开查看InputConfig
{
"MediaGroupArray": [{
"GroupName": "start",
"MediaArray": [
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/lgh/lgh-start-1.mp4"
]
},
{
"GroupName": "middle",
"MediaArray": [
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/lgh/lgh-m-1.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/lgh/lgh-m-2.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/lgh/lgh-m-3.mp4"
]
},
{
"GroupName": "end",
"MediaArray": [
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/lgh/lgh-end-1.mp4"
]
}
],
"SpeechTextArray": [
"假期纠结去哪儿玩?云南泸沽湖邀您共赴一场与自然的约会。湛蓝湖水如镜,映照着摩梭女儿国的独特风情,如诗如画。泛舟湖心,感受猪槽船摇曳的岁月静好;仰望女神山,倾听古老神秘的故事传说。还在等什么,快来泸沽湖共享这一份静谧而迷人的湖光山色吧!",
"假期规划还在犹豫不决?何不考虑赴一场云南泸沽湖的自然盛宴。那湛蓝如镜的湖面,映射出摩梭女儿国独特的民俗风情,如诗如画,引人入胜。您可在湖心悠然泛舟,体验猪槽船摇曳间的宁静岁月;也可抬头瞻仰神圣女神山,倾听那穿越千年的古老神秘传说。快来泸沽湖,共享这片静谧而迷人的湖光山色所带来的无尽诗意吧!"
],
"TitleArray": [
"泸沽湖:湖光山色中的摩梭风情",
"探寻秘境泸沽湖",
"沉浸式体验泸沽湖"
]
}
展开查看OutputConfig
{
"Count": 4,
"Height": 1080,
"Width": 1920,
"MediaURL": "http://<your-bucket>.oss-<region-id>.aliyuncs.com/script/output_{index}_w.mp4"
}
方案二:批量智能图文匹配一键成片
结果示例
竖屏 | 横屏 |
SDK调用示例
展开查看代码示例
package com.example;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.ice20201109.Client;
import com.aliyun.ice20201109.models.*;
import com.aliyun.teaopenapi.models.Config;
import java.util.*;
/**
* 需要maven引入二方包依赖:
* <dependency>
* <groupId>com.aliyun</groupId>
* <artifactId>ice20201109</artifactId>
* <version>2.3.0</version>
* </dependency>
* <dependency>
* <groupId>com.alibaba</groupId>
* <artifactId>fastjson</artifactId>
* <version>1.2.9</version>
* </dependency>
*/
public class SmartMixBatchEditingService {
static final String regionId = "<service-region>"; // 智能图文匹配支持cn-shanghai,cn-beijing,cn-hangzhou
static final String bucket = "<your-bucket>";
private Client iceClient;
public static void main(String[] args) throws Exception {
SmartMixBatchEditingService smartMixBatchEditingService = new SmartMixBatchEditingService();
smartMixBatchEditingService.initClient();
smartMixBatchEditingService.runExample();
}
public void initClient() throws Exception {
// 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
// 本示例以将AccessKey ID和 AccessKey Secret保存在环境变量为例说明。配置方法请参见:https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-access-credentials?spm=a2c4g.11186623.0.0.423350fbOTFdOB#2a38e5c14b4em
com.aliyun.credentials.Client credentialClient = new com.aliyun.credentials.Client();
Config config = new Config();
config.setCredential(credentialClient);
// 如需硬编码AccessKey ID和AccessKey Secret,代码如下,但强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
// config.accessKeyId = <第二步创建的AccessKey ID>;
// config.accessKeySecret = <第二步创建的AccessKey Secret>;
config.endpoint = "ice." + regionId + ".aliyuncs.com";
config.regionId = regionId;
iceClient = new Client(config);
}
public void runExample() throws Exception {
// 视频素材
List<String> mediaArray = Arrays.asList(
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-1.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-2.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-3.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-4.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-5.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-6.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-7.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-8.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-9.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-10.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-11.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-12.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-13.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-14.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-15.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-16.mp4"
);
// 口播文案
String speechText = "在那广袤无垠的蔚蓝深处,一幅生机勃勃的画卷正徐徐展开。清澈碧蓝的海水中,珊瑚礁犹如海底森林,五彩斑斓,它们是海洋生物多样性的重要基石,为无数的小鱼、贝类和海藻提供庇护所。慵懒而可爱的海狮们,在岩石上享受着温暖阳光的沐浴,惬意地晒着太阳,与大自然和谐共生。海豚在蔚蓝的海水中结伴畅游,彼此追逐嬉戏,展现着大自然赋予的灵动与智慧。然而美丽的海洋环境正面临着前所未有的挑战。各种垃圾污染如同伤疤一般烙印在海洋的肌肤之上,无情地侵蚀着原本纯净的生态环境。众多物种面临食物短缺、疾病增多乃至种群减少的危机。我们必须行动起来,守护这份美丽而又脆弱的蓝色家园,让未来的海洋再次恢复它的纯净与活力。";
// 视频标题
String title = "守护蓝色家园";
JSONObject inputConfig = new JSONObject();
inputConfig.put("MediaArray", mediaArray);
inputConfig.put("SpeechText", speechText);
inputConfig.put("Title", title);
// 生成的成片数
int produceCount = 4;
// 成片宽高,生成竖屏文件
int outputWidth = 1080;
int outputHeight = 1920;
//// 成片宽高,生成横屏文件
//int outputWidth = 1920;
//int outputHeight = 1080;
// 成片oss地址,需包含{index} 占位符
String mediaUrl = "http://" + bucket + ".oss-" + regionId + ".aliyuncs.com/smart_mix/output_{index}.mp4";
JSONObject outputConfig = new JSONObject();
outputConfig.put("MediaURL", mediaUrl);
outputConfig.put("Count", produceCount);
outputConfig.put("Width", outputWidth);
outputConfig.put("Height", outputHeight);
// 提交一键成片任务
SubmitBatchMediaProducingJobRequest request = new SubmitBatchMediaProducingJobRequest();
request.setInputConfig(inputConfig.toJSONString());
request.setOutputConfig(outputConfig.toJSONString());
SubmitBatchMediaProducingJobResponse response = iceClient.submitBatchMediaProducingJob(request);
String jobId = response.getBody().getJobId();
System.out.println("Start smart mix batch job, batchJobId: " + jobId);
// 轮询任务状态直到全部结束
System.out.println("Waiting job finished...");
int maxTry = 3000;
int i = 0;
while (i < maxTry) {
Thread.sleep(3000);
i++;
GetBatchMediaProducingJobRequest getRequest = new GetBatchMediaProducingJobRequest();
getRequest.setJobId(jobId);
GetBatchMediaProducingJobResponse getResponse = iceClient.getBatchMediaProducingJob(getRequest);
String status = getResponse.getBody().getEditingBatchJob().getStatus();
System.out.println("BatchJobId: " + jobId + ", status:" + status);
if ("Failed".equals(status)) {
System.out.println("Batch job failed. JobInfo: " + JSONObject.toJSONString(getResponse.getBody().getEditingBatchJob()));
throw new Exception("Produce failed. BatchJobId: " + jobId);
}
if ("Finished".equals(status)) {
System.out.println("Batch job finished. JobInfo: " + JSONObject.toJSONString(getResponse.getBody().getEditingBatchJob()));
break;
}
}
}
}
API调用入参详情
展开查看InputConfig
{
"MediaArray": [
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-1.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-2.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-3.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-4.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-5.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-6.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-7.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-8.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-9.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-10.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-11.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-12.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-13.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-14.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-15.mp4",
"http://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/sea/sea-16.mp4"
],
"SpeechText": "在那广袤无垠的蔚蓝深处,一幅生机勃勃的画卷正徐徐展开。清澈碧蓝的海水中,珊瑚礁犹如海底森林,五彩斑斓,它们是海洋生物多样性的重要基石,为无数的小鱼、贝类和海藻提供庇护所。慵懒而可爱的海狮们,在岩石上享受着温暖阳光的沐浴,惬意地晒着太阳,与大自然和谐共生。海豚在蔚蓝的海水中结伴畅游,彼此追逐嬉戏,展现着大自然赋予的灵动与智慧。然而美丽的海洋环境正面临着前所未有的挑战。各种垃圾污染如同伤疤一般烙印在海洋的肌肤之上,无情地侵蚀着原本纯净的生态环境。众多物种面临食物短缺、疾病增多乃至种群减少的危机。我们必须行动起来,守护这份美丽而又脆弱的蓝色家园,让未来的海洋再次恢复它的纯净与活力。",
"Title":"守护蓝色家园"
}
展开查看OutputConfig
{
"Count": 4,
"Height": 1080,
"Width": 1920,
"MediaURL": "http://<your-bucket>.oss-<region-id>.aliyuncs.com/script/output_{index}_w.mp4"
}
方案三:批量个性化混剪
结果示例
输入为口播文案
展开查看示例代码
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.ice20201109.Client;
import com.aliyun.ice20201109.models.*;
import com.aliyun.teaopenapi.models.Config;
import java.util.*;
// 成功视频
// http://oushu-test-shanghai.oss-cn-shanghai.aliyuncs.com/ice_output/46b29eb5775f4f758846171ab79bfca7.mp4
/**
* 需要maven引入二方包依赖:
* <dependency>
* <groupId>com.aliyun</groupId>
* <artifactId>ice20201109</artifactId>
* <version>2.1.0</version>
* </dependency>
* <dependency>
* <groupId>com.alibaba</groupId>
* <artifactId>fastjson</artifactId>
* <version>1.2.9</version>
* </dependency>
*/
public class BatchProduceAlignment {
static final String regionId = "cn-shanghai";
static final String bucket = "<your-bucket>";
private Client iceClient;
public static void main(String[] args) throws Exception {
BatchProduceAlignment batchProduce = new BatchProduceAlignment();
batchProduce.initClient();
batchProduce.run();
}
public void initClient() throws Exception {
// 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
// 本示例以将AccessKey ID和 AccessKey Secret保存在环境变量为例说明。配置方法请参见:https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-access-credentials?spm=a2c4g.11186623.0.0.423350fbOTFdOB#2a38e5c14b4em
com.aliyun.credentials.Client credentialClient = new com.aliyun.credentials.Client();
Config config = new Config();
config.setCredential(credentialClient);
// 如需硬编码AccessKey ID和AccessKey Secret,代码如下,但强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
// config.accessKeyId = <第二步创建的AccessKey ID>;
// config.accessKeySecret = <第二步创建的AccessKey Secret>;
config.endpoint = "ice." + regionId + ".aliyuncs.com";
config.regionId = regionId;
iceClient = new Client(config);
}
public void run() throws Exception {
// 文字素材
String text = "人们懂得用五味杂陈形容人生,因为懂得味道是每个人心中固守的情怀。在这个时代,每一个人都经历了太多的苦痛和喜悦,人们总会将苦涩藏在心里,而把幸福变成食物,呈现在四季的餐桌之上";
// 视频素材
String[] videoArray = new String[]{
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f1.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f2.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f3.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f4.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f5.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f6.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f7.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f8.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f9.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f10.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f11.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f12.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f13.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f14.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f15.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f16.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f17.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f18.mp4"
};
// 背景音乐素材
String[] bgMusicArray = new String[]{
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/music/m1.wav",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/music/m2.wav",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/music/m3.wav"
};
// 视频标题
String title = "舌尖上的美食";
// 生成的成片数
int produceCount = 2;
// 批量提交任务
List<String> jobIds = new ArrayList<String>();
for (int i = 0; i < produceCount; i++) {
String jobId = produceSingleVideo(title, text, videoArray, bgMusicArray);
jobIds.add(jobId);
}
// 轮询任务状态直到全部结束
System.out.println("waiting job finished...");
while (true) {
Thread.sleep(3000);
boolean allFinished = true;
for (int i = 0; i < jobIds.size(); i++) {
String jobId = jobIds.get(i);
GetMediaProducingJobRequest req = new GetMediaProducingJobRequest();
req.setJobId(jobId);
GetMediaProducingJobResponse response = iceClient.getMediaProducingJob(req);
GetMediaProducingJobResponseBody.GetMediaProducingJobResponseBodyMediaProducingJob mediaProducingJob = response.getBody().getMediaProducingJob();
String status = mediaProducingJob.getStatus();
System.out.println("jobId: " + mediaProducingJob.getJobId() + ", status:" + status);
if ("Failed".equalsIgnoreCase(status)) {
System.out.println("jobfailed. jobInfo: " + JSONObject.toJSONString(mediaProducingJob));
throw new Exception("Produce failed. jobid: " + mediaProducingJob.getJobId());
}
if (!"Success".equalsIgnoreCase(status)) {
allFinished = false;
break;
}
}
if (allFinished) {
System.out.println("all job finished.");
break;
}
}
}
public String produceSingleVideo(String title, String text, String[] videoArray, String[] bgMusicArray) throws Exception {
text = text.replace(",", "。");
text = text.replace("\n", "。");
String[] sentenceArray = text.split("。");
JSONArray videoClipArray = new JSONArray();
JSONArray audioClipArray = new JSONArray();
List<String> videoList = Arrays.asList(videoArray);
Collections.shuffle(videoList);
for (int i = 0; i < sentenceArray.length; i++) {
String sentence = sentenceArray[i];
String clipId = "clip" + i;
String videoUrl = videoList.get(i);
String videoClip = "{\"MediaURL\":\""+videoUrl+"\",\"ReferenceClipId\":\""+clipId+"\",\"Effects\":[{\"Type\":\"Background\",\"SubType\":\"Blur\",\"Radius\":0.1}]}";
videoClipArray.add(JSONObject.parseObject(videoClip));
String audioClip = "{\"Type\":\"AI_TTS\",\"Content\":\"" + sentence + "\",\"Voice\":\"zhichu\",\"ClipId\":\""+clipId+"\",\"Effects\":[{\"Type\":\"AI_ASR\",\"Font\":\"Alibaba PuHuiTi\",\"Alignment\":\"TopCenter\",\"Y\":0.75,\"FontSize\":55,\"FontColor\":\"#ffffff\",\"AdaptMode\":\"AutoWrap\",\"TextWidth\":0.8,\"Outline\":2,\"OutlineColour\":\"#000000\"}]}";
audioClipArray.add(JSONObject.parseObject(audioClip));
}
String subtitleTrack = "{\"SubtitleTrackClips\":[{\"Type\":\"Text\",\"Font\":\"HappyZcool-2016\",\"Content\":\""+title+"\",\"FontSize\":80,\"FontColor\":\"#ffffff\",\"Y\":0.15,\"Alignment\":\"TopCenter\",\"EffectColorStyle\":\"CS0004-000005\",\"FontFace\":{\"Bold\":true,\"Italic\":false,\"Underline\":false}}]}";
int bgMusicIndex = (int)(Math.random() * bgMusicArray.length);
String bgMusicUrl = bgMusicArray[bgMusicIndex];
String timeline = "{\"VideoTracks\":[{\"VideoTrackClips\":"+videoClipArray.toJSONString()+"}],\"AudioTracks\":[{\"AudioTrackClips\":"+audioClipArray.toJSONString()+"},{\"AudioTrackClips\":[{\"MediaURL\":\""+bgMusicUrl+"\"}]}],\"SubtitleTracks\":[" + subtitleTrack + "]}";
//
String targetFileName = UUID.randomUUID().toString().replace("-", "");
String outputMediaUrl = "http://" + bucket + ".oss-" + regionId + ".aliyuncs.com/ice_output/" + targetFileName + ".mp4";
int width = 720;
int height = 1280;
String outputMediaConfig = "{\"MediaURL\":\"" + outputMediaUrl + "\",\"Width\":"+width+",\"Height\":"+height+"}";
SubmitMediaProducingJobRequest request = new SubmitMediaProducingJobRequest();
request.setTimeline(timeline);
request.setOutputMediaConfig(outputMediaConfig);
SubmitMediaProducingJobResponse response = iceClient.submitMediaProducingJob(request);
System.out.println("start job. jobid: " + response.getBody().getJobId() + ", outputMediaUrl: " + outputMediaUrl);
return response.getBody().getJobId();
}
}
输入为口播音频
展开查看示例代码
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.ice20201109.Client;
import com.aliyun.ice20201109.models.*;
import com.aliyun.teaopenapi.models.Config;
import java.util.*;
/**
* 需要maven引入二方包依赖:
* <dependency>
* <groupId>com.aliyun</groupId>
* <artifactId>ice20201109</artifactId>
* <version>2.1.0</version>
* </dependency>
* <dependency>
* <groupId>com.alibaba</groupId>
* <artifactId>fastjson</artifactId>
* <version>1.2.9</version>
* </dependency>
*/
public class BatchProduce {
static final String regionId = "cn-shanghai";
static final String bucket = "<your-bucket>";
private Client iceClient;
public static void main(String[] args) throws Exception {
BatchProduce batchProduce = new BatchProduce();
batchProduce.initClient();
batchProduce.run();
}
public void initClient() throws Exception {
// 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
// 本示例以将AccessKey ID和 AccessKey Secret保存在环境变量为例说明。配置方法请参见:https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-access-credentials?spm=a2c4g.11186623.0.0.423350fbOTFdOB#2a38e5c14b4em
com.aliyun.credentials.Client credentialClient = new com.aliyun.credentials.Client();
Config config = new Config();
config.setCredential(credentialClient);
// 如需硬编码AccessKey ID和AccessKey Secret,代码如下,但强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
// config.accessKeyId = <第二步创建的AccessKey ID>;
// config.accessKeySecret = <第二步创建的AccessKey Secret>;
config.endpoint = "ice." + regionId + ".aliyuncs.com";
config.regionId = regionId;
iceClient = new Client(config);
}
public void run() throws Exception {
// 口播音频素材
String inputSpeechAudio = "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/food_speech.mp3";
// 视频素材
String[] videoArray = new String[]{
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f1.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f2.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f3.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f4.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f5.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f6.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f7.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f8.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f9.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f10.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f11.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f12.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f13.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f14.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f15.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f16.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f17.mp4",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f18.mp4"
};
// 背景音乐素材
String[] bgMusicArray = new String[]{
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/music/m1.wav",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/music/m2.wav",
"https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/music/m3.wav"
};
// 视频标题
String title = "舌尖上的美食";
// 生成的成片数
int produceCount = 2;
// 开始合成
// 步骤1:对口播进行语音识别
SubmitASRJobRequest asrJobRequest = new SubmitASRJobRequest();
asrJobRequest.setInputFile(inputSpeechAudio);
SubmitASRJobResponse asrJobResponse = iceClient.submitASRJob(asrJobRequest);
String asrJobId = asrJobResponse.getBody().getJobId();
String asrResult = null;
for (int i = 0; i < 10000; i++) {
Thread.sleep(3000);
GetSmartHandleJobRequest getSmartHandleJobRequest = new GetSmartHandleJobRequest();
getSmartHandleJobRequest.setJobId(asrJobId);
GetSmartHandleJobResponse asrResponse = iceClient.getSmartHandleJob(getSmartHandleJobRequest);
String jobStatus = asrResponse.getBody().getState();
System.out.println("asrJobId: " + asrJobId + ", status: " + jobStatus);
if ("Failed".equalsIgnoreCase(jobStatus)) {
System.out.println("asr job failed.");
return;
}
if ("Finished".equalsIgnoreCase(jobStatus)) {
asrResult = asrResponse.getBody().getJobResult().getAiResult();
break;
}
}
System.out.println("asr job finished. asr result: " + asrResult);
// 步骤2:批量提交任务
List<String> jobIds = new ArrayList<String>();
for (int i = 0; i < produceCount; i++) {
String jobId = produceSingleVideo(title, inputSpeechAudio, asrResult, videoArray, bgMusicArray);
jobIds.add(jobId);
}
// 步骤3:轮询任务状态直到全部结束
System.out.println("waiting job finished...");
while (true) {
Thread.sleep(3000);
boolean allFinished = true;
for (int i = 0; i < jobIds.size(); i++) {
String jobId = jobIds.get(i);
GetMediaProducingJobRequest req = new GetMediaProducingJobRequest();
req.setJobId(jobId);
GetMediaProducingJobResponse response = iceClient.getMediaProducingJob(req);
GetMediaProducingJobResponseBody.GetMediaProducingJobResponseBodyMediaProducingJob mediaProducingJob = response.getBody().getMediaProducingJob();
String status = mediaProducingJob.getStatus();
System.out.println("jobId: " + mediaProducingJob.getJobId() + ", status:" + status);
if ("Failed".equalsIgnoreCase(status)) {
System.out.println("jobfailed. jobInfo: " + JSONObject.toJSONString(mediaProducingJob));
throw new Exception("Produce failed. jobid: " + mediaProducingJob.getJobId());
}
if (!"Success".equalsIgnoreCase(status)) {
allFinished = false;
break;
}
}
if (allFinished) {
System.out.println("all job finished.");
break;
}
}
}
public String produceSingleVideo(String title, String inputSpeechAudio, String asrResult, String[] videoArray, String[] bgMusicArray) throws Exception {
JSONArray videoClipArray = new JSONArray();
JSONArray subtitleClipArray = new JSONArray();
List<String> videoList = Arrays.asList(videoArray);
Collections.shuffle(videoList);
JSONArray asrResultArray = JSONArray.parseArray(asrResult);
for (int i = 0; i < asrResultArray.size(); i++) {
JSONObject asrItem = asrResultArray.getJSONObject(i);
String content = asrItem.getString("content");
float from = asrItem.getFloat("from");
float to = asrItem.getFloat("to");
float duration = to - from;
String videoUrl = videoList.get(i);
String videoClip = "{\"MediaURL\":\"" + videoUrl + "\",\"Effects\":[{\"Type\":\"Background\",\"SubType\":\"Blur\",\"Radius\":0.1},{\"Type\":\"Clip\",\"SubType\":\"RandomClip\",\"ClipDuration\":" + duration + "}]}";
videoClipArray.add(JSONObject.parseObject(videoClip));
String subtitleClip = "{\"Content\":\"" + content + "\",\"TimelineIn\":" + from + ",\"TimelineOut\":" + to + ",\"Type\":\"Text\",\"Font\":\"Alibaba PuHuiTi\",\"Alignment\":\"TopCenter\",\"Y\":0.75,\"FontSize\":55,\"FontColor\":\"#ffffff\",\"AdaptMode\":\"AutoWrap\",\"TextWidth\":0.8,\"Outline\":2,\"OutlineColour\":\"#000000\"}";
subtitleClipArray.add(JSONObject.parseObject(subtitleClip));
}
String titleTrack = "{\"SubtitleTrackClips\":[{\"Type\":\"Text\",\"Font\":\"HappyZcool-2016\",\"Content\":\""+title+"\",\"FontSize\":80,\"FontColor\":\"#ffffff\",\"Y\":0.15,\"Alignment\":\"TopCenter\",\"EffectColorStyle\":\"CS0004-000005\",\"FontFace\":{\"Bold\":true,\"Italic\":false,\"Underline\":false}}]}";
String subtitleTrack = "{\"SubtitleTrackClips\":"+subtitleClipArray+"}";
int bgMusicIndex = (int)(Math.random() * bgMusicArray.length);
String bgMusicUrl = bgMusicArray[bgMusicIndex];
String timeline = "{\"VideoTracks\":[{\"VideoTrackClips\":"+videoClipArray.toJSONString()+"}],\"AudioTracks\":[{\"AudioTrackClips\":[{\"MediaURL\":\""+inputSpeechAudio+"\"}]},{\"AudioTrackClips\":[{\"MediaURL\":\""+bgMusicUrl+"\"}]}],\"SubtitleTracks\":[" + titleTrack + "," + subtitleTrack + "]}";
//
String targetFileName = UUID.randomUUID().toString().replace("-", "");
String outputMediaUrl = "http://" + bucket + ".oss-" + regionId + ".aliyuncs.com/ice_output/" + targetFileName + ".mp4";
int width = 720;
int height = 1280;
String outputMediaConfig = "{\"MediaURL\":\"" + outputMediaUrl + "\",\"Width\":"+width+",\"Height\":"+height+"}";
SubmitMediaProducingJobRequest request = new SubmitMediaProducingJobRequest();
request.setTimeline(timeline);
request.setOutputMediaConfig(outputMediaConfig);
SubmitMediaProducingJobResponse response = iceClient.submitMediaProducingJob(request);
System.out.println("start job. jobid: " + response.getBody().getJobId() + ", outputMediaUrl: " + outputMediaUrl);
return response.getBody().getJobId();
}
}
相关文档
反馈
- 本页导读
文档反馈