康鲁杰
2025-03-25 3f3760641eb5efd3eeb18f3f183ca788dce4921d
yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/digitalhumans/DigitalHumansServiceUtil.java
@@ -58,7 +58,9 @@
    @Resource
    private ConfigApi configApi;
    @Resource
    private FileApi fileApi;
    @Async
    public void remoteHeyGemTrain(DigitalHumansTrailVO digitalHumansTrailVo){
        String origin_audio = configApi.getConfigValueByKey(HEYGEM_VOICE_DATA) + "/origin_audio";
        String temp = configApi.getConfigValueByKey(HEYGEM_FACE2FACE) + "/temp";
@@ -81,7 +83,6 @@
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 音频文件路径
        String audioFileName = modelFileName.replace(extname, ".wav");
@@ -137,8 +138,22 @@
                // 处理业务逻辑错误,更新状态和错误信息
                String referenceAudioText = responseJson.getString("reference_audio_text");
                String asrFormatAudioUrl = responseJson.getString("asr_format_audio_url");
                // 如果成功,更新状态为0(成功)
                // 如果成功,获取一帧当图片
                String picFileName = modelFileName.replace(extname, ".png");
                String pngPath = configApi.getConfigValueByKey(EASEGEN_URL) + "\\human_picture";
                try {
                    Files.createDirectories(Path.of(pngPath));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                String picFilePath = Paths.get(pngPath , picFileName).toString();
                int frameTime = 3; // 截取第 5 秒的画面
                extractFrame(modelFilePath, picFilePath, frameTime);
                byte[] fileContent = Files.readAllBytes(Paths.get(picFilePath)); // 读取文件内容
                String fileUrl = fileApi.createFile(fileContent);
                System.out.println(fileUrl);
                digitalHumansMapper.update(
                        new UpdateWrapper<DigitalHumansDO>()
                                .lambda()
@@ -146,6 +161,7 @@
                                .set(DigitalHumansDO::getStatus, 0)  // 更新字段 status 为 0
                                .set(DigitalHumansDO::getAsrFormatAudioUrl,asrFormatAudioUrl)
                                .set(DigitalHumansDO::getReferenceAudioText,referenceAudioText)
                                .set(DigitalHumansDO::getPictureUrl,fileUrl)
                );
                success = true;
            }catch (Exception e){
@@ -166,7 +182,6 @@
                }
            }
        }
    }
    /**
     * 调用 FFmpeg 提取音频
@@ -198,6 +213,41 @@
            e.printStackTrace();
        }
    }
    /**
     * 调用 FFmpeg 提取视频帧
     * @param videoPath 视频文件路径
     * @param outputImagePath 输出图片路径
     * @param frameTime 截取的时间点
     */
    public static void extractFrame(String videoPath, String outputImagePath, int frameTime) {
        ProcessBuilder processBuilder = new ProcessBuilder(
                "ffmpeg","-i", videoPath,"-ss", String.valueOf(frameTime),
                "-vframes", "1",
                "-q:v", "2",
                outputImagePath
        );
        processBuilder.redirectErrorStream(true); // 合并错误输出
        try {
            Process process = processBuilder.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            int exitCode = process.waitFor(); // 等待执行完毕
            if (exitCode == 0) {
                System.out.println("图片已成功提取到:" + outputImagePath);
            } else {
                System.out.println("FFmpeg 执行失败,错误代码:" + exitCode);
            }
        } catch (IOException | InterruptedException e) {
            System.out.println("FFmpeg 执行失败,发生异常:" + e.getMessage());
        }
    }
    public void remoteTrain(DigitalHumansTrailVO digitalHumansTrailVo){
        //训练前校验