康鲁杰
2025-04-11 5d34fde28b22e7f020028ee8bbcd5cd2f50426da
字幕
已修改11个文件
已添加2个文件
330 ■■■■ 文件已修改
easegen-front/.env.prod 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
easegen-front/vite.config.ts 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursemedia/CourseMediaController.java 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursemedia/vo/CourseMediaEditSReqVO.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursemedia/vo/CourseMediaRespVO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursemedia/vo/CourseMediaSaveReqVO.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursemedia/vo/CourseMediaSubtitlesReqVO.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/dal/dataobject/coursemedia/CourseMediaDO.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceImpl.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceUtil.java 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/voices/VoicesServiceImpl.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/AbstractFileClient.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
easegen-front/.env.prod
@@ -1,12 +1,12 @@
# ç”Ÿäº§çŽ¯å¢ƒï¼šåªåœ¨æ‰“åŒ…æ—¶ä½¿ç”¨
NODE_ENV=production
# æœ¬åœ°å¼€å‘环境:本地启动所有项目(前端、后端、APP)时使用,不依赖外部环境
NODE_ENV=development
VITE_DEV=false
VITE_DEV=true
# è¯·æ±‚路径
VITE_BASE_URL='http://127.0.0.1:48080'
VITE_BASE_URL=''
# æ–‡ä»¶ä¸Šä¼ ç±»åž‹ï¼šserver - åŽç«¯ä¸Šä¼ ï¼Œ client - å‰ç«¯ç›´è¿žä¸Šä¼ ï¼Œä»…支持S3服务
# æ–‡ä»¶ä¸Šä¼ ç±»åž‹ï¼šserver - åŽç«¯ä¸Šä¼ ï¼Œ client - å‰ç«¯ç›´è¿žä¸Šä¼ ï¼Œä»…支持 S3 æœåŠ¡
VITE_UPLOAD_TYPE=server
# ä¸Šä¼ è·¯å¾„
VITE_UPLOAD_URL='http://127.0.0.1:48080/admin-api/infra/file/upload'
@@ -15,10 +15,10 @@
VITE_API_URL=/admin-api
# æ˜¯å¦åˆ é™¤debugger
VITE_DROP_DEBUGGER=true
VITE_DROP_DEBUGGER=false
# æ˜¯å¦åˆ é™¤console.log
VITE_DROP_CONSOLE=true
VITE_DROP_CONSOLE=false
# æ˜¯å¦sourcemap
VITE_SOURCEMAP=false
@@ -26,8 +26,8 @@
# æ‰“包路径
VITE_BASE_PATH=/
# è¾“出路径
VITE_OUT_DIR=dist-prod
# å•†åŸŽH5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
VITE_MALL_H5_DOMAIN='http://192.168.3.159:3000'
# éªŒè¯ç çš„开关
VITE_APP_CAPTCHA_ENABLE=false
easegen-front/vite.config.ts
@@ -35,10 +35,10 @@
            host: "0.0.0.0",
            open: env.VITE_OPEN === 'true',
            /* headers: {
                "Cross-Origin-Opener-Policy": "same-origin", // ä¿æŠ¤ä½ çš„æºç«™ç‚¹å…å—攻击
                "Cross-Origin-Embedder-Policy": "require-corp", // ä¿æŠ¤å—害者免受你的源站点的影响
            }, */
            // headers: {
            //     "Cross-Origin-Opener-Policy": "same-origin", // ä¿æŠ¤ä½ çš„æºç«™ç‚¹å…å—攻击
            //     "Cross-Origin-Embedder-Policy": "require-corp", // ä¿æŠ¤å—害者免受你的源站点的影响
            // },
            // æœ¬åœ°è·¨åŸŸä»£ç†. ç›®å‰æ³¨é‡Šçš„原因:暂时没有用途,server ç«¯å·²ç»æ”¯æŒè·¨åŸŸ
            // proxy: {
            //   ['/admin-api']: {
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursemedia/CourseMediaController.java
@@ -6,10 +6,7 @@
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaMegerVO;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaPageReqVO;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaRespVO;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaSaveReqVO;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.*;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.courses.vo.AppCoursesUpdateReqVO;
import cn.iocoder.yudao.module.digitalcourse.dal.dataobject.coursemedia.CourseMediaDO;
import cn.iocoder.yudao.module.digitalcourse.service.coursemedia.CourseMediaService;
@@ -114,4 +111,24 @@
        return courseMediaService.reMegerMedia(mediaMegerVO);
    }
}
    /**
     * ç”Ÿæˆå­—幕
     */
    @PostMapping("/createSubtitles")
    public CommonResult createSubtitles(@RequestBody CourseMediaSubtitlesReqVO courseMediaSubtitlesReqVO){
        return courseMediaService.createSubtitles(courseMediaSubtitlesReqVO);
    }
    /**
     * ç”Ÿæˆå¸¦å­—幕视频
     */
    @PostMapping("/createSubtitlesVideo")
    public CommonResult createSubtitlesVideo(@RequestBody CourseMediaSubtitlesReqVO courseMediaSubtitlesReqVO){
        return courseMediaService.createSubtitlesVideo(courseMediaSubtitlesReqVO);
    }
    @PutMapping("/updateSubtitles")
    public CommonResult<Boolean> updateSubtitles(@Valid @RequestBody CourseMediaEditSReqVO updateReqVO) {
        courseMediaService.updateSubtitles(updateReqVO);
        return success(true);
    }
}
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursemedia/vo/CourseMediaEditSReqVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - ä¿®æ”¹å­—幕地址 Request VO")
@Data
public class CourseMediaEditSReqVO {
    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12757")
    private Long id;
    private String subtitlesUrl;
}
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursemedia/vo/CourseMediaRespVO.java
@@ -75,4 +75,12 @@
    @Schema(description = "背景图片")
    private String thumbnail;
}
    @Schema(description = "字幕文件生成状态1合成中,2成功,3失败")
    private Integer subtitlesStatus;
    @Schema(description = "视频添加字幕状态1添加中,2成功,3失败")
    private Integer subtitlesAddStatus;
    @Schema(description = "带字幕文件的视频地址")
    private String videoUrl;
    @Schema(description = "字幕语言")
    private String lang;
}
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursemedia/vo/CourseMediaSaveReqVO.java
@@ -42,4 +42,6 @@
    @Schema(description = "背景图片")
    private String thumbnail;
}
}
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursemedia/vo/CourseMediaSubtitlesReqVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - è¯¾ç¨‹åª’体字幕 Request VO")
@Data
public class CourseMediaSubtitlesReqVO {
    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12757")
    private Long id;
    @Schema(description = "字幕文件地址")
    private String subtitlesUrl;
    @Schema(description = "字幕文件生成状态1合成中,2成功,3失败")
    private Integer subtitlesStatus;
    @Schema(description = "视频添加字幕状态1添加中,2成功,3失败")
    private Integer subtitlesAddStatus;
    @Schema(description = "带字幕文件的视频地址")
    private String videoUrl;
    private String lang;
    private String sentenceGap;
}
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/dal/dataobject/coursemedia/CourseMediaDO.java
@@ -93,4 +93,9 @@
    * é¢„估所需扣除的积分
    * */
    private Integer expectedReducePoint;
}
    private Integer subtitlesStatus;
    private Integer subtitlesAddStatus;
    private String videoUrl;
    private String lang;
}
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaService.java
@@ -2,9 +2,7 @@
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaMegerVO;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaPageReqVO;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaSaveReqVO;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.*;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.courses.vo.AppCoursesUpdateReqVO;
import cn.iocoder.yudao.module.digitalcourse.dal.dataobject.coursemedia.CourseMediaDO;
import jakarta.validation.Valid;
@@ -60,4 +58,9 @@
    CommonResult reMegerMedia(CourseMediaMegerVO updateReqVO);
}
    CommonResult createSubtitles(CourseMediaSubtitlesReqVO courseMediaSubtitlesReqVO);
    CommonResult createSubtitlesVideo(CourseMediaSubtitlesReqVO courseMediaSubtitlesReqVO);
    void updateSubtitles(CourseMediaEditSReqVO updateReqVO);
}
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceImpl.java
@@ -4,9 +4,7 @@
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
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.CourseMediaPageReqVO;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaSaveReqVO;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.*;
import cn.iocoder.yudao.module.digitalcourse.dal.dataobject.coursemedia.CourseMediaDO;
import cn.iocoder.yudao.module.digitalcourse.dal.mysql.coursemedia.CourseMediaMapper;
import cn.iocoder.yudao.module.digitalcourse.manager.MediaTaskManager;
@@ -136,6 +134,42 @@
    }
    @Override
    public CommonResult createSubtitles(CourseMediaSubtitlesReqVO courseMediaSubtitlesReqVO) {
        CourseMediaDO courseMediaDO1 = courseMediaMapper.selectOne(new QueryWrapperX<CourseMediaDO>().lambda().eq(CourseMediaDO::getId, courseMediaSubtitlesReqVO.getId()));
        if (courseMediaDO1.getSubtitlesStatus()!= null && courseMediaDO1.getSubtitlesStatus() == 1) {
            throw new RuntimeException("字幕生成中,请勿重复提交");
        }
        CourseMediaDO courseMediaDO = new CourseMediaDO();
        courseMediaDO.setId(courseMediaSubtitlesReqVO.getId());
        courseMediaDO.setSubtitlesStatus(1);
        courseMediaMapper.updateById(courseMediaDO);
        courseMediaServiceUtil.createSubtitles(courseMediaSubtitlesReqVO);
        return CommonResult.success("视频字幕生成中,请稍后查看");
    }
    @Override
    public CommonResult createSubtitlesVideo(CourseMediaSubtitlesReqVO courseMediaSubtitlesReqVO) {
        CourseMediaDO courseMediaDO1 = courseMediaMapper.selectOne(new QueryWrapperX<CourseMediaDO>().lambda().eq(CourseMediaDO::getId, courseMediaSubtitlesReqVO.getId()).eq(CourseMediaDO::getSubtitlesStatus, 2));
        if (courseMediaDO1 == null) {
            return CommonResult.error(BAD_REQUEST.getCode(), "字幕文件不存在或未生成");
        }
        CourseMediaDO courseMediaDO = new CourseMediaDO();
        courseMediaDO.setCourseId(courseMediaSubtitlesReqVO.getId());
        courseMediaDO.setSubtitlesAddStatus(1);
        courseMediaMapper.updateById(courseMediaDO);
        courseMediaServiceUtil.createSubtitlesVideo(courseMediaDO1);
        return CommonResult.success("视频添加字幕中,请稍后查看");
    }
    @Override
    public void updateSubtitles(CourseMediaEditSReqVO updateReqVO) {
        // æ ¡éªŒå­˜åœ¨
        validateCourseMediaExists(updateReqVO.getId());
        // æ›´æ–°
        CourseMediaDO updateObj = BeanUtils.toBean(updateReqVO, CourseMediaDO.class);
        updateObj.setSubtitlesStatus(2);
        courseMediaMapper.updateById(updateObj);
    }
}
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceUtil.java
@@ -3,10 +3,12 @@
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
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;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursescenecomponents.vo.AppCourseSceneComponentsMegerReqVO;
import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursescenes.vo.AppCourseScenesMegerReqVO;
import cn.iocoder.yudao.module.digitalcourse.dal.dataobject.coursemedia.CourseMediaDO;
@@ -21,6 +23,7 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
@@ -33,6 +36,7 @@
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
@@ -50,6 +54,11 @@
    static final String EASEGEN_CORE_KEY = "easegen.core.key";
    static final String SUBTITLES_URL  = "subtitles.url";
    private static final String EASEGEN_URL = "easegen.url";
    private static final String SUBTITLES = "subtitles";
    private static final String F2F = "f2f";
    private static final String HEYGEM_FACE2FACE = "heygem.face2face";
    @Resource
    private CourseMediaMapper courseMediaMapper;
