|
@@ -11,7 +11,6 @@ import org.jeecg.modules.opencv.service.IModelVideoCompositeInfoService;
|
|
import org.jeecg.modules.opencv.service.IModelVideoInfoConfigService;
|
|
import org.jeecg.modules.opencv.service.IModelVideoInfoConfigService;
|
|
import org.jeecg.modules.opencv.service.IModelVideoInfoService;
|
|
import org.jeecg.modules.opencv.service.IModelVideoInfoService;
|
|
import org.jeecg.modules.opencv.utils.ImageUtils;
|
|
import org.jeecg.modules.opencv.utils.ImageUtils;
|
|
-import org.jeecg.modules.opencv.utils.VideoProcessing;
|
|
|
|
import org.opencv.core.Core;
|
|
import org.opencv.core.Core;
|
|
import org.opencv.core.Mat;
|
|
import org.opencv.core.Mat;
|
|
import org.opencv.core.Size;
|
|
import org.opencv.core.Size;
|
|
@@ -136,7 +135,7 @@ public class FfmpegServiceImpl implements IFfmpegService {
|
|
while ((line = br.readLine()) != null) {
|
|
while ((line = br.readLine()) != null) {
|
|
result.append(line + "\n");
|
|
result.append(line + "\n");
|
|
}
|
|
}
|
|
- log.info("FFMPEG视频转换进程错误信息:" + result.toString());
|
|
|
|
|
|
+// log.info("FFMPEG视频转换进程错误信息:" + result.toString());
|
|
|
|
|
|
result = new StringBuffer();
|
|
result = new StringBuffer();
|
|
line = null;
|
|
line = null;
|
|
@@ -144,7 +143,7 @@ public class FfmpegServiceImpl implements IFfmpegService {
|
|
while ((line = br2.readLine()) != null) {
|
|
while ((line = br2.readLine()) != null) {
|
|
result.append(line + "\n");
|
|
result.append(line + "\n");
|
|
}
|
|
}
|
|
- log.info("FFMPEG视频转换进程输出内容为:" + result.toString());
|
|
|
|
|
|
+// log.info("FFMPEG视频转换进程输出内容为:" + result.toString());
|
|
} catch (IOException e2) {
|
|
} catch (IOException e2) {
|
|
e2.printStackTrace();
|
|
e2.printStackTrace();
|
|
} finally {
|
|
} finally {
|
|
@@ -317,15 +316,24 @@ public class FfmpegServiceImpl implements IFfmpegService {
|
|
String finalVideoPath = PropertiesUtils.getValue("kuaishou_config", "model_video_final_path");
|
|
String finalVideoPath = PropertiesUtils.getValue("kuaishou_config", "model_video_final_path");
|
|
|
|
|
|
String fillFilePath = LoadFileUtil.downLoadFromUrl(url, fillVideoPath);
|
|
String fillFilePath = LoadFileUtil.downLoadFromUrl(url, fillVideoPath);
|
|
|
|
+ Long current1 = System.currentTimeMillis();
|
|
|
|
+ log.info("替换视频下载完成:总时长{}毫秒", current1 - current);
|
|
String srcFilePath = LoadFileUtil.downLoadFromUrl(videoInfo.getModelVideoUrl(), srcVideoPath);
|
|
String srcFilePath = LoadFileUtil.downLoadFromUrl(videoInfo.getModelVideoUrl(), srcVideoPath);
|
|
-
|
|
|
|
|
|
+ Long current2 = System.currentTimeMillis();
|
|
|
|
+ log.info("模板文件下载完成:总时长{}毫秒", current2 - current1);
|
|
String splitSrcPath = srcVideoPath + current + File.separator;
|
|
String splitSrcPath = srcVideoPath + current + File.separator;
|
|
|
|
+ LoadFileUtil.checkFile(splitSrcPath);
|
|
String splitFillPath = fillVideoPath + current + File.separator;
|
|
String splitFillPath = fillVideoPath + current + File.separator;
|
|
|
|
+ LoadFileUtil.checkFile(splitFillPath);
|
|
String splitFinalPath = finalVideoPath + current + File.separator;
|
|
String splitFinalPath = finalVideoPath + current + File.separator;
|
|
LoadFileUtil.checkFile(splitFinalPath);
|
|
LoadFileUtil.checkFile(splitFinalPath);
|
|
//1:切分视频
|
|
//1:切分视频
|
|
- VideoProcessing.grabberVideoFramer(srcFilePath, splitSrcPath);
|
|
|
|
- VideoProcessing.grabberVideoFramer(fillFilePath, splitFillPath);
|
|
|
|
|
|
+ videoSplitToImage(srcFilePath, splitSrcPath);
|
|
|
|
+ Long current3 = System.currentTimeMillis();
|
|
|
|
+ log.info("模板文件切分完成:总时长{}毫秒", current3 - current2);
|
|
|
|
+ videoSplitToImage(fillFilePath, splitFillPath);
|
|
|
|
+ Long current4 = System.currentTimeMillis();
|
|
|
|
+ log.info("填充文件切分完成:总时长{}毫秒", current4 - current3);
|
|
ModelVideoInfoConfig config = configService.getByModelId(videoInfo.getId());
|
|
ModelVideoInfoConfig config = configService.getByModelId(videoInfo.getId());
|
|
if (null == config) {
|
|
if (null == config) {
|
|
log.error("配置文件尚未配置=>modelId:{}", videoInfo.getId());
|
|
log.error("配置文件尚未配置=>modelId:{}", videoInfo.getId());
|
|
@@ -339,13 +347,13 @@ public class FfmpegServiceImpl implements IFfmpegService {
|
|
//视频替换结束帧数
|
|
//视频替换结束帧数
|
|
int exchangeEndFrameNum = config.getFullScreenEndFrame();
|
|
int exchangeEndFrameNum = config.getFullScreenEndFrame();
|
|
//2.1 复制原始视频无变化图片
|
|
//2.1 复制原始视频无变化图片
|
|
- for (int i = 0; i < exchangeStartFrameNum; i++) {
|
|
|
|
|
|
+ for (int i = 1; i < exchangeStartFrameNum; i++) {
|
|
Mat srcNoChangeImage = Imgcodecs.imread(splitSrcPath + i + ".jpg");
|
|
Mat srcNoChangeImage = Imgcodecs.imread(splitSrcPath + i + ".jpg");
|
|
Imgcodecs.imwrite(splitFinalPath + i + ".jpg", srcNoChangeImage);
|
|
Imgcodecs.imwrite(splitFinalPath + i + ".jpg", srcNoChangeImage);
|
|
}
|
|
}
|
|
|
|
|
|
//2.2 转场动画(从fill文件夹的第一帧开始)
|
|
//2.2 转场动画(从fill文件夹的第一帧开始)
|
|
- String getImageName = splitFillPath + "0.jpg";
|
|
|
|
|
|
+ String getImageName = splitFillPath + "1.jpg";
|
|
Mat image = Imgcodecs.imread(getImageName, Imgcodecs.IMREAD_COLOR);
|
|
Mat image = Imgcodecs.imread(getImageName, Imgcodecs.IMREAD_COLOR);
|
|
//(1)径向模糊图片
|
|
//(1)径向模糊图片
|
|
Mat radialBlur = ImageUtils.radialBlur(image);
|
|
Mat radialBlur = ImageUtils.radialBlur(image);
|
|
@@ -369,7 +377,7 @@ public class FfmpegServiceImpl implements IFfmpegService {
|
|
Imgcodecs.imwrite(splitFinalPath + exchangeStartFrameNum + ".jpg", wholeImage);
|
|
Imgcodecs.imwrite(splitFinalPath + exchangeStartFrameNum + ".jpg", wholeImage);
|
|
exchangeStartFrameNum++;
|
|
exchangeStartFrameNum++;
|
|
//2.3复制填充视频无变化图片
|
|
//2.3复制填充视频无变化图片
|
|
- int checkNum = 1;
|
|
|
|
|
|
+ int checkNum = 2;
|
|
for (int i = exchangeStartFrameNum; i < exchangeEndFrameNum; i++) {
|
|
for (int i = exchangeStartFrameNum; i < exchangeEndFrameNum; i++) {
|
|
String fillImagePath = splitFillPath + checkNum + ".jpg";
|
|
String fillImagePath = splitFillPath + checkNum + ".jpg";
|
|
File file = new File(fillImagePath);
|
|
File file = new File(fillImagePath);
|
|
@@ -381,33 +389,45 @@ public class FfmpegServiceImpl implements IFfmpegService {
|
|
}
|
|
}
|
|
checkNum++;
|
|
checkNum++;
|
|
}
|
|
}
|
|
|
|
+ Long current5 = System.currentTimeMillis();
|
|
|
|
+ log.info("图片替换完成:总时长{}毫秒", current5 - current4);
|
|
//3开始合成视频
|
|
//3开始合成视频
|
|
//3.1 抽取音频文件
|
|
//3.1 抽取音频文件
|
|
String srcM4aFilePath = splitSrcPath + "src.m4a";
|
|
String srcM4aFilePath = splitSrcPath + "src.m4a";
|
|
getM4aFromMp4(srcFilePath, srcM4aFilePath);
|
|
getM4aFromMp4(srcFilePath, srcM4aFilePath);
|
|
-
|
|
|
|
|
|
+ Long current6 = System.currentTimeMillis();
|
|
|
|
+ log.info("抽取模板音频文件完成:总时长{}毫秒", current6 - current4);
|
|
String fillM4aFilePath = splitSrcPath + "fill.m4a";
|
|
String fillM4aFilePath = splitSrcPath + "fill.m4a";
|
|
getM4aFromMp4(fillFilePath, fillM4aFilePath);
|
|
getM4aFromMp4(fillFilePath, fillM4aFilePath);
|
|
|
|
+ Long current7 = System.currentTimeMillis();
|
|
|
|
+ log.info("抽取填充音频文件完成:总时长{}毫秒", current7 - current6);
|
|
//3.2 截取源模板音频文件
|
|
//3.2 截取源模板音频文件
|
|
String cutM4aFilePath = splitSrcPath + "cut.m4a";
|
|
String cutM4aFilePath = splitSrcPath + "cut.m4a";
|
|
//计算需要截取的音频时长
|
|
//计算需要截取的音频时长
|
|
String secondStr = getSecond(exchangeStartFrameNum);
|
|
String secondStr = getSecond(exchangeStartFrameNum);
|
|
cutM4a(srcM4aFilePath, cutM4aFilePath, "00:00:00.000", secondStr);
|
|
cutM4a(srcM4aFilePath, cutM4aFilePath, "00:00:00.000", secondStr);
|
|
-
|
|
|
|
|
|
+ Long current8 = System.currentTimeMillis();
|
|
|
|
+ log.info("音频文件截取完成:总时长{}毫秒", current8 - current7);
|
|
//3.3 合并两个音频文件
|
|
//3.3 合并两个音频文件
|
|
String finalM4aFilePath = splitSrcPath + "final.m4a";
|
|
String finalM4aFilePath = splitSrcPath + "final.m4a";
|
|
audioMosaic(cutM4aFilePath, fillM4aFilePath, finalM4aFilePath);
|
|
audioMosaic(cutM4aFilePath, fillM4aFilePath, finalM4aFilePath);
|
|
-
|
|
|
|
|
|
+ Long current9 = System.currentTimeMillis();
|
|
|
|
+ log.info("音频文件合成完成:总时长{}毫秒", current9 - current8);
|
|
//3.4 将最终生成的图片合成为视频
|
|
//3.4 将最终生成的图片合成为视频
|
|
String noVoiceVideoFilePath = splitSrcPath + "novoice.mp4";
|
|
String noVoiceVideoFilePath = splitSrcPath + "novoice.mp4";
|
|
mergeImageToVideo(splitFinalPath, 25, noVoiceVideoFilePath);
|
|
mergeImageToVideo(splitFinalPath, 25, noVoiceVideoFilePath);
|
|
|
|
+ Long current10 = System.currentTimeMillis();
|
|
|
|
+ log.info("图片合成视频完成:总时长{}毫秒", current10 - current9);
|
|
//3.5 合并视频和音频
|
|
//3.5 合并视频和音频
|
|
String finalVideoFilePath = splitSrcPath + "final.mp4";
|
|
String finalVideoFilePath = splitSrcPath + "final.mp4";
|
|
mergeAudioAndVideo(noVoiceVideoFilePath, finalM4aFilePath, finalVideoFilePath);
|
|
mergeAudioAndVideo(noVoiceVideoFilePath, finalM4aFilePath, finalVideoFilePath);
|
|
|
|
+ Long current11 = System.currentTimeMillis();
|
|
|
|
+ log.info("视频合成完成:总时长{}毫秒", current11 - current10);
|
|
//3.6 上传视频文件至OSS并返回url存入数据库
|
|
//3.6 上传视频文件至OSS并返回url存入数据库
|
|
InputStream inputStream = new FileInputStream(finalVideoFilePath);
|
|
InputStream inputStream = new FileInputStream(finalVideoFilePath);
|
|
String finalUrl = OSSUtils.uploadFile2OSS(inputStream, "model/final/", videoInfo.getId() + "_" + current + ".mp4");
|
|
String finalUrl = OSSUtils.uploadFile2OSS(inputStream, "model/final/", videoInfo.getId() + "_" + current + ".mp4");
|
|
- System.out.println(finalUrl);
|
|
|
|
|
|
+ Long current12 = System.currentTimeMillis();
|
|
|
|
+ log.info("文件上传oss完成:总时长{}毫秒", current12 - current11);
|
|
ModelVideoCompositeInfo compositeInfo = new ModelVideoCompositeInfo(userId, videoInfo, finalUrl);
|
|
ModelVideoCompositeInfo compositeInfo = new ModelVideoCompositeInfo(userId, videoInfo, finalUrl);
|
|
compositeInfoService.saveOrUpdate(compositeInfo);
|
|
compositeInfoService.saveOrUpdate(compositeInfo);
|
|
//删除文件
|
|
//删除文件
|
|
@@ -423,6 +443,32 @@ public class FfmpegServiceImpl implements IFfmpegService {
|
|
return null;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
+ public void videoSplitToImage(String srcFilePath, String splitSrcPath) {
|
|
|
|
+ StringBuffer command = new StringBuffer();
|
|
|
|
+ command.append(FFMPEG_PATH);
|
|
|
|
+ command.append(" -i ");
|
|
|
|
+ command.append(srcFilePath);
|
|
|
|
+ command.append(" -threads 5");
|
|
|
|
+ command.append(" -preset");
|
|
|
|
+ command.append(" ultrafast ");
|
|
|
|
+ command.append(splitSrcPath + "%d.jpg");
|
|
|
|
+ Runtime runtime = Runtime.getRuntime();
|
|
|
|
+ Process pro = null;
|
|
|
|
+ try {
|
|
|
|
+ pro = runtime.exec(new String[]{"sh", "-c", command.toString()});
|
|
|
|
+ printProcessMsg(pro);
|
|
|
|
+ int status = pro.waitFor();
|
|
|
|
+ if (status == 0) {
|
|
|
|
+ log.info("视频切分成功:{}", command.toString());
|
|
|
|
+ } else {
|
|
|
|
+ log.info("视频切分失败:{}", command.toString());
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
private void deleteFile(String splitSrcPath, String splitFillPath, String splitFinalPath, String srcFilePath, String fillFilePath) {
|
|
private void deleteFile(String splitSrcPath, String splitFillPath, String splitFinalPath, String srcFilePath, String fillFilePath) {
|
|
LoadFileUtil.delFile(splitFillPath);
|
|
LoadFileUtil.delFile(splitFillPath);
|
|
LoadFileUtil.delFile(splitSrcPath);
|
|
LoadFileUtil.delFile(splitSrcPath);
|