| | |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.io.*; |
| | | import java.math.BigDecimal; |
| | | import java.math.BigInteger; |
| | | import java.math.RoundingMode; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Path; |
| | | import java.nio.file.StandardCopyOption; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.stream.Collectors; |
| | | |
| | |
| | | AuditionVO auditionVO = new AuditionVO(); |
| | | auditionVO.setHumanId(String.valueOf(digitalHumansDO.getId())); |
| | | for (AppCourseScenesMegerReqVO scene : scenes) { |
| | | |
| | | //TODO 先判断是否有备注内容 |
| | | auditionVO.setText(scene.getBackground().getPptRemark()); |
| | | String audition = serviceImpl.audition(auditionVO); |
| | | // 提取音频文件名(路径的最后一部分) |
| | |
| | | String substring1 = configApi.getConfigValueByKey("easegen.url") + digitalHumansDO.getFixVideoUrl().substring(digitalHumansDO.getFixVideoUrl().lastIndexOf("/")); |
| | | String fileName1 = digitalHumansDO.getFixVideoUrl().substring(digitalHumansDO.getFixVideoUrl().lastIndexOf('/') + 1); |
| | | String newFileName1 = "D:/heygem_data/face2face/temp/" + fileName1; |
| | | //获取时间戳 |
| | | Date date = new Date(); |
| | | long timestamp = date.getTime(); |
| | | String newFileName2 = "D:/heygem_data/face2face/temp/"+timestamp+".mp4"; |
| | | //获取PPT内容 |
| | | String cover = scene.getComponents().get(1).getCover(); |
| | | String cover = scene.getComponents().get(1).getSrc(); |
| | | cover = configApi.getConfigValueByKey("easegen.url") + scene.getComponents().get(1).getSrc().substring(scene.getComponents().get(1).getSrc().lastIndexOf("/")); |
| | | |
| | | //获取背景 |
| | | String cover1 = scene.getBackground().getCover(); |
| | | cover1 = configApi.getConfigValueByKey("easegen.url") + scene.getBackground().getCover().substring(scene.getBackground().getCover().lastIndexOf("/")); |
| | | // 去掉扩展名 |
| | | int dotIndex = fileName1.lastIndexOf('.'); |
| | | String substring2 = fileName1.substring(0, dotIndex); |
| | | // 合成ppt背景,视频,模板 |
| | | //ffmpeg -i 2.png -i 1.mp4 -filter_complex "[0:v]scale=w=ceil(iw/2)*2:h=ceil(ih/2)*2[bg];[1:v]scale=iw/2:ih/2[v1];[bg][v1]overlay=x=0:y=H-h" output.mp4 |
| | | ProcessBuilder builder = new ProcessBuilder( |
| | | "ffmpeg", "-i", cover1,"-i",cover,"-i",substring1,"-filter_complex","[0:v]scale=",scene.getBackground().getWidth().toString(),":",scene.getBackground().getHeight().toString(),"[bg];[1:v]scale=",scene.getComponents().get(1).getWidth().toString(),":",scene.getComponents().get(1).getHeight().toString(),"[v1];[bg][v1]overlay=x=",scene.getComponents().get(1).getMarginLeft().toString(),":y=",scene.getComponents().get(1).getTop().toString(),"[img];[2:v]scale=",scene.getComponents().get(0).getWidth().toString(),":",scene.getComponents().get(0).getHeight().toString(),"[v2];[img][v2]overlay=x=",scene.getComponents().get(0).getMarginLeft().toString(),":y=",scene.getComponents().get(0).getTop().toString(),newFileName1 |
| | | "ffmpeg", |
| | | "-i", cover1, |
| | | "-i", cover, |
| | | "-i", substring1, |
| | | "-filter_complex", |
| | | "[0:v]scale=" + Math.round(scene.getBackground().getWidth()) + ":" + Math.round(scene.getBackground().getHeight()) + "[bg];" + |
| | | "[1:v]scale=" + Math.round(scene.getComponents().get(1).getWidth()) + ":" + Math.round(scene.getComponents().get(1).getHeight()) + "[v1];" + |
| | | "[bg][v1]overlay=x=" + Math.round(scene.getComponents().get(1).getMarginLeft()) + ":y=" + Math.round(scene.getComponents().get(1).getTop()) + "[img];" + |
| | | "[2:v]scale=" + Math.round(scene.getComponents().get(0).getWidth()) + ":" + Math.round(scene.getComponents().get(0).getHeight()) + "[v2];" + |
| | | "[img][v2]overlay=x=" + Math.round(scene.getComponents().get(0).getMarginLeft()) + ":y=" + Math.round(scene.getComponents().get(0).getTop()), |
| | | newFileName2 |
| | | ); |
| | | System.out.println(newFileName2); |
| | | builder.redirectErrorStream(true); |
| | | Process process = null; |
| | | try { |
| | | process = builder.start(); |
| | | // 读取 FFmpeg 输出(可选) |
| | | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); |
| | | System.out.println(builder.command()); |
| | | String line; |
| | | while ((line = reader.readLine()) != null) { |
| | | System.out.println(line); |
| | | } |
| | | |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | |
| | | // 读取 FFmpeg 输出(可选) |
| | | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); |
| | | try { |
| | | Files.copy(Path.of(substring), Path.of(newFileName), StandardCopyOption.REPLACE_EXISTING); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | |
| | | //最大重试次数 |
| | | int maxRetries = 3; |
| | | // 当前重试次数 |
| | |
| | | HashMap<String, Object> objectObjectHashMap = new HashMap<>(); |
| | | //音频路径 |
| | | objectObjectHashMap.put("audio_url", fileName); |
| | | //视频路径(无声) |
| | | objectObjectHashMap.put("video_url", fileName1); |
| | | //视频路径 |
| | | objectObjectHashMap.put("video_url",timestamp+".mp4"); |
| | | //唯一key(用于查询) |
| | | String code = RandomUtil.randomString(32); |
| | | //固定值 |
| | |
| | | String result = getResult(code); |
| | | result = "D:/heygem_data/face2face/temp" + result; |
| | | videoUrls.add(result); |
| | | System.out.println("驱动视频名"+result); |
| | | // 如果成功,更新状态为1(成功) |
| | | courseMediaDO.setStatus(1); |
| | | courseMediaMapper.updateById(courseMediaDO); |
| | | success = true; |
| | | } catch (Exception e) { |
| | | retryCount++; |
| | | if (retryCount >= maxRetries) { |
| | |
| | | break; |
| | | } |
| | | } |
| | | success = true; |
| | | } |
| | | |
| | | } |
| | | String fileListPath = "D:/heygem_data/face2face/temp/filelist.txt"; |
| | | try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileListPath))) { |
| | |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | //去掉updateReqVO.getName()中的空格和特殊字符 |
| | | String newFileName = updateReqVO.getName().replaceAll("[\\s\\p{Punct}]", ""); |
| | | ProcessBuilder builder = new ProcessBuilder( |
| | | "ffmpeg", "-f", "concat", "-safe","0", "-i", "DD:/heygem_data/face2face/temp/filelist.txt", "-c", "copy", "D:/heygem_data/face2face/temp/生成视频.mp4" |
| | | "ffmpeg", "-f", "concat", "-safe","0", "-i",fileListPath , "-c", "copy", "D:/heygem_data/face2face/temp/"+"111111.mp4" |
| | | ); |
| | | builder.redirectErrorStream(true); |
| | | Process process = null; |
| | | try { |
| | | process = builder.start(); |
| | | // 读取 FFmpeg 输出(可选) |
| | | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); |
| | | System.out.println(builder.command()); |
| | | System.out.println("最终视频已生成"); |
| | | String line; |
| | | while ((line = reader.readLine()) != null) { |
| | | System.out.println(line); |
| | | } |
| | | |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | |
| | | |
| | | } |
| | | |
| | | // 四舍五入方法 |
| | | private static int round(double value) { |
| | | return BigDecimal.valueOf(value) |
| | | .setScale(0, RoundingMode.HALF_UP) |
| | | .intValue(); |
| | | } |
| | | |
| | | public String getResult(String taskCode) { |
| | | // 使用 do-while 循环轮询任务状态 |
| | | // 定义变量存储返回结果 |