easegen-front/src/views/chooseTemplate/index.vue
@@ -1566,14 +1566,15 @@ warningStrArr.push( `åºæ¯<span style="color: red; font-weight: bold;">${i + 1}</span>æ ææç壿å 容` ) } else { //夿å»é¤æ ç¾åçå 容é¿åº¦æ¯å¦è¶ è¿2000å if (plainText.length > 2000) { warningStrArr.push( `åºæ¯<span style="color: red; font-weight: bold;">${i + 1}</span>壿å å®¹è¶ è¿2000åï¼è¯·åå°ææååºæ¯` ) } } // else { // //夿å»é¤æ ç¾åçå 容é¿åº¦æ¯å¦è¶ è¿2000å // if (plainText.length > 2000) { // warningStrArr.push( // `åºæ¯<span style="color: red; font-weight: bold;">${i + 1}</span>壿å å®¹è¶ è¿2000åï¼è¯·åå°ææååºæ¯` // ) // } // } } } easegen-front/src/views/digitalcourse/digitalhumans/DigitalHumansForm.vue
@@ -47,13 +47,6 @@ <el-form-item v-if="formData.useModel == 2" :label="t('digitalhumans.video')" prop="videoUrl"> <!-- 忬èªå¸¦çè§é¢ä¸ä¼ --> <UploadFile v-if="!(formData.videoUrl || formData.fixVideoUrl)" v-model="formData.videoUrl" :fileType="['mp4','mov']" :limit="1" @on-success="handleFileSuccess('videoUrl', $event)"/> <!-- åææ·»å çå»é¤ç»¿å¹ç --> <!-- <div v-if="!(formData.videoUrl || formData.fixVideoUrl)" > <CES2 @start="StartCes" @Thnd="End" msg="Welcome to Your Vue.js App"/> <div style="color: red;" v-show="isUploading" > å½åæ£å¨å¤çå¹¶ä¸ä¼ ä¸ï¼è¯·èå¿çå¾ ... </div> </div> --> <!-- åè§é¢ææ¾å¨ --> <!-- <video-player v-if="formData.videoUrl || formData.fixVideoUrl" :property="videoProperty"/> --> <!-- æ°çè§é¢ææ¾å¨ --> @@ -105,7 +98,6 @@ import {VideoPlayerProperty} from "@/components/DiyEditor/components/mobile/VideoPlayer/config"; import { useUpload } from '@/components/UploadFile/src/useUpload' import { el } from 'element-plus/es/locale'; import CES2 from './CES2.vue' import { any } from 'vue-types'; const { t } = useI18n() // å½é å easegen-front/src/views/digitalcourse/digitalhumans/LookDigitalHumansForm.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,271 @@ <template> <Dialog :title="dialogTitle" v-model="dialogVisible"> <el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px" v-loading="formLoading" > <el-form-item :label="t('digitalhumans.name')" prop="name"> <el-input v-model="formData.name" :placeholder="t('common.inputText') + t('digitalhumans.name')" /> </el-form-item> <el-form-item :label="t('digitalhumans.code')" prop="code" v-if="false" > // å½åæ°å人è§é¢çç¼ç ç±»å <el-input v-model="formData.code" :placeholder="t('common.inputText') + t('digitalhumans.code')" /> </el-form-item> <el-form-item :label="t('digitalhumans.gender')" prop="gender"> <el-select v-model="formData.gender" :placeholder="t('common.selectText')+t('digitalhumans.gender')"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> <el-form-item :label="t('digitalhumans.useModel')" prop="useModel" v-if="false" > //æ°å人模å¼éæ©æ¡ <el-select v-model="formData.useModel" :placeholder="t('common.selectText')+t('digitalhumans.useModel')"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.USE_MODEL)" :key="dict.value" :label="dict.label" :value="Number(dict.value)" /> </el-select> </el-form-item> <el-form-item label="èæ¯æ ·å¼" prop="isTransparent"> <el-select v-model="formData.isTransparent" placeholder="è¯·éæ©æ¯å¦å»é¤èæ¯"> <el-option value="1" label="éæèæ¯"/> <el-option value="2" label="绿å¹èæ¯"/> </el-select> </el-form-item> <el-form-item v-if="formData.useModel == 1" :label="t('digitalhumans.picture')" prop="pictureUrl"> <UploadImg v-if="formData" v-model="formData.fixPictureUrl" /> <UploadImg v-else v-model="formData.pictureUrl" /> </el-form-item> <!-- <el-form-item v-if="formData.useModel == 2" :label="t('digitalhumans.video')" prop="videoUrl"> --> <el-form-item v-if="false" :label="t('digitalhumans.video')" prop="videoUrl"> <!-- 忬èªå¸¦çè§é¢ä¸ä¼ --> <UploadFile v-if="!(formData.videoUrl || formData.fixVideoUrl)" v-model="formData.videoUrl" :fileType="['mp4','mov']" :limit="1" @on-success="handleFileSuccess('videoUrl', $event)"/> <!-- åè§é¢ææ¾å¨ --> <!-- <video-player v-if="formData.videoUrl || formData.fixVideoUrl" :property="videoProperty"/> --> <!-- æ°çè§é¢ææ¾å¨ --> <VideoPlayerMov v-if="formData.videoUrl || formData.fixVideoUrl" :property="videoProperty"/> </el-form-item> <!-- <el-form-item :label="æ 徿 è¯" prop="matting"> <el-select v-model="formData.matting" :placeholder="è¯·éæ©æ 徿 è¯"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.DIGITALCOURSE_DIGITALHUMAN_MATTING)" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item>--> <el-form-item :label="t('digitalhumans.posture')" prop="posture"> <el-select v-model="formData.posture" :placeholder="t('common.selectText') + t('digitalhumans.posture')"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.DIGITALCOURSE_DIGITALHUMAN_POSTURE)" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> <el-form-item :label="t('digitalhumans.type')" prop="type"> <el-select v-model="formData.type" :placeholder="t('common.selectText') + t('digitalhumans.type')"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.DIGITALCOURSE_DIGITALHUMAN_TYPE)" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> </el-form> <template #footer> <el-button @click="submitForm" type="primary" :disabled="formLoading" :loading="isUploading" >{{t('common.ok')}}</el-button> <el-button @click="dialogVisible = false">{{t('common.cancel')}}</el-button> </template> </Dialog> </template> <script setup lang="ts"> import { getIntDictOptions, DICT_TYPE } from '@/utils/dict' import * as DigitalHumansApi from '@/api/digitalcourse/digitalhumans' import VideoPlayer from "@/components/DiyEditor/components/mobile/VideoPlayer/index.vue"; import VideoPlayerMov from "@/components/DiyEditor/components/mobile/VideoPlayer_mov/index.vue"; import {DiyComponent} from "@/components/DiyEditor/util"; import {VideoPlayerProperty} from "@/components/DiyEditor/components/mobile/VideoPlayer/config"; import { useUpload } from '@/components/UploadFile/src/useUpload' import { el } from 'element-plus/es/locale'; import { any } from 'vue-types'; const { t } = useI18n() // å½é å const message = useMessage() // æ¶æ¯å¼¹çª const { uploadUrl, httpRequest } = useUpload() //ä¸ä¼ æ¹æ³ const dialogVisible = ref(false) // å¼¹çªçæ¯å¦å±ç¤º const dialogTitle = ref('') // å¼¹çªçæ é¢ const formLoading = ref(false) // 表åçå è½½ä¸ï¼1ï¼ä¿®æ¹æ¶çæ°æ®å è½½ï¼2ï¼æäº¤çæé®ç¦ç¨ const formType = ref('') // 表åçç±»åï¼create - æ°å¢ï¼update - ä¿®æ¹ const formData = ref({ id: undefined, expireStatus: undefined, finishTime: undefined, gender: undefined, matting: undefined, name: undefined, code: undefined, pictureUrl: undefined, posture: undefined, snapshotHeight: undefined, snapshotUrl: undefined, snapshotWidth: undefined, type: undefined, useGeneralModel: undefined, useModel: undefined, status: undefined, isTransparent: undefined, }) // å½åæ¯å¦æ£å¨ä¸ä¼ è§é¢ const isUploading = ref(false) const videoProperty = { videoUrl: '', posterUrl: '', autoplay: false, style: { bgType: 'color', bgColor: '#fff', marginBottom: 8, height: 300 } } as DiyComponent<VideoPlayerProperty> watch(()=> formData.value.videoUrl,(newVal,oldValue)=>{ if (newVal && newVal.length > 0){ videoProperty.videoUrl = formData.value.fixVideoUrl || newVal } }) const formRules = reactive({ gender: [{ required: true, message: 'æ§å«ä¸è½ä¸ºç©º', trigger: 'change' }], name: [{ required: true, message: 'åç§°ä¸è½ä¸ºç©º', trigger: 'blur' }], pictureUrl: [{ required: true, message: 'å¾çURLä¸è½ä¸ºç©º', trigger: 'blur' }], posture: [{ required: true, message: 'å§¿å¿ä¸è½ä¸ºç©º', trigger: 'change' }], snapshotHeight: [{ required: true, message: 'å¿«ç §é«åº¦ä¸è½ä¸ºç©º', trigger: 'blur' }], snapshotUrl: [{ required: true, message: 'å¿«ç §URLä¸è½ä¸ºç©º', trigger: 'blur' }], snapshotWidth: [{ required: true, message: 'å¿«ç §å®½åº¦ä¸è½ä¸ºç©º', trigger: 'blur' }], type: [{ required: true, message: 'ç±»åä¸è½ä¸ºç©º', trigger: 'change' }], useGeneralModel: [{ required: true, message: '使ç¨éç¨æ¨¡åä¸è½ä¸ºç©º', trigger: 'change' }], isTransparent: [{ required: true, message: 'æ¯å¦å»é¤èæ¯ä¸è½ä¸ºç©º', trigger: 'change' }], status: [{ required: true, message: 'ç¶æä¸è½ä¸ºç©º', trigger: 'change' }], videoUrl: [{ required: true, message: 'è§é¢ä¸è½ä¸ºç©º', trigger: 'blur' }] }) const formRef = ref() // 表å Ref const StartCes = () => { console.log( " ----- å¼å§ ----- " ) isUploading.value = true } const End = (res)=>{ const FileObject = { file:res } httpRequest( FileObject ).then( response =>{ console.log(response) formData.value.videoUrl = response.data; } ).finally( res => { isUploading.value = false } ) } /** æå¼å¼¹çª */ const open = async (type: string, id?: number) => { dialogVisible.value = true dialogTitle.value = t('action.' + type) formType.value = type resetForm() // ä¿®æ¹æ¶ï¼è®¾ç½®æ°æ® if (id) { formLoading.value = true try { formData.value = await DigitalHumansApi.getDigitalHumans(id) } finally { formLoading.value = false } }else{ InitHumMODEL() } } defineExpose({ open }) // æä¾ open æ¹æ³ï¼ç¨äºæå¼å¼¹çª /** æäº¤è¡¨å */ const emit = defineEmits(['success']) // å®ä¹ success äºä»¶ï¼ç¨äºæä½æååçåè° const submitForm = async () => { // æ ¡éªè¡¨å await formRef.value.validate() // æäº¤è¯·æ± formLoading.value = true try { const data = formData.value as unknown as DigitalHumansApi.DigitalHumansVO if (formType.value === 'create') { await DigitalHumansApi.createDigitalHumans(data) message.success(t('common.createSuccess')) } else { await DigitalHumansApi.updateDigitalHumans(data) message.success(t('common.updateSuccess')) } dialogVisible.value = false // åéæä½æåçäºä»¶ emit('success') } finally { formLoading.value = false } } /** é置表å */ const resetForm = () => { formData.value = { id: undefined, expireStatus: undefined, finishTime: undefined, gender: undefined, matting: undefined, name: undefined, code: undefined, pictureUrl: undefined, posture: undefined, snapshotHeight: undefined, snapshotUrl: undefined, snapshotWidth: undefined, type: undefined, useGeneralModel: undefined, useModel: undefined, status: undefined, } formRef.value?.resetFields() } const handleFileSuccess = (fileType,response) => { if (fileType === 'videoUrl') { formData.value.videoUrl = response.data; } }; // ä¿®æ¹é»è®¤çæ°å人è§é¢æ¨¡å¼ä¸ºè§é¢ const InitHumMODEL = ()=>{ let ModelList = getIntDictOptions( DICT_TYPE.USE_MODEL ) for (let index = 0; index < ModelList.length; index++) { const element = ModelList[index]; if( element.label === "è§é¢" ){ formData.value.useModel = Number( element.value ) } } } </script> easegen-front/src/views/digitalcourse/digitalhumans/index.vue
@@ -173,7 +173,7 @@ <el-button link type="primary" @click="openForm('detail', scope.row.id)" @click="OpenLookformRef('detail', scope.row.id)" v-hasPermi="['digitalcourse:digital-humans:delete']" > {{t('digitalhumans.view')}} @@ -190,8 +190,10 @@ /> </ContentWrap> <!-- 表åå¼¹çªï¼æ·»å /ä¿®æ¹ --> <!-- 表åå¼¹çªï¼æ·»å --> <DigitalHumansForm ref="formRef" @success="getList" /> <!-- 表åå¼¹çªï¼ä¿®æ¹ --> <LookDigitalHumansForm ref="LookformRef" @success="getList" /> <!-- å¤ç --> <AuditForm ref="auditFormRef" @success="getList" /> </template> @@ -203,6 +205,7 @@ import download from '@/utils/download' import * as DigitalHumansApi from '@/api/digitalcourse/digitalhumans' import DigitalHumansForm from './DigitalHumansForm.vue' import LookDigitalHumansForm from './LookDigitalHumansForm.vue' import AuditForm from './AuditForm.vue' import { useUserStoreWithOut } from '@/store/modules/user' const userStore = useUserStoreWithOut() // ç¨æ·ä¿¡æ¯ç¼å @@ -260,13 +263,20 @@ handleQuery() } /** æ·»å /ä¿®æ¹æä½ */ /** æ·»å æä½ */ const formRef = ref() const auditFormRef = ref() const openForm = (type: string, id?: number) => { formRef.value.open(type, id) } /* ä¿®æ¹æä½ */ const LookformRef = ref() const OpenLookformRef = ( type: string, id?:number ) => { LookformRef.value.open( type, id ) } const openAuditForm = (type: string, id?: number) => { auditFormRef.value.open(type, id) } yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceUtil.java
@@ -26,16 +26,15 @@ 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; @@ -97,7 +96,7 @@ 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); // æåé³é¢æä»¶åï¼è·¯å¾çæåä¸é¨åï¼ @@ -107,32 +106,58 @@ // æåè§é¢æä»¶åï¼è·¯å¾çæåä¸é¨åï¼ 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 = "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; // å½åéè¯æ¬¡æ° @@ -145,8 +170,8 @@ 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); //åºå®å¼ @@ -191,10 +216,10 @@ 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) { @@ -213,7 +238,9 @@ break; } } success = true; } } String fileListPath = "D:/heygem_data/face2face/temp/filelist.txt"; try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileListPath))) { @@ -224,13 +251,24 @@ } 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); } @@ -238,6 +276,13 @@ } // åèäºå ¥æ¹æ³ private static int round(double value) { return BigDecimal.valueOf(value) .setScale(0, RoundingMode.HALF_UP) .intValue(); } public String getResult(String taskCode) { // ä½¿ç¨ do-while 循ç¯è½®è¯¢ä»»å¡ç¶æ // å®ä¹åéåå¨è¿åç»æ