@@ -0,0 +1,173 @@
package cn.iocoder.yudao.module.tik.media ;
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 org.springframework.stereotype.Component ;
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-hangzhou " ;
static final String bucket = " muye-ai-chat " ;
private Client iceClient ;
private final String accessKeyId = " LTAI5tPV9Ag3csf41GZjaLTA " ;
private final String accessKeySecret = " kDqlGeJTKw6tJtFYiaY8vQTFuVIQDs " ;
public static void main ( String [ ] args ) {
try {
BatchProduceAlignment batchProduce = new BatchProduceAlignment ( ) ;
batchProduce . initClient ( ) ;
// 文字素材
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 = 3 ;
List < String > mediaList = batchProduce . batchProduceAlignment ( title , text , videoArray , bgMusicArray , produceCount ) ;
mediaList . forEach ( System . out : : println ) ;
} catch ( Exception e ) {
System . out . println ( " Produce failed. Exception: " + e . toString ( ) ) ;
}
}
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 = accessKeyId ;
config . accessKeySecret = accessKeySecret ;
config . endpoint = " ice. " + regionId + " .aliyuncs.com " ;
config . regionId = regionId ;
iceClient = new Client ( config ) ;
}
public List < String > batchProduceAlignment ( String title , String text , String [ ] videoArray , String [ ] bgMusicArray , int produceCount ) throws Exception {
// 批量提交任务
List < String > jobIds = new ArrayList < > ( ) ;
for ( int i = 0 ; i < produceCount ; i + + ) {
String jobId = produceSingleVideo ( title , text , videoArray , bgMusicArray ) ;
jobIds . add ( jobId ) ;
}
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 ) ) {
throw new Exception ( " Produce failed. jobid: " + mediaProducingJob . getJobId ( ) ) ;
}
if ( ! " Success " . equalsIgnoreCase ( status ) ) {
allFinished = false ;
break ;
}
}
if ( allFinished ) {
break ;
}
}
return jobIds ;
}
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 ) ;
//ystem.out.println("start job. jobid: " + response.getBody().getJobId() + ", outputMediaUrl: " + outputMediaUrl);
return response . getBody ( ) . getJobId ( ) + " : " + outputMediaUrl ;
}
}