@@ -74,7 +83,7 @@
     * @return
     */
    public void remoteMegerMedia(CourseMediaMegerVO updateReqVO) {
        FileUtil.clean("D:/heygem_data/face2face/temp/");
        FileUtil.clean(configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/temp/");
        CourseMediaDO courseMediaDO = courseMediaMapper.selectById(updateReqVO.getCourseMediaId());
        courseMediaDO.setStatus(1);
        courseMediaMapper.updateById(courseMediaDO);
@@ -109,15 +118,15 @@
            // æå–音频文件名(路径的最后一部分)
            String substring = configApi.getConfigValueByKey("easegen.url") + audition.substring(audition.lastIndexOf("/"));
            String fileName = audition.substring(audition.lastIndexOf('/') + 1);
            String newFileName = "D:/heygem_data/face2face/temp/" + fileName;
            String newFileName = configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/temp/" + fileName;
            // æå–视频文件名(路径的最后一部分)
            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;
            String newFileName1 = configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/temp/"+fileName1;
            //获取时间戳
            Date date = new Date();
            long timestamp = date.getTime();
            String newFileName2 = "D:/heygem_data/face2face/temp/"+timestamp+".mp4";
            String newFileName2 = configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/temp/"+timestamp+".mp4";
            //获取PPT内容
            String cover = scene.getComponents().get(1).getSrc();
            cover = configApi.getConfigValueByKey("easegen.url") + scene.getComponents().get(1).getSrc().substring(scene.getComponents().get(1).getSrc().lastIndexOf("/"));
@@ -202,7 +211,7 @@
                    objectObjectHashMap.put("chaofen", 0);
                    objectObjectHashMap.put("watermark_switch", 0);
                    objectObjectHashMap.put("pn", 1);
                    HttpResponse execute = HttpRequest.post("http://192.168.3.161:8383/easy/submit")
                    HttpResponse execute = HttpRequest.post(configApi.getConfigValueByKey(F2F) +"/easy/submit")
                            .body(JSON.toJSONString(objectObjectHashMap))
                            .execute();
                    String body = execute.body();
@@ -237,7 +246,18 @@
                    //调用查询视频结果
                    String result = getResult(code);
                    result = "D:/heygem_data/face2face/temp" + result;
                    if (result == null) {
                        retryCount++;
                        if (retryCount >= maxRetries) {
                            // è¶…过重试次数,更新状态和错误信息
                            courseMediaDO.setStatus(3); // 3 è¡¨ç¤ºåˆæˆå¤±è´¥
                            courseMediaDO.setErrorReason(truncateErrorMsg("视频合成任务失败,请联系管理员,错误信息: " + execute.getStatus()));
                            courseMediaMapper.updateById(courseMediaDO);
                            return;
                        }
                        continue; // é‡æ–°å°è¯•
                    }
                    result = configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/temp" + result;
                    videoUrls.add(result);
                    System.out.println("驱动视频名"+result);
                } catch (Exception e) {
@@ -262,7 +282,7 @@
            }
        }
        String fileListPath = "D:/heygem_data/face2face/temp/filelist.txt";
        String fileListPath = configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/temp/filelist.txt";
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileListPath))) {
            for (String path : videoUrls) {
                writer.write("file '" + path + "'\n");
@@ -294,7 +314,7 @@
            throw new RuntimeException(e);
        }
        // "D:/heygem_data/face2face/temp/"+"111111.mp4"将这个文件转成byte[]
        byte[] bytes = FileUtil.readBytes(FileUtil.file("D:/heygem_data/face2face/temp/"+"111111.mp4"));
        byte[] bytes = FileUtil.readBytes(FileUtil.file(configApi.getConfigValueByKey(HEYGEM_FACE2FACE) +"/temp/"+"111111.mp4"));
        String file = fileApi.createFile(bytes);
        // å¦‚果成功,更新状态为1(成功)
        courseMediaDO.setStatus(2);
@@ -322,7 +342,7 @@
        do {
            try {
                // è°ƒç”¨æŽ¥å£èŽ·å–ä»»åŠ¡çŠ¶æ€ï¼ˆå‡è®¾ä½¿ç”¨ Hutool çš„ HttpRequest)
                String body = HttpRequest.get("http://192.168.3.161:8383/easy/query?code=" + taskCode)
                String body = HttpRequest.get(configApi.getConfigValueByKey(F2F) + "/easy/query?code=" + taskCode)
                        .execute()
                        .body();
@@ -547,4 +567,118 @@
            ex.printStackTrace();
        }
    }
    @Async
    public void createSubtitles(CourseMediaSubtitlesReqVO courseMediaSubtitlesReqVO) {
        String subtitlesUrl = configApi.getConfigValueByKey(SUBTITLES_URL);
        CourseMediaDO courseMediaDO = courseMediaMapper.selectById(courseMediaSubtitlesReqVO.getId());
        if (courseMediaDO.getStatus()!= 2) {
            throw new RuntimeException("视频合成失败,无法生成字幕");
        }
        String previewUrl = courseMediaDO.getPreviewUrl();
        String subtitles = configApi.getConfigValueByKey(SUBTITLES);
        String extname = previewUrl.substring(previewUrl.lastIndexOf("."));
        //这个是file参数
        String modelFileName = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + extname;
        String modelFilePath = Paths.get(subtitles, modelFileName).toString();
        String substring = configApi.getConfigValueByKey(EASEGEN_URL) + previewUrl.substring(previewUrl.lastIndexOf("/"));
        try {
            Files.copy(Path.of(substring), Path.of(modelFilePath), StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        try {
            // å‘送POST请求
            HttpResponse execute = HttpRequest.get(subtitlesUrl + "/get_subtitles?file=" + modelFileName+"&lang="+courseMediaSubtitlesReqVO.getLang()+"&sentence_gap="+courseMediaSubtitlesReqVO.getSentenceGap()).execute();
            String body = execute.body();
            // æ£€æŸ¥å“åº”状态码是否成功
            if (execute.getStatus() != 200) {
                courseMediaMapper.update(new UpdateWrapper<CourseMediaDO>().lambda().eq(CourseMediaDO::getId, courseMediaSubtitlesReqVO.getId()).set(CourseMediaDO::getSubtitlesStatus, 3));
                return;
            }
            // è§£æžå“åº”,检查是否有错误信息
            JSONObject responseJson = JSON.parseObject(body);
            String final_video_path = responseJson.getString("subtitle_file");
            //获取文件名
            int index1 = final_video_path.lastIndexOf('/');
            int index2 = final_video_path.lastIndexOf('\\');
            int lastIndex = Math.max(index1, index2); // å–最大一个
            String fileName = final_video_path.substring(lastIndex + 1);
            byte[] content = Files.readAllBytes(Paths.get(final_video_path));
            String fileUrl = fileApi.createFile(fileName, null, content);
            courseMediaMapper.update(
                    new UpdateWrapper<CourseMediaDO>()
                            .lambda()
                            .eq(CourseMediaDO::getId, courseMediaSubtitlesReqVO.getId())  // æ¡ä»¶ï¼šcode ç­‰äºŽä¼ å…¥çš„值
                            .set(CourseMediaDO::getSubtitlesUrl, fileUrl)
                            .set(CourseMediaDO::getLang, courseMediaSubtitlesReqVO.getLang())
                            .set(CourseMediaDO::getSubtitlesStatus,2)
            );
            FileUtil.del(modelFilePath);
            FileUtil.del(final_video_path);
            // å¤„理业务逻辑错误,更新状态和错误信息
        } catch (HttpException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    @Async
    public void createSubtitlesVideo(CourseMediaDO courseMediaDO) {
        String subtitlesUrl1 = configApi.getConfigValueByKey(SUBTITLES_URL);
        String previewUrl = courseMediaDO.getPreviewUrl();
        String subtitlesUrl = courseMediaDO.getSubtitlesUrl();
        String subtitles = configApi.getConfigValueByKey(SUBTITLES);
        String extname = previewUrl.substring(previewUrl.lastIndexOf("."));
        String subtitlesExtname = subtitlesUrl.substring(subtitlesUrl.lastIndexOf("."));
        //这个是file参数
        String yyyyMMddHHmmssSSS = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
        String modelFileName = yyyyMMddHHmmssSSS + extname;
        String subtitlesFileName = yyyyMMddHHmmssSSS + subtitlesExtname;
        String modelFilePath = Paths.get(subtitles, modelFileName).toString();
        String subtitlesFilePath = Paths.get(subtitles, subtitlesFileName).toString();
        String substring = configApi.getConfigValueByKey(EASEGEN_URL) + previewUrl.substring(previewUrl.lastIndexOf("/"));
        String subtitlesSubstring = configApi.getConfigValueByKey(EASEGEN_URL) + subtitlesUrl.substring(subtitlesUrl.lastIndexOf("/"));
        try {
            Files.copy(Path.of(substring), Path.of(modelFilePath), StandardCopyOption.REPLACE_EXISTING);
            Files.copy(Path.of(subtitlesSubstring), Path.of(subtitlesFilePath), StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //modelFileName æ˜¯è§†é¢‘路径,subtitlesFileName æ˜¯å­—幕路径
        try {
            // å‘送POST请求
            HttpResponse execute = HttpRequest.get(subtitlesUrl1 + "/add_subtitles?file=" + modelFileName+"&lang="+courseMediaDO.getLang()+"&srt="+subtitlesFileName).execute();
            String body = execute.body();
            // æ£€æŸ¥å“åº”状态码是否成功
            if (execute.getStatus() != 200) {
                courseMediaMapper.update(new UpdateWrapper<CourseMediaDO>().lambda().eq(CourseMediaDO::getId, courseMediaDO.getId()).set(CourseMediaDO::getSubtitlesAddStatus, 3));
                return;
            }
            // è§£æžå“åº”,检查是否有错误信息
            JSONObject responseJson = JSON.parseObject(body);
            String final_video_path = responseJson.getString("subtitled_file");
            //获取文件名
            int index1 = final_video_path.lastIndexOf('/');
            int index2 = final_video_path.lastIndexOf('\\');
            int lastIndex = Math.max(index1, index2); // å–最大一个
            String fileName = final_video_path.substring(lastIndex + 1);
            byte[] content = Files.readAllBytes(Paths.get(final_video_path));
            String fileUrl = fileApi.createFile(fileName, null, content);
            courseMediaMapper.update(
                    new UpdateWrapper<CourseMediaDO>()
                            .lambda()
                            .eq(CourseMediaDO::getId, courseMediaDO.getId())  // æ¡ä»¶ï¼šcode ç­‰äºŽä¼ å…¥çš„值
                            .set(CourseMediaDO::getVideoUrl, fileUrl)
                            .set(CourseMediaDO::getSubtitlesAddStatus,2)
            );
            FileUtil.del(final_video_path);
            // å¤„理业务逻辑错误,更新状态和错误信息
        } catch (HttpException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/voices/VoicesServiceImpl.java
@@ -137,6 +137,7 @@
    @Resource
    private DigitalHumansMapper digitalHumansMapper;
    private static final String EASEGEN_URL = "easegen.url";
    private static final String HEYGEM_CORE_URL = "heygem.core.url";
    @Override
    public String audition(AuditionVO auditionVO) {
        DigitalHumansDO digitalHumansDO = digitalHumansMapper.selectById(auditionVO.getHumanId());
@@ -152,7 +153,9 @@
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        HttpResponse execute = HttpRequest.post("http://192.168.3.161:18180/v1/invoke")
        String configValueByKey = configApi.getConfigValueByKey(HEYGEM_CORE_URL);
        String url = configValueByKey + "/v1/invoke";
        HttpResponse execute = HttpRequest.post(url)
                .body(jsonString)
                .execute();
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/AbstractFileClient.java
@@ -63,7 +63,7 @@
     * @return URL è®¿é—®åœ°å€
     */
    protected String formatFileUrl(String domain, String path) {
        return StrUtil.format("{}/admin-api/infra/file/{}/get/{}", domain, getId(), path);
        return StrUtil.format("/admin-api/infra/file/{}/get/{}", getId(), path);
    }
}