Commit 8d5c82cb authored by Administrator's avatar Administrator

数字人视频生成

parent 75216ae2
......@@ -278,4 +278,30 @@ export default {
return Promise.reject(`与 img2img_inpaint Api 通讯失败`);
});
},
submitGenDigitHumanVideo(post_data: any): Promise<string> {
if (!post_data) {
return Promise.reject("输入不能为空");
}
return request.post('/text2video/gen_video_digithuman', post_data)
.then((res: any) => {
// console.log(res);
if (res && res.code === 0) {
if (res.data.result.combined_video_oss) {
return res.data.result.combined_video_oss;
} else if (res.data.result.human_video_out_oss) {
return res.data.result.human_video_out_oss;
} else {
return Promise.reject("视频合成失败");
}
} else {
const errorMessage = res ? res.message : "未知错误";
return Promise.reject(errorMessage);
}
})
.catch((err: any) => {
console.log(`err = ${JSON.stringify(err)}`);
return Promise.reject(`与后端 gen_video_digithuman 接口通讯失败`);
});
},
}
......@@ -3,6 +3,7 @@ import HomeView from '../views/home/index.vue'
import HomeViewEn from '../views/home/index_en.vue'
import RecordSteps from '../views/home/record_steps.vue'
import CalcRetire from '../views/home/calc_retire.vue'
import GenDigitHumanVideo from '../views/home/gen_digit_human_video.vue'
const router = createRouter({
......@@ -10,13 +11,13 @@ const router = createRouter({
routes: [
{
path: '/',
name: 'CalcRetire',
component: CalcRetire
name: 'GenDigitHumanVideo',
component: GenDigitHumanVideo
},
{
path: '/recordsteps',
name: 'recordsteps',
component: RecordSteps
path: '/calcretire',
name: 'CalcRetire',
component: CalcRetire
},
{
path: '/text2video',
......
<script setup lang="ts">
import text2videoService from "@/api/service/text2videoService";
import utils from "@/utils/utils";
import {
ElMessage, genFileId,
type UploadInstance,
type UploadProps,
type UploadRawFile
} from "element-plus";
import { nextTick, onMounted, reactive, ref } from "vue";
const debug = ref(import.meta.env.MODE === 'production' ? false : true);
// const debug = ref(false);
const loading = ref(false);
const title = ref("生成数字人视频");
const form = reactive({
task_id: "",
lang: "<|zh|>",
text: "国庆假期期间A股休市,而港股继续狂飙,成交量创历史新高,吸引了全球投资者目光。A股节日休市期间,恒生指数累计上涨9.3%,恒生科技指数涨幅超13%,“牛市旗手”券商股的普遍涨幅更是达到50%~100%甚至更高。与此同时,外资也继续看多中国资产。贝莱德、高盛等国际金融机构纷纷上调中国股市评级至“超配”。火上热搜!节后A股开盘即涨停?持续狂飙,还没上车的怎么办?国新办举行发布会介绍系统落实一揽子增量政策等情况,又将传递哪些信号?10月8日8:00开始,第一财经《直击节后首日交易》特别节目,与您一起见证历史,探讨投资策略,敬请关注!",
sample_audio_path: "",
sample_video_path: "",
show_image_or_video_path: "",
bgm: "",
final_video: "",
});
onMounted(() => {
// 初始化task_id
form.task_id = utils.genDateTimeStr();
console.log('页面加载,task_id=', form.task_id)
document.title = title.value;
if (!debug) {
form.text = "";
form.sample_audio_path = "";
form.sample_video_path = "";
form.show_image_or_video_path = "";
form.bgm = "";
}
});
// =========== 上传通用 Begin ===========
const actionUrl = ref(
import.meta.env.MODE === 'production'
? '/file'
: import.meta.env.VITE_APP_BASE_API + '/file'
)
const handleUploadError = (error: Error) => {
ElMessage({
message: String(error.message),
type: "error",
});
}
const handleBeforeUpload = async (file: any) => {
const isLt1M = file.size / 1024 / 1024 <= 10;
if (!isLt1M) {
ElMessage.error('文件大小不能超过 10MB')
return false
}
}
// =========== 上传通用 END ===========
// =========== 上传音频 Begin ===========
const upload_sample_audio = ref<UploadInstance>();
const UploadSampleAudioSuccess = (val: Wm.UploadResult) => {
if (val.code == 0) {
form.sample_audio_path = val.data[0].path;
ElMessage({
message: '上传成功',
type: 'success'
})
} else {
ElMessage({
message: '上传失败:'+val.message,
type: 'error'
})
}
}
const handleUploadSampleAudioExceed: UploadProps['onExceed'] = (files) => {
// 清除已上传的文件
upload_sample_audio.value!.clearFiles()
// 获取超出限制的第一个文件
const file = files[0] as UploadRawFile
// 给文件分配一个新的唯一标识
file.uid = genFileId()
// 手动触发文件上传
upload_sample_audio.value!.handleStart(file)
// 提交上传
upload_sample_audio.value!.submit()
}
const handleUploadSampleAudioRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
// 清除已上传的文件
upload_sample_audio.value!.clearFiles()
form.sample_audio_path = '';
}
// =========== 上传音频 END ===========
// =========== 上传采样视频 Begin ===========
const upload_sample_video = ref<UploadInstance>();
const UploadSampleVideoSuccess = (val: Wm.UploadResult) => {
if (val.code == 0) {
form.sample_video_path = val.data[0].path;
ElMessage({
message: '上传成功',
type: 'success'
})
} else {
ElMessage({
message: '上传失败:'+val.message,
type: 'error'
})
}
}
const handleUploadSampleVideoExceed: UploadProps['onExceed'] = (files) => {
// 清除已上传的文件
upload_sample_video.value!.clearFiles()
// 获取超出限制的第一个文件
const file = files[0] as UploadRawFile
// 给文件分配一个新的唯一标识
file.uid = genFileId()
// 手动触发文件上传
upload_sample_video.value!.handleStart(file)
// 提交上传
upload_sample_video.value!.submit()
}
const handleUploadSampleVideoRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
// 清除已上传的文件
upload_sample_video.value!.clearFiles()
form.sample_video_path = '';
}
// =========== 上传采样视频 END ===========
// =========== 上传拼接视频或图片 Begin ===========
const upload_show_image_or_video = ref<UploadInstance>();
const UploadShowImageOrVideoSuccess = (val: Wm.UploadResult) => {
if (val.code == 0) {
form.show_image_or_video_path = val.data[0].path;
ElMessage({
message: '上传成功',
type: 'success'
})
} else {
ElMessage({
message: '上传失败:'+val.message,
type: 'error'
})
}
}
const handleUploadShowImageOrVideoExceed: UploadProps['onExceed'] = (files) => {
// 清除已上传的文件
upload_show_image_or_video.value!.clearFiles()
// 获取超出限制的第一个文件
const file = files[0] as UploadRawFile
// 给文件分配一个新的唯一标识
file.uid = genFileId()
// 手动触发文件上传
upload_show_image_or_video.value!.handleStart(file)
// 提交上传
upload_show_image_or_video.value!.submit()
}
const handleUploadShowImageOrVideoRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
// 清除已上传的文件
upload_show_image_or_video.value!.clearFiles()
form.show_image_or_video_path = '';
}
// =========== 上传拼接视频或图片 END ===========
// 生成视频
const onGenVideo = async () => {
if (!form.text || form.text.length == 0
|| !form.sample_audio_path || form.sample_audio_path.length == 0
|| !form.sample_video_path || form.sample_video_path.length == 0
) {
ElMessage({
message: "文案、采样声音、出镜人物 均不能为空",
type: "error",
});
return;
}
try {
const video_param = {
task_id: form.task_id,
lang: form.lang,
text: form.text,
sample_audio_path: form.sample_audio_path,
sample_video_path: form.sample_video_path,
show_image_or_video_path: form.show_image_or_video_path,
bgm: "",
}
const result = await text2videoService.submitGenDigitHumanVideo(video_param);
console.log(result);
form.final_video = "";
form.final_video = result + "?v=" + utils.genDateTimeStr();
} catch(error: any) {
// console.error(error);
ElMessage({
message: error,
type: "error",
});
};
};
</script>
<!-- ============================================================================================================ -->
<!-- ============================================================================================================ -->
<!-- ============================================================================================================ -->
<template>
<main class="home-container">
<!-- 标题 -->
<el-divider content-position="left">{{ title }}</el-divider>
<el-form :model="form" label-width="114px" v-loading="loading">
<!-- 文案 -->
<el-form-item label="文案">
<el-input
v-model="form.text"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
placeholder="Please input"
/>
</el-form-item>
<!-- 采样声音 -->
<el-form-item label="采样声音">
<el-upload
ref="upload_sample_audio"
:show-file-list="true"
:limit="1"
accept=".wav,.WAV"
:action="actionUrl"
:on-success="UploadSampleAudioSuccess"
:on-exceed="handleUploadSampleAudioExceed"
:on-error="handleUploadError"
:before-upload="handleBeforeUpload"
:on-remove="handleUploadSampleAudioRemove"
>
<el-button type="primary" size="small">上传</el-button>
<template #tip>
<div class="el-upload__tip" style="color: #ff0000">
wav 格式, 时长不大于 30秒, 文件小于 10M。
</div>
</template>
</el-upload>
</el-form-item>
<!-- 出镜人物 -->
<el-form-item label="出镜人物">
<el-upload
ref="upload_sample_video"
:show-file-list="true"
:limit="1"
accept=".mp4,.MP4"
:action="actionUrl"
:on-success="UploadSampleVideoSuccess"
:on-exceed="handleUploadSampleVideoExceed"
:on-error="handleUploadError"
:before-upload="handleBeforeUpload"
:on-remove="handleUploadSampleVideoRemove"
>
<el-button type="primary" size="small">上传</el-button>
<template #tip>
<div class="el-upload__tip" style="color: #ff0000">
mp4 格式, 时长 5秒左右即可, 文件小于 10M。
</div>
</template>
</el-upload>
</el-form-item>
<!-- 拼接视频或图片 -->
<el-form-item label="拼接视频或图片">
<el-upload
ref="upload_show_image_or_video"
:show-file-list="true"
:limit="1"
accept=".mp4,.MP4,.png,.PNG,.jpg,.JPG,.jpeg,.JPEG"
:action="actionUrl"
:on-success="UploadShowImageOrVideoSuccess"
:on-exceed="handleUploadShowImageOrVideoExceed"
:on-error="handleUploadError"
:before-upload="handleBeforeUpload"
:on-remove="handleUploadShowImageOrVideoRemove"
>
<el-button type="primary" size="small">上传</el-button>
<template #tip>
<div class="el-upload__tip" style="color: #ff0000">
可以上传视频(mp4)或图片(jpg, png),
作为最终视频的上半部分,也可以不上传,不传则只生成数字人视频。
</div>
</template>
</el-upload>
</el-form-item>
<!-- 结果 -->
<el-form-item>
<el-button type="primary" @click="onGenVideo">生成视频</el-button>
</el-form-item>
<el-form-item>
<video :src="form.final_video" controls></video>
</el-form-item>
</el-form>
</main>
</template>
<style lang="scss" scoped>
.home-container {
width: 100%;
}
</style>
<style lang="scss">
.home-container {
.el-table .el-table__cell {
z-index: calc(var(--el-table-index) -1);
}
}
.dashed-div {
border: 1px dashed #999;
margin: 5px 0;
padding: 2px;
}
</style>
......@@ -27,8 +27,8 @@ export default defineConfig({
proxy: {
'/api/': {
// target: 'http://127.0.0.1:5001/', // 本机后端服务
target: 'http://wm-tools-backend.frp.wmdigit.com:8888/', // new3090后端服务
// target: 'http://wm-tools-backend-test.frp.wmdigit.com:8888/', // 4090-1测试后端服务
// target: 'http://wm-tools-backend.frp.wmdigit.com:8888/', // new3090后端服务
target: 'http://wm-tools-backend-test.frp.wmdigit.com:8888/', // 测试后端服务
changeOrigin: true,
rewrite: (path: any) => path.replace(/^\/api/, '')
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment