| | |
| | | package cn.iocoder.yudao.module.digitalcourse.service.coursemedia; |
| | | |
| | | import cn.hutool.core.io.FileUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | |
| | | import cn.iocoder.yudao.module.digitalcourse.manager.MediaTaskManager; |
| | | import cn.iocoder.yudao.module.digitalcourse.model.MediaTask; |
| | | import cn.iocoder.yudao.module.infra.api.config.ConfigApi; |
| | | import cn.iocoder.yudao.module.infra.api.file.FileApi; |
| | | import com.alibaba.fastjson.JSON; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | import java.io.*; |
| | | import java.time.LocalDateTime; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.module.digitalcourse.enums.ErrorCodeConstants.COURSE_MEDIA_NOT_EXISTS; |
| | | |
| | |
| | | |
| | | @Resource |
| | | private CourseMediaServiceUtil courseMediaServiceUtil; |
| | | |
| | | @Resource |
| | | private FileApi fileApi; |
| | | |
| | | @Override |
| | | public Long createCourseMedia(CourseMediaSaveReqVO createReqVO) { |
| | |
| | | updateObj.setSubtitlesStatus(2); |
| | | courseMediaMapper.updateById(updateObj); |
| | | } |
| | | |
| | | /** |
| | | * 上传片头片尾 |
| | | * @param courseMediaSubtitlesReqVO |
| | | * @return |
| | | */ |
| | | @Override |
| | | public CommonResult createTrailer(CourseMediaSubtitlesReqVO courseMediaSubtitlesReqVO) { |
| | | CourseMediaDO courseMediaDO = new CourseMediaDO(); |
| | | courseMediaDO.setId(courseMediaSubtitlesReqVO.getId()); |
| | | courseMediaDO.setTrailer(courseMediaSubtitlesReqVO.getTrailer()); |
| | | courseMediaDO.setTitles(courseMediaSubtitlesReqVO.getTitles()); |
| | | int i = courseMediaMapper.updateById(courseMediaDO); |
| | | if (i>0){ |
| | | return CommonResult.success("片头片尾上传成功"); |
| | | } |
| | | return CommonResult.error(BAD_REQUEST.getCode(),"片头片尾上传失败"); |
| | | } |
| | | |
| | | /** |
| | | * 合成片头片尾视频 |
| | | * @param courseMediaSubtitlesReqVO |
| | | * @return |
| | | */ |
| | | @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(),"视频合成失败"); |
| | | } |
| | | } |