shenrongliang
2025-04-17 536833633323d2484f03906f2ae90573db7a8c47
异步处理合成片头片尾
已修改2个文件
140 ■■■■ 文件已修改
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceImpl.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceUtil.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceImpl.java
@@ -254,71 +254,8 @@
     */
    @Override
    public CommonResult createCompositeVideo(CourseMediaSubtitlesReqVO courseMediaSubtitlesReqVO) {
        //片头地址
        String titles = courseMediaSubtitlesReqVO.getTitles();
        titles = configApi.getConfigValueByKey("easegen.url") + titles.substring(titles.lastIndexOf("/"));
        //片尾地址
        String trailer = courseMediaSubtitlesReqVO.getTrailer();
        trailer = configApi.getConfigValueByKey("easegen.url") + trailer.substring(trailer.lastIndexOf("/"));
        String videoUrl = courseMediaSubtitlesReqVO.getVideoUrl();
        String previewUrl = courseMediaSubtitlesReqVO.getPreviewUrl();
        List<String> videoUrls = new ArrayList<>();
        videoUrls.add(titles);
        if (videoUrl != null){
            videoUrl = configApi.getConfigValueByKey("easegen.url") + videoUrl.substring(videoUrl.lastIndexOf("/"));
            videoUrls.add(videoUrl);
            videoUrls.add(trailer);
        } else if (previewUrl != null) {
            previewUrl = configApi.getConfigValueByKey("easegen.url") + previewUrl.substring(previewUrl.lastIndexOf("/"));
            videoUrls.add(previewUrl);
            videoUrls.add(trailer);
        }
        //判断文件夹是否存在,如果不存在就创建
        String filePath = configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/compositeVideo/";
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        String fileListPath = configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/compositeVideo/filelist.txt";
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileListPath))) {
            for (String path : videoUrls) {
                writer.write("file '" + path + "'\n");
            }
            System.out.println("文件列表已生成:" + fileListPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //去掉updateReqVO.getName()中的空格和特殊字符
        String newFileName = courseMediaSubtitlesReqVO.getCourseName().replaceAll("[\\s\\p{Punct}]", "");
        ProcessBuilder builder = new ProcessBuilder(
                "ffmpeg", "-f", "concat", "-safe","0", "-i",fileListPath , "-c", "copy", configApi.getConfigValueByKey(HEYGEM_FACE2FACE)+"/compositeVideo/"+newFileName+".mp4"
//                q
        );
        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);
        }
        byte[] bytes = FileUtil.readBytes(FileUtil.file(configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/compositeVideo/"+newFileName+".mp4"));
        String compositeVideo = fileApi.createFile(bytes);
        CourseMediaDO courseMediaDO = new CourseMediaDO();
        courseMediaDO.setId(courseMediaSubtitlesReqVO.getId());
        courseMediaDO.setCompositeVideo(compositeVideo);
        int i = courseMediaMapper.updateById(courseMediaDO);
        if (i>0){
            return CommonResult.success("视频合成成功");
        }
        return CommonResult.error(BAD_REQUEST.getCode(),"视频合成失败");
        //异步合成
        courseMediaServiceUtil.createCompositeVideo(courseMediaSubtitlesReqVO);
        return CommonResult.success("视频合成中,请稍后查看");
    }
}
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceUtil.java
@@ -6,6 +6,7 @@
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaMegerVO;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaSubtitlesReqVO;
@@ -44,6 +45,8 @@
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
@Service
@Validated
@@ -163,7 +166,7 @@
                        newFileName2 // 输出文件名
                );
            } else if ("2".equals(scene.getHasPerson())) {
                // 当没有人像时,视频放在 cover 的下层
                // 当没有人像时,substring1放在 cover1 的下层
                builder = new ProcessBuilder(
                        "ffmpeg",
                        "-i", cover1, // 背景图
@@ -691,4 +694,70 @@
            throw new RuntimeException(e);
        }
    }
    @Async
    public CommonResult createCompositeVideo(CourseMediaSubtitlesReqVO courseMediaSubtitlesReqVO) {
        //片头地址
        String titles = courseMediaSubtitlesReqVO.getTitles();
        titles = configApi.getConfigValueByKey("easegen.url") + titles.substring(titles.lastIndexOf("/"));
        //片尾地址
        String trailer = courseMediaSubtitlesReqVO.getTrailer();
        trailer = configApi.getConfigValueByKey("easegen.url") + trailer.substring(trailer.lastIndexOf("/"));
        String videoUrl = courseMediaSubtitlesReqVO.getVideoUrl();
        String previewUrl = courseMediaSubtitlesReqVO.getPreviewUrl();
        List<String> videoUrls = new ArrayList<>();
        videoUrls.add(titles);
        if (videoUrl != null){
            videoUrl = configApi.getConfigValueByKey("easegen.url") + videoUrl.substring(videoUrl.lastIndexOf("/"));
            videoUrls.add(videoUrl);
            videoUrls.add(trailer);
        } else if (previewUrl != null) {
            previewUrl = configApi.getConfigValueByKey("easegen.url") + previewUrl.substring(previewUrl.lastIndexOf("/"));
            videoUrls.add(previewUrl);
            videoUrls.add(trailer);
        }
        //判断文件夹是否存在,如果不存在就创建
        String filePath = configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/compositeVideo/";
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        String fileListPath = configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/compositeVideo/filelist.txt";
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileListPath))) {
            for (String path : videoUrls) {
                writer.write("file '" + path + "'\n");
            }
            System.out.println("文件列表已生成:" + fileListPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //去掉updateReqVO.getName()中的空格和特殊字符
        String newFileName = courseMediaSubtitlesReqVO.getCourseName().replaceAll("[\\s\\p{Punct}]", "");
        ProcessBuilder builder = new ProcessBuilder(
                "ffmpeg", "-f", "concat", "-safe","0", "-i",fileListPath , "-c", "copy", configApi.getConfigValueByKey(HEYGEM_FACE2FACE)+"/compositeVideo/"+newFileName+".mp4"
//                q
        );
        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("最终视频已生成");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        byte[] bytes = FileUtil.readBytes(FileUtil.file(configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/compositeVideo/"+newFileName+".mp4"));
        String compositeVideo = fileApi.createFile(bytes);
        CourseMediaDO courseMediaDO = new CourseMediaDO();
        courseMediaDO.setId(courseMediaSubtitlesReqVO.getId());
        courseMediaDO.setCompositeVideo(compositeVideo);
        int i = courseMediaMapper.updateById(courseMediaDO);
        if (i>0){
            return CommonResult.success("视频合成成功");
        }
        return CommonResult.error(BAD_REQUEST.getCode(),"视频合成失败");
    }
}