Commit dde1752c by haojie

文本提交没有传时长的问题

parent 802559fd
...@@ -103,6 +103,10 @@ ...@@ -103,6 +103,10 @@
.file-name { .file-name {
font-size: @size-16; font-size: @size-16;
color: #888fa1; color: #888fa1;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
.reset-submit { .reset-submit {
width: 200px; width: 200px;
......
...@@ -57,7 +57,7 @@ export default defineComponent({ ...@@ -57,7 +57,7 @@ export default defineComponent({
default: '', default: '',
}, },
}, },
emits: ['update:modelValue', 'change', 'file'], emits: ['update:modelValue', 'change', 'file', 'firstFrame'],
setup(props, { emit }) { setup(props, { emit }) {
const files = ref([]); const files = ref([]);
// 文件地址 // 文件地址
...@@ -96,6 +96,7 @@ export default defineComponent({ ...@@ -96,6 +96,7 @@ export default defineComponent({
curfile.url = ''; curfile.url = '';
curfile.status = 0; curfile.status = 0;
curfile.firstFrame = ''; curfile.firstFrame = '';
emit('firstFrame', null);
files.value = []; files.value = [];
} }
}; };
...@@ -159,6 +160,7 @@ export default defineComponent({ ...@@ -159,6 +160,7 @@ export default defineComponent({
const UploadSuccessCallback = async (uuid: any, url: any) => { const UploadSuccessCallback = async (uuid: any, url: any) => {
if (props.showFirstFrame) { if (props.showFirstFrame) {
let first = await getFirstFrameOfVideo(url); let first = await getFirstFrameOfVideo(url);
emit('firstFrame', first);
curfile.firstFrame = URL.createObjectURL(first); curfile.firstFrame = URL.createObjectURL(first);
} }
// 关闭定时器 // 关闭定时器
......
...@@ -11,6 +11,7 @@ import routerConfig from '@/router/tool'; ...@@ -11,6 +11,7 @@ import routerConfig from '@/router/tool';
import useConfuse from '@/hooks/useConfuse'; import useConfuse from '@/hooks/useConfuse';
import { callPyjsInWindow, writeLog } from '@/utils/pyqt'; import { callPyjsInWindow, writeLog } from '@/utils/pyqt';
import { getTestUuid } from '@/constants/token'; import { getTestUuid } from '@/constants/token';
import { getDurationOfAudioFile } from '@/utils/audio';
// 轮询处理文本脚本语音生成回调 // 轮询处理文本脚本语音生成回调
export const processTextCallback = () => { export const processTextCallback = () => {
...@@ -235,19 +236,19 @@ export const processTextCallback = () => { ...@@ -235,19 +236,19 @@ export const processTextCallback = () => {
task_id: getTaskId(isConfuse, uuid), task_id: getTaskId(isConfuse, uuid),
}); });
if (res.code == 0) { if (res.code == 0) {
if (isDev()) { // if (isDev()) {
for (let i = 0; i < 1; i++) { // for (let i = 0; i < 1; i++) {
let params = { // let params = {
data: { // data: {
audio_address: // audio_address:
'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-16fcc74a89-d3f1-4545-a17c-d155dfa7978f.wav', // 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-16fcc74a89-d3f1-4545-a17c-d155dfa7978f.wav',
task_id: 0, // task_id: 0,
id: i, // id: i,
}, // },
}; // };
res.data.push(params); // res.data.push(params);
} // }
} // }
if (res.data.length) { if (res.data.length) {
// 根据id升序排列 // 根据id升序排列
res.data = TableSortAsc(res.data, 'data.id'); res.data = TableSortAsc(res.data, 'data.id');
...@@ -274,13 +275,23 @@ export const processTextCallback = () => { ...@@ -274,13 +275,23 @@ export const processTextCallback = () => {
let resultList = await audioStart([data.audio_address], true); let resultList = await audioStart([data.audio_address], true);
// 转一维 // 转一维
resultList = dimensionalConvert(resultList); resultList = dimensionalConvert(resultList);
let newList = resultList.map((row: any) => { let newList = [];
return { // 获取音频时长
for (let $j = 0; $j < resultList.length; $j++) {
let row = resultList[$j];
let duration = await getDurationOfAudioFile(row.content);
let param: any = {
content: row.content, content: row.content,
movement_type: list[index].movement_type, movement_type: list[index].movement_type,
movement_name: list[index].movement_name, movement_name: list[index].movement_name,
}; };
}); if (typeof duration === 'number') {
param.duration = parseInt(duration + '');
} else {
param.duration = 0;
}
newList.push(param);
}
// 要提交的数组 // 要提交的数组
list[index].newList = newList; list[index].newList = newList;
commitInfo({ commitInfo({
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
:config="ossConfig" :config="ossConfig"
:accept="videoAccept" :accept="videoAccept"
:uploadInfo="videoUploadInfo" :uploadInfo="videoUploadInfo"
@firstFrame="firstFrame"
></Upload> ></Upload>
</div> </div>
<div class="divide">+</div> <div class="divide">+</div>
...@@ -25,21 +26,34 @@ ...@@ -25,21 +26,34 @@
</div> </div>
</div> </div>
<div class="face-transplant-footer"> <div class="face-transplant-footer">
<div class="footer-options">
<div class="fase-hd-switch">
<span class="label">是否开启人脸高清</span>
<Switch v-model="FaceHDSwitch"></Switch>
</div>
</div>
<div class="footer-buttons">
<Button theme="opacity" class="face-transplant-footer-reset" @click="onReset">重置</Button> <Button theme="opacity" class="face-transplant-footer-reset" @click="onReset">重置</Button>
<Button theme="green" class="face-transplant-create" @click="openDialog">生成</Button> <Button theme="green" class="face-transplant-create" @click="openDialog">生成</Button>
</div> </div>
<ConfirmDialog v-model="confirmDialogVisible" title="确定生成吗?" @confirm="confirm"></ConfirmDialog> </div>
<OptionsDialog v-model="optionsDialogVisible" :loading="loading" @submit="onSubmit"></OptionsDialog>
</div> </div>
</template> </template>
<script lang="tsx" setup> <script lang="tsx" setup>
import ConfirmDialog from '@/components/ConfirmDialog.vue'; import Switch from '@/components/switch';
import Button from '@/components/Button.vue'; import Button from '@/components/Button.vue';
import Upload from '@/components/upload'; import Upload from '@/components/upload';
import { videoAccept, imageAccept } from '@/constants/token'; import { videoAccept, imageAccept } from '@/constants/token';
import { getUploadConfig } from '@/service/Common'; import { getUploadConfig } from '@/service/Common';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { show_message } from '@/utils/tool'; import { alyOssUpload, show_message } from '@/utils/tool';
import OptionsDialog from './optionsDialog.vue';
import { createChangeFaseTask } from '@/utils/api/userApi';
import { v4 } from 'uuid';
const emit = defineEmits(['restart']);
const videoUploadInfo = { const videoUploadInfo = {
label1: '选择需要换脸的视频', label1: '选择需要换脸的视频',
...@@ -58,18 +72,49 @@ const imageUploadInfo = { ...@@ -58,18 +72,49 @@ const imageUploadInfo = {
}; };
const ossConfig = ref({}); const ossConfig = ref({});
// 弹窗状态 // 选项弹窗状态
const confirmDialogVisible = ref(false); const optionsDialogVisible = ref(false);
const loading = ref(false);
// 视频文件 // 视频文件
const videoFile = ref(''); const videoFile = ref('');
// 视频第一帧
const videoFrame = ref();
// 上传后的视频第一帧
const uploadVideoFrame = ref('');
// 图片文件 // 图片文件
const imageFile = ref(''); const imageFile = ref('');
// 人脸高清
const FaceHDSwitch = ref(true);
const getConfig = async () => { const getConfig = async () => {
ossConfig.value = await getUploadConfig(); ossConfig.value = await getUploadConfig();
}; };
// 视频第一帧改变
const firstFrame = (file: Blob) => {
videoFrame.value = file;
};
const uploadSuccess = (name: string, url: string) => {
uploadVideoFrame.value = url;
};
// 视频第一帧上传到阿里云
const uploadImage = async () => {
try {
await getConfig();
let uuid = v4();
const res: any = await alyOssUpload(ossConfig.value, videoFrame.value, uploadSuccess, () => '', uuid);
if (res.status == 'success') {
return true;
}
return false;
} catch (e) {
console.log(e);
return false;
}
};
const openDialog = () => { const openDialog = () => {
if (!videoFile.value) { if (!videoFile.value) {
show_message('视频必传'); show_message('视频必传');
...@@ -79,21 +124,50 @@ const openDialog = () => { ...@@ -79,21 +124,50 @@ const openDialog = () => {
show_message('图片必传'); show_message('图片必传');
return; return;
} }
confirmDialogVisible.value = true; optionsDialogVisible.value = true;
}; };
// 重置 // 重置
const onReset = () => { const onReset = () => {
videoFile.value = ''; videoFile.value = '';
imageFile.value = ''; imageFile.value = '';
FaceHDSwitch.value = true;
uploadVideoFrame.value = '';
videoFrame.value = null;
}; };
// 确定生成 // 确定生成
const confirm = async () => { const onSubmit = async (params: any) => {
try { try {
console.log(videoFile.value); loading.value = true;
console.log(imageFile.value); if (videoFrame.value) {
// 视频第一帧上传到阿里云
const status = await uploadImage();
if (!status) {
show_message('上传失败');
return;
}
}
const res: any = await createChangeFaseTask({
name: params.title,
cover: uploadVideoFrame.value,
extend: {
source: imageFile.value,
target: videoFile.value,
face_enhancer: FaceHDSwitch.value,
},
});
if (res.code == 0) {
show_message('提交成功,请等待', 'success');
// 刷新记录
emit('restart');
loading.value = false;
optionsDialogVisible.value = false;
onReset();
}
loading.value = false;
} catch (e) { } catch (e) {
loading.value = false;
console.log(e); console.log(e);
} }
}; };
...@@ -153,9 +227,22 @@ onMounted(() => { ...@@ -153,9 +227,22 @@ onMounted(() => {
height: 60px; height: 60px;
border-top: 1px solid #9f9f9f; border-top: 1px solid #9f9f9f;
display: flex; display: flex;
justify-content: flex-end; justify-content: space-between;
align-items: center; align-items: center;
padding: 0 20px; padding: 0 20px;
.footer-options {
.fase-hd-switch {
display: flex;
align-items: center;
.label {
font-size: @size-16;
color: white;
font-weight: 400;
margin-right: 12px;
}
}
}
.footer-buttons {
.t-button { .t-button {
font-weight: 700; font-weight: 700;
font-size: @size-14; font-size: @size-14;
...@@ -169,5 +256,6 @@ onMounted(() => { ...@@ -169,5 +256,6 @@ onMounted(() => {
margin-left: 20px; margin-left: 20px;
} }
} }
}
} }
</style> </style>
<template>
<Dialog v-model="visible" className="face-transplant-options-dialog" @confirm="onConfirm">
<template #header> 智能换脸 </template>
<template #body>
<div>
<FormItem label="视频名称">
<Input v-model="videoName" align="left" placeholder="请输入视频名称"></Input>
</FormItem>
</div>
</template>
<ConfirmDialog
v-model="confirmDialogVisible"
:zIndex="3000"
title="确定生成吗?"
@confirm="confirmCreate"
></ConfirmDialog>
<Loading v-show="loading" :mask="true"></Loading>
</Dialog>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import Dialog from '@/components/Dialog.vue';
import FormItem from '@/componentsUsiness/formItem.vue';
import Input from '@/components/input/index.vue';
import { show_message } from '@/utils/tool';
import ConfirmDialog from '@/components/ConfirmDialog.vue';
import Loading from '@/components/loading.vue';
const props = withDefaults(
defineProps<{
modelValue: boolean;
loading: boolean;
}>(),
{},
);
const emit = defineEmits(['update:modelValue', 'submit']);
// 确认弹窗状态
const confirmDialogVisible = ref(false);
const visible = computed({
get() {
return props.modelValue;
},
set(value) {
emit('update:modelValue', value);
},
});
// 视频名称
const videoName = ref('');
const onConfirm = () => {
if (!videoName.value) {
show_message('请输入视频名称');
return;
}
confirmDialogVisible.value = true;
};
// 确定生成
const confirmCreate = () => {
// 提交
emit('submit', {
title: videoName.value,
});
};
</script>
<style lang="less">
.face-transplant-options-dialog {
.t-dialog {
position: relative;
.t-dialog__body {
padding: 30px 0 !important;
.custom-usiness-form-item {
align-items: center;
}
}
}
}
</style>
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<template v-else-if="list.length"> <template v-else-if="list.length">
<div class="record-items" v-for="item in list" :key="item.id"> <div class="record-items" v-for="item in list" :key="item.id">
<div class="left"> <div class="left">
<img :src="item.cover_url" alt="" /> <img :src="item.cover" alt="" />
</div> </div>
<div class="center"> <div class="center">
<div class="name"> <div class="name">
...@@ -20,17 +20,36 @@ ...@@ -20,17 +20,36 @@
<div class="download-box"> <div class="download-box">
<Button <Button
theme="green" theme="green"
:class="['download-button', item.audit_status != 3 ? 'download-button__disabled' : '']" :class="['download-button', item.status != 1 || !item.url ? 'download-button__disabled' : '']"
@click="onDownloadVideo(item)" @click="onDownloadVideo(item)"
>下载</Button >下载</Button
> >
</div> </div>
</div> </div>
<CustomizationStatus :status="item.audit_status"> <div class="customization-status-face">
<template #progressTip> <!-- 成功 -->
<template v-if="item.status == 1">
<div class="status">
<img :src="imgs.success" />
<div>{{ item.status_label }}</div>
</div>
</template>
<!-- 等待 -->
<template v-else-if="item.status == 2">
<div class="status">
<img :src="imgs.underReview" />
<div>{{ item.status_label }}</div>
</div>
</template>
<!-- 进行中 -->
<template v-else-if="item.status == 3">
<div class="status">
<img :src="imgs.progress" />
<div>{{ item.status_label }}</div>
<div class="progress-tips">{{ tipsLabel }}</div> <div class="progress-tips">{{ tipsLabel }}</div>
</div>
</template> </template>
</CustomizationStatus> </div>
</div> </div>
</template> </template>
<template v-else> <template v-else>
...@@ -40,7 +59,6 @@ ...@@ -40,7 +59,6 @@
</template> </template>
<script lang="tsx" setup> <script lang="tsx" setup>
import CustomizationStatus from '@/components/CustomizationStatus';
import Button from '@/components/Button.vue'; import Button from '@/components/Button.vue';
import { pyDownloadVideo } from '@/utils/pyqt'; import { pyDownloadVideo } from '@/utils/pyqt';
import { show_message } from '@/utils/tool'; import { show_message } from '@/utils/tool';
...@@ -57,15 +75,22 @@ withDefaults( ...@@ -57,15 +75,22 @@ withDefaults(
}, },
); );
const imgs = {
underReview: new URL('@/assets/svg/custom/underReview.svg', import.meta.url).href,
auditFailure: new URL('@/assets/svg/custom/auditFailure.svg', import.meta.url).href,
progress: new URL('@/assets/svg/custom/progress.svg', import.meta.url).href,
success: new URL('@/assets/svg/custom/success.svg', import.meta.url).href,
};
const tipsLabel = ref('该过程需要10~24小时'); const tipsLabel = ref('该过程需要10~24小时');
// 下载视频 // 下载视频
const onDownloadVideo = (item: any) => { const onDownloadVideo = (item: any) => {
if (item.audit_status != 3) { if (item.status != 3) {
return; return;
} }
// 下载item的视频 // 下载item的视频
let url = item.video_url; let url = item.url;
if (!url) { if (!url) {
show_message('没有视频'); show_message('没有视频');
return; return;
...@@ -133,6 +158,21 @@ const onDownloadVideo = (item: any) => { ...@@ -133,6 +158,21 @@ const onDownloadVideo = (item: any) => {
font-size: @size-16; font-size: @size-16;
} }
} }
.customization-status-face {
.status {
font-size: @size-18;
color: #fff;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 166px;
white-space: nowrap;
& > * {
margin: 4px 0;
}
}
}
.download-box { .download-box {
.download-button { .download-button {
height: 28px !important; height: 28px !important;
......
<template> <template>
<Customizable class="face-transplant-izable" :video="true" :icon="getIcon()" :label="navigationLabels.faceTransplant"> <Customizable class="face-transplant-izable" :video="true" :icon="getIcon()" :label="navigationLabels.faceTransplant">
<template #header> <template #header>
<Header></Header> <Header @restart="onRestart"></Header>
</template> </template>
<CustomTabs v-model="currentTab" theme="dark2" class="custom-tabs-flex"> <CustomTabs v-model="currentTab" theme="dark2" class="custom-tabs-flex">
<CustomTabPanel name="1" label="生成记录"> <CustomTabPanel name="1" label="生成记录">
...@@ -28,7 +28,7 @@ import PersonSvg from '@/assets/svg/home/faceTransplant.svg'; ...@@ -28,7 +28,7 @@ import PersonSvg from '@/assets/svg/home/faceTransplant.svg';
import { onMounted, ref, reactive } from 'vue'; import { onMounted, ref, reactive } from 'vue';
import routerConfig from '@/router/tool'; import routerConfig from '@/router/tool';
import { jumpPageAddNavigation } from '@/router/jump'; import { jumpPageAddNavigation } from '@/router/jump';
import { getDigitalPeopleList } from '@/service/Common'; import { getChangeFaseRecord } from '@/utils/api/userApi';
const { addNavigation } = jumpPageAddNavigation(); const { addNavigation } = jumpPageAddNavigation();
...@@ -46,10 +46,17 @@ const getIcon = () => { ...@@ -46,10 +46,17 @@ const getIcon = () => {
// 获取我的数字人列表 // 获取我的数字人列表
const getList = async () => { const getList = async () => {
try {
loading.value = true; loading.value = true;
let res = await getDigitalPeopleList(); const res: any = await getChangeFaseRecord();
personList.list = res.myList; if (res.code == 0) {
personList.list = res.data.data;
}
loading.value = false;
} catch (e) {
loading.value = false; loading.value = false;
console.log(e);
}
}; };
onMounted(() => { onMounted(() => {
...@@ -57,6 +64,10 @@ onMounted(() => { ...@@ -57,6 +64,10 @@ onMounted(() => {
// 获取数字人列表 // 获取数字人列表
getList(); getList();
}); });
const onRestart = () => {
getList();
};
</script> </script>
<style lang="less"> <style lang="less">
......
...@@ -518,3 +518,24 @@ export const randomLiveReply = () => { ...@@ -518,3 +518,24 @@ export const randomLiveReply = () => {
}, },
}); });
}; };
// 创建换脸任务
export const createChangeFaseTask = (data: any) => {
const header = getHeader();
return request.post(`/api/face`, data, {
headers: {
...header,
},
});
};
// 换脸记录
export const getChangeFaseRecord = () => {
const header = getHeader();
return request.get(`/api/face`, {
params: {},
headers: {
...header,
},
});
};
...@@ -8,7 +8,7 @@ const error_messaage = '请求错误'; ...@@ -8,7 +8,7 @@ const error_messaage = '请求错误';
const getBaseUrl = async () => { const getBaseUrl = async () => {
if (isDev()) { if (isDev()) {
// return 'http://156.247.11.21:93'; return 'http://156.247.11.21:93';
return ''; return '';
} }
// 默认线上地址 // 默认线上地址
......
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