|
|
@@ -19,7 +19,6 @@ import com.tzld.supply.model.param.FFmpeg.VideoTimeCutParam;
|
|
|
import com.tzld.supply.model.param.FFmpeg.VideoUrlsParam;
|
|
|
import com.tzld.supply.model.po.supply.spider.*;
|
|
|
import com.tzld.supply.util.AliOssFileTool;
|
|
|
-import com.tzld.supply.util.CdnUtil;
|
|
|
import com.tzld.supply.util.DateUtils;
|
|
|
import com.tzld.supply.util.DistributedIdGenerator;
|
|
|
import com.xxl.job.core.biz.model.ReturnT;
|
|
|
@@ -167,20 +166,14 @@ public class VideoGenerateJob {
|
|
|
for (SpiderContentMedia image : imageList) {
|
|
|
// 现仅一种效果,后更改为多种效果随机
|
|
|
String outputVideoName = String.format("%s_%d.mp4", produceVideo.getContentId(), System.currentTimeMillis());
|
|
|
- String command = String.format("ffmpeg -loop 1 -i %s -t 3 -r 25 -filter_complex " +
|
|
|
- "\"[0:v]scale=720:1280:force_original_aspect_ratio=increase,crop=720:1280,gblur=sigma=5[bg];" +
|
|
|
- "[0:v]scale=720:1280:force_original_aspect_ratio=decrease,pad=720:1280:(ow-iw)/2:(oh-ih)/2:color=black@0[fg];" +
|
|
|
- "[fg]zoompan=z='min(1.00+0.000266*on,1.02)':d=1:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':s=720x1280[fg_anim];" +
|
|
|
- "[bg][fg_anim]overlay=0:0:format=auto\" " +
|
|
|
- "-c:v libx264 -pix_fmt yuv420p -movflags +faststart \"%s\"",
|
|
|
- CdnUtil.getOssHttpUrl(image.getOssKey()), outputVideoName);
|
|
|
+ String command = randomImageToVideoAnimation(image.getOssKey(), outputVideoName);
|
|
|
CommandParam commandParam = CommandParam.builder()
|
|
|
.ffmpegCommand(command)
|
|
|
.outputFile(outputVideoName)
|
|
|
.outputType("video")
|
|
|
.build();
|
|
|
String commandResponseData = ffmpegApiService.command(commandParam);
|
|
|
- String fileName = String.format("supply/material/video/%s", outputVideoName);
|
|
|
+ String fileName = String.format("supply/produce/material/video/%s", outputVideoName);
|
|
|
String imageToVideoOssUrl = AliOssFileTool.downloadAndSaveInOSS(fileName, commandResponseData, "video/mp4");
|
|
|
|
|
|
// 获取视频信息
|
|
|
@@ -191,6 +184,53 @@ public class VideoGenerateJob {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private String randomImageToVideoAnimation(String imageUrl, String outputVideoName) {
|
|
|
+ String command;
|
|
|
+ switch (new Random().nextInt(2)) {
|
|
|
+ // 放大
|
|
|
+ case 0:
|
|
|
+ command = String.format("ffmpeg -loop 1 -i %s -filter_complex " +
|
|
|
+ "\"[0:v]scale=720:1280:force_original_aspect_ratio=increase,boxblur=40:40,crop=720:1280[bg];" +
|
|
|
+ "[0:v]scale=720:1280:force_original_aspect_ratio=decrease,setsar=1[fg];" +
|
|
|
+ "[bg][fg]overlay=(W-w)/2:(H-h)/2,format=yuv420p[base];" +
|
|
|
+ "[base]zoompan=z='min(zoom+0.003,1.3)':d=75:x='(iw/2)-(iw/zoom/2)':y='(ih/2)-(ih/zoom/2)':s=720x1280:fps=25[zoom]\" " +
|
|
|
+ "-map \"[zoom]\" -t 3 -y \"%s\"",
|
|
|
+ imageUrl, outputVideoName);
|
|
|
+ break;
|
|
|
+ // 平移
|
|
|
+ case 1:
|
|
|
+ // 生成随机方向
|
|
|
+ String[][] directions = {
|
|
|
+ {"0", "0", "(W-w)", "(H-h)"}, // 左上 -> 右下
|
|
|
+ {"(W-w)", "(H-h)", "0", "0"}, // 右下 -> 左上
|
|
|
+ {"0", "(H-h)", "(W-w)", "0"}, // 左下 -> 右上
|
|
|
+ {"(W-w)", "0", "0", "(H-h)"} // 右上 -> 左下
|
|
|
+ };
|
|
|
+ Random rand = new Random();
|
|
|
+ int index = rand.nextInt(directions.length);
|
|
|
+ String[] dir = directions[index];
|
|
|
+ String xExpr = String.format("x='%s + (%s-%s)*t/%d'", dir[0], dir[2], dir[0], 3);
|
|
|
+ String yExpr = String.format("y='%s + (%s-%s)*t/%d'", dir[1], dir[3], dir[1], 3);
|
|
|
+ // 构造 FFmpeg 命令
|
|
|
+ command = String.format("ffmpeg -y -loop 1 -i %s -filter_complex" +
|
|
|
+ "\"[0:v]scale=720:1280:force_original_aspect_ratio=increase,boxblur=40:40,crop=720:1280[bg];" +
|
|
|
+ "[0:v]scale=720:1280:force_original_aspect_ratio=decrease,setsar=1[fg];" +
|
|
|
+ "[bg][fg]overlay=" + xExpr + ":" + yExpr + ",format=yuv420p\"" +
|
|
|
+ "-t3 %s", imageUrl, outputVideoName);
|
|
|
+ break;
|
|
|
+ // 背景模糊
|
|
|
+ default:
|
|
|
+ command = String.format("ffmpeg -loop 1 -i %s -t 3 -r 25 -filter_complex " +
|
|
|
+ "\"[0:v]scale=720:1280:force_original_aspect_ratio=increase,crop=720:1280,gblur=sigma=5[bg];" +
|
|
|
+ "[0:v]scale=720:1280:force_original_aspect_ratio=decrease,pad=720:1280:(ow-iw)/2:(oh-ih)/2:color=black@0[fg];" +
|
|
|
+ "[fg]zoompan=z='min(1.00+0.000266*on,1.02)':d=1:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':s=720x1280[fg_anim];" +
|
|
|
+ "[bg][fg_anim]overlay=0:0:format=auto\" " +
|
|
|
+ "-c:v libx264 -pix_fmt yuv420p -movflags +faststart \"%s\"",
|
|
|
+ imageUrl, outputVideoName);
|
|
|
+ }
|
|
|
+ return command;
|
|
|
+ }
|
|
|
+
|
|
|
private MediaInfo getMediaInfo(String videoUrl) {
|
|
|
String mediaInfo = ffmpegApiService.videoInfo(new VideoInfoParam(videoUrl));
|
|
|
return JSONObject.parseObject(mediaInfo, MediaInfo.class);
|
|
|
@@ -234,7 +274,7 @@ public class VideoGenerateJob {
|
|
|
.build();
|
|
|
lastEndTime = endTime;
|
|
|
String videoCutUrl = ffmpegApiService.timeCutVideo(timeCutParam);
|
|
|
- String fileName = String.format("supply/material/video/%s_%d.mp4", produceVideo.getContentId(), System.currentTimeMillis());
|
|
|
+ String fileName = String.format("supply/produce/material/video/%s_%d.mp4", produceVideo.getContentId(), System.currentTimeMillis());
|
|
|
String videoCutOssUrl = AliOssFileTool.downloadAndSaveInOSS(fileName, videoCutUrl, "video/mp4");
|
|
|
// 获取视频信息
|
|
|
MediaInfo mediaInfo = getMediaInfo(videoCutOssUrl);
|
|
|
@@ -334,7 +374,7 @@ public class VideoGenerateJob {
|
|
|
.outputType("video")
|
|
|
.build();
|
|
|
String commandResponseData = ffmpegApiService.command(commandParam);
|
|
|
- String fileName = String.format("supply/video/%s", videoName);
|
|
|
+ String fileName = String.format("supply/produce/video/%s", videoName);
|
|
|
String finalVideoUrl = AliOssFileTool.downloadAndSaveInOSS(fileName, commandResponseData, "video/mp4");
|
|
|
// 更新视频地址
|
|
|
produceVideo.setUrl(finalVideoUrl);
|