Commit c7731fcb by haojie

洗稿

parent 0d8701a5
......@@ -25,6 +25,7 @@
"rules": {
// 禁止 || true ,关闭
"no-constant-condition": 0,
"no-empty": 0,
"vue/no-setup-props-destructure": 0,
"vue/no-v-model-argument": 0,
"vue/no-v-for-template-key": 0,
......
......@@ -6,9 +6,10 @@
:volume="firstVideoVolume"
ref="videoFirst"
class="video-default"
loop
:src="video1"
:loop="loop"
@canplay="canplay"
@ended="firstVideoEnded"
></video>
<video
v-show="!showFirstVideo"
......@@ -16,7 +17,7 @@
:volume="secondVideoVolume"
class="video-default"
:src="video2"
@ended="onVideoEnded"
@ended="secondVideoEnded"
@canplay="canplay2"
></video>
<ConfirmDialog v-model="confirmVisible" :closeOnOverlayClick="false" :footer="footerStatus" @confirm="confirm">
......@@ -42,19 +43,35 @@ import { onBeforeRouteLeave } from 'vue-router';
import { injectWindow } from '@/utils/pyqt';
import { show_message } from '@/utils/tool';
const props = defineProps<{
const props = withDefaults(
defineProps<{
video1: string;
video2: string;
playId?: any;
progress: number;
}>();
mainIndex?: number | null;
totalTime: number;
liveDetail: any;
}>(),
{
mainIndex: null,
},
);
const emit = defineEmits(['playEnd', 'update:progress']);
const emit = defineEmits([
'update:totalTime',
'currentTime',
'playEnd',
'mainVideoStartPlay',
'mainVideoPlayEnd',
'update:progress',
]);
const store = useStore();
const videoNum = computed(() => store.getters['live/getVideoNum']);
const liveVideoStatus = computed(() => store.getters['live/getLiveVideoStatus']);
const loop = ref(false);
const loading = ref(true);
const footerStatus = ref(false);
const showFirstVideo = ref(true);
......@@ -63,6 +80,9 @@ const videoSecondPlay = ref(false);
const confirmVisible = ref(true);
// 第一个视频是否首次播放
const videoFirstPlay = ref(true);
// 第二个视频是否首次播放
const videoSecondFirstPlay = ref(true);
......@@ -98,18 +118,35 @@ const closeInterval = () => {
interval = null;
};
// 确定播放
const confirm = () => {
openInterval();
onPlay();
videoFirstPlay.value = false;
emit('mainVideoStartPlay', props.mainIndex);
};
// 主视频可以播放
const canplay = () => {
// 获取视频总时长
total.value = videoFirst.value.duration;
// onPlay();
emit('update:totalTime', total.value);
if (!videoFirstPlay.value) {
//
onPlay();
emit('mainVideoStartPlay', props.mainIndex);
}
};
// 主视频播放完毕
const firstVideoEnded = () => {
if (videoFirst.value.ended) {
emit('mainVideoPlayEnd', props.mainIndex);
}
};
const onVideoEnded = () => {
// 互动视频播放完毕
const secondVideoEnded = () => {
if (videoSecond.value?.ended) {
emit('playEnd', props.playId);
showFirstVideo.value = true;
......@@ -156,6 +193,17 @@ watch(
},
);
// 判断是否洗稿
watch(
() => props.liveDetail,
(v) => {
if (v && v.is_disorganize === 0) {
// 不洗稿,开启循环播放
loop.value = true;
}
},
);
watch(
() => props.video1,
(v) => {
......@@ -183,6 +231,8 @@ const updateTime = () => {
if (total.value) {
// 计算百分比
emit('update:progress', Math.floor((videoFirst.value.currentTime / total.value) * 100));
// 提交当前进度
emit('currentTime', videoFirst.value.currentTime);
}
};
// 减小正在播放的视频音量
......
......@@ -102,19 +102,21 @@ export default defineComponent({
// 文件是否上传过
const fileHasUploaded = (file: File) => {
for (let i = 0; i < fileList.value.length; i++) {
let item = fileList.value[i].file;
if (
item === file ||
(item.lastModified == file.lastModified &&
item.name == file.name &&
item.size == file.size &&
item.type == file.type)
) {
show_message(`${file.name}已经上传过了`);
return false;
}
}
// for (let i = 0; i < fileList.value.length; i++) {
// let item = fileList.value[i].file;
// if (item) {
// if (
// item === file ||
// (item.lastModified == file.lastModified &&
// item.name == file.name &&
// item.size == file.size &&
// item.type == file.type)
// ) {
// show_message(`${file.name}已经上传过了`);
// return false;
// }
// }
// }
return true;
};
......@@ -131,9 +133,11 @@ export default defineComponent({
return false;
}
// 文件后缀
const fileSuffix = getFileSuffix(file);
let fileSuffix = getFileSuffix(file);
if (props.accept) {
if (props.accept.indexOf(fileSuffix) == -1) {
let accept = props.accept.toLowerCase();
fileSuffix = fileSuffix.toLowerCase();
if (accept.indexOf(fileSuffix) == -1) {
show_message(`本次上传仅支持${props.accept}格式`);
return false;
}
......@@ -269,6 +273,8 @@ export default defineComponent({
fileList.value.forEach((item: any) => {
if (item.url) {
list.push(item.url);
} else if (item.audio_url) {
list.push(item.audio_url);
}
if (item.time) {
totalTime += item.time;
......@@ -322,7 +328,7 @@ export default defineComponent({
</span>
</div>
)}
<div class="file-name">{item.file.name}</div>
<div class="file-name">{item.file?.name}</div>
{computedTotalTime() ? (
<audio
src={item.url}
......
import { computed, onBeforeUnmount, ref, watch } from 'vue';
import { useStore } from 'vuex';
import { createLiveKeys, scriptTypeText } from '@/service/CreateLive';
import { getLiveTtsCallback, createLiveTask, liveTts } from '@/utils/api/userApi';
import { alyOssUpload, show_message } from '@/utils/tool';
import { getLiveTtsCallback, createLiveTask, liveTts, liveTaskRegenerate } from '@/utils/api/userApi';
import { alyOssUpload, dimensionalConvert, isDev, show_message } from '@/utils/tool';
import { audioMerge, splitAudio } from '@/utils/audio';
import { useLiveInfoSubmit } from '@/hooks/useStoreCommit';
import { getUploadConfig } from '@/service/Common';
import { getUploadConfig, onUpdateLiveTask } from '@/service/Common';
import { v4 } from 'uuid';
import { useRoute, useRouter } from 'vue-router';
import routerConfig from '@/router/tool';
import useConfuse from '@/hooks/useConfuse';
import CustomException from '@/utils/error';
import { callPyjsInWindow } from '@/utils/pyqt';
// 轮询处理文本脚本语音生成回调
export const processTextCallback = () => {
......@@ -46,6 +48,7 @@ export const processTextCallback = () => {
// 生成音频
let res: any = await liveTts(params);
if (res.code == 0) {
console.log('等待音频生成完成');
// 开始轮询
openInterval(true);
}
......@@ -57,6 +60,7 @@ export const processTextCallback = () => {
() => confuseList.value,
(v) => {
if (v.length) {
console.log('洗稿列表变化');
// 提交生成音频任务
submitAudioTask(v);
}
......@@ -81,25 +85,29 @@ export const processTextCallback = () => {
params.type_content = item[createLiveKeys.textScriptValue];
// 音色id
params.phonetic_timbres_id = item[createLiveKeys.textSoundColor];
// 文本内容
params.content = item[createLiveKeys.textScriptList].map((item: any) => {
// 文本内容--先转一维数组
let newList = dimensionalConvert(item[createLiveKeys.textScriptList]);
params.content = newList.map((row: any) => {
return {
title: item.title,
content: item.content,
title: row.title,
content: row.content,
};
});
} else {
// 音频
params.type_content = item[createLiveKeys.audioScriptList].map((item: any) => {
console.log(item[createLiveKeys.audioScriptList]);
params.type_content = item[createLiveKeys.audioScriptList].map((audioScript: any) => {
let list = [];
item.data.forEach((it: any) => {
audioScript.data.forEach((it: any) => {
let params = {
content: '',
};
if (typeof it === 'string') {
params.content = it;
} else {
} else if (it.url) {
params.content = it.url;
} else {
params.content = it.audio_url;
}
list.push(params);
});
......@@ -134,7 +142,8 @@ export const processTextCallback = () => {
};
// 提交后台
const submit = async () => {
const submit = async (type: string = 'create') => {
if (type === 'create') {
try {
let res: any = await createLiveTask(filterFiled());
if (res.code == 0) {
......@@ -145,13 +154,40 @@ export const processTextCallback = () => {
console.log(e);
return false;
}
} else {
// 更新
console.log('更新');
try {
let params = filterFiled();
loading.value = true;
let res: any = await onUpdateLiveTask(route.query.id, params);
if (res) {
if (route.query.type === 'edit') {
// 通知python删除对应的output.mp4
callPyjsInWindow('deleteOutputVideo', {
id: route.query.id,
});
}
// 回首页
backHome();
}
loading.value = false;
} catch (e) {
loading.value = false;
console.log(e);
}
}
};
// 任务提交成功后的回调
const submitSuccessed = (message: string = '创建成功') => {
const submitSuccessed = (message: string = '创建成功', back: boolean = true) => {
if (message) {
show_message(message, 'success');
}
if (back) {
// 回首页
backHome();
}
initCreateStore();
// 通知三个模块清空自己的内容
initNum.value += 1;
......@@ -192,6 +228,10 @@ export const processTextCallback = () => {
// 循环上传阿里云
const uploadToAly = async (fileList: File[]) => {
// 每次上传前清空数组
alyList.value = [];
console.log('任务数');
console.log(fileList.length);
// 获取阿里云配置
let config = await getUploadConfig();
for (let i = 0; i < fileList.length; i++) {
......@@ -232,6 +272,8 @@ export const processTextCallback = () => {
let split_list = await splitAudio(file, 5 * 1024 * 1024);
if (split_list && split_list.length) {
let result = await uploadToAly(split_list);
console.log('上传完毕');
console.log(result.length);
// 是否一维数组
if (dimensional) {
return result;
......@@ -239,11 +281,32 @@ export const processTextCallback = () => {
return [result];
}
}
} else {
}
};
// 重新生成直播
const regenerate = async (list: any[], successCallback: boolean) => {
try {
let params = filterFiled();
params.type_content = list;
let res: any = await liveTaskRegenerate(route.query.id, params);
if (res.code == 0) {
if (successCallback) {
submitSuccessed();
}
}
} catch (e) {
console.log(e);
}
};
// 获取任务id
const getTaskId = (isConfuse: boolean) => {
const getTaskId = (isConfuse: boolean, uuid: string = '') => {
if (uuid) {
console.log('自定义的uuid');
return uuid;
}
if (isConfuse) {
// 是洗稿任务
return currentConfuseId.value;
......@@ -251,12 +314,30 @@ export const processTextCallback = () => {
return createLiveInfo.value[createLiveKeys.scriptUuid];
};
const getTaskStatus = async (isConfuse: boolean) => {
const getTaskStatus = async (
isConfuse: boolean,
type: string = 'create',
successCallback: boolean,
uuid: string,
customRegenerate: any = false,
) => {
try {
let res: any = await getLiveTtsCallback({
task_id: getTaskId(isConfuse),
task_id: getTaskId(isConfuse, uuid),
});
if (res.code == 0) {
if (isDev()) {
let params = {
data: {
audio_address:
'http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/jupiter-flow/tmp/ed71050141c74954ac779cfbb9dd9604.wav?Expires=1691136228&OSSAccessKeyId=LTAIUpwNp2H7pBG5&Signature=jE01uOk8Vfa08ovlPbJYI2Bhwvs%3D',
task_id: 0,
},
};
for (let i = 0; i < 10; i++) {
res.data.push(params);
}
}
if (res.data.length >= createLiveInfo.value[createLiveKeys.textScriptList].length) {
// 关闭定时器
closeInterval();
......@@ -267,7 +348,11 @@ export const processTextCallback = () => {
res.data.forEach((item: any) => {
// 根据task_id更新数组对象
let data = item.data;
if (data && data.audio_address && data.task_id) {
if (
data &&
data.audio_address &&
(typeof data.task_id === 'string' || typeof data.task_id === 'number')
) {
audio_list.push(data.audio_address);
let index = list.findIndex((it: any) => it.task_id == data.task_id);
if (index !== -1) {
......@@ -280,18 +365,23 @@ export const processTextCallback = () => {
show_message('缺少音频或id');
}
});
if (!audio_list.length) {
throw new CustomException('没有要处理的音频');
}
let resultList = await audioStart(audio_list, false);
// 修改store的type_content
commitInfo({
[createLiveKeys.textScriptValue]: resultList,
});
// 提交
await submit();
await submit(type);
// 需要洗稿
if (createLiveInfo.value[createLiveKeys.isDisorganize]) {
//
await startConfuse();
} else {
loading.value = false;
submitSuccessed();
}
} else {
......@@ -305,19 +395,31 @@ export const processTextCallback = () => {
}
});
let resultList = await audioStart(audio_list, false);
console.log('提交的个数');
console.log(resultList.length);
// 提交
if (customRegenerate) {
await customRegenerate(resultList);
} else {
await regenerate(resultList, successCallback);
}
loading.value = false;
}
}
}
} catch (e) {
console.log(e);
}
};
const openInterval = (isConfuse: boolean) => {
const openInterval = (
isConfuse: boolean,
type: string = 'create',
successCallback: boolean = true,
uuid: string = '',
customRegenerate: any = false,
) => {
interval.value = window.setInterval(() => {
getTaskStatus(isConfuse);
getTaskStatus(isConfuse, type, successCallback, uuid, customRegenerate);
}, 3000);
};
......@@ -341,5 +443,8 @@ export const processTextCallback = () => {
submit,
submitSuccessed,
backHome,
currentConfuseId,
confuseList,
currentStartConfuse,
};
};
......@@ -15,6 +15,7 @@
</template>
<script lang="ts" setup>
import allRouter from '@/router';
import { useRoute } from 'vue-router';
const route = useRoute();
......
<template>
<div class="start-only-video-live">
<!-- <Button theme="green" @click="playVideo">开始播放</Button> -->
<AddVideoPlay
v-model:progress="progress"
:playId="playId"
@playEnd="playEnd"
:video1="video"
:video2="video2"
></AddVideoPlay>
</div>
</template>
<script lang="ts" setup>
import Button from '@/components/Button.vue';
import { onBeforeUnmount, ref, watch } from 'vue';
import AddVideoPlay from '@/components/AddVideoPlay.vue';
const props = withDefaults(
defineProps<{
video: any;
video2: any;
playId?: any;
modelValue: any;
}>(),
{
playId: 0,
},
);
const videoRef1 = ref<HTMLVideoElement>();
let interval1 = null;
const progress = ref(0);
const emit = defineEmits(['update:modelValue', 'playEnd']);
watch(
() => progress.value,
(v) => {
emit('update:modelValue', v);
},
);
const playEnd = (id: any) => {
emit('playEnd', id);
};
const closeInterval = () => {
window.clearInterval(interval1);
clearInterval(interval1);
interval1 = null;
};
const playVideo = () => {
console.log(videoRef1.value);
videoRef1.value.play();
closeInterval();
interval1 = window.setInterval(() => {
// 播放结束
if (videoRef1.value.ended) {
closeInterval();
}
}, 100);
};
onBeforeUnmount(() => {
closeInterval();
});
</script>
<style lang="less">
.start-only-video-live {
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
}
</style>
......@@ -12,7 +12,7 @@
maxHeight: maxHeight + 'px',
}"
>
<Grid :length="digitalList.list.length" :rowGap="12" :marginLeft="8">
<div class="create-digital-person-grid">
<template v-for="item in digitalList.list" :key="item.id">
<CardOne
:row="item"
......@@ -23,7 +23,7 @@
@change="onCardChange"
></CardOne>
</template>
</Grid>
</div>
</div>
</div>
</div>
......@@ -31,10 +31,9 @@
<script lang="ts" setup>
import Loading from '@/components/loading.vue';
import Grid from '@/components/Grid.vue';
import Select from '@/components/Select.vue';
import CardOne from '@/components/cardOne.vue';
import { ref, onMounted, reactive, watch, computed } from 'vue';
import { ref, onMounted, reactive, watch, computed, onActivated } from 'vue';
import { getElBounding, getWindowClient, isDev } from '@/utils/tool';
import { useStore } from 'vuex';
import { createLiveKeys } from '@/service/CreateLive';
......@@ -84,12 +83,14 @@ const updateInfo = (info: any) => {
name = info.name;
digital_man_id = info.digital_man_id;
} else if (info.content) {
// 草稿
name = info.content.name ? info.content.name : '';
digital_man_id = info.content.digital_man_id ? info.content.digital_man_id : '';
}
if (name) {
// 更新标题
store.commit('live/setName', name);
}
if (info.users_id !== 0) {
// 我的数字人
currentOption.value = '2';
......@@ -122,11 +123,13 @@ watch(
);
const onSelectChange = (value: string) => {
if (value) {
commitInfo({
[createLiveKeys.id_type]: value,
});
currentOption.value = value;
checkPerson();
}
};
// 从python获取视频路径
......@@ -158,6 +161,26 @@ const digitalList = reactive({
my: [],
});
const findIdinList = () => {
if (route.query.id) {
// 找到对应的id
let index1 = digitalList.my.findIndex((item: any) => item.id == route.query.id);
if (index1 !== -1) {
currentCard.value = digitalList.my[index1].id;
}
let index2 = digitalList.admin.findIndex((item: any) => item.id == route.query.id);
if (index2 !== -1) {
currentCard.value = digitalList.admin[index2].id;
}
if (currentCard.value) {
let params = {
[createLiveKeys.id]: currentCard.value,
};
commitInfo(params);
}
}
};
const changeCurrentList = () => {
if (currentCard.value) {
// 找到对应的库
......@@ -189,6 +212,7 @@ const getList = async () => {
digitalList.admin = res.adminList;
// digitalList.admin = digitalList.admin.concat(res.adminList);
digitalList.my = res.myList;
findIdinList();
changeCurrentList();
checkPerson();
loading.value = false;
......@@ -196,15 +220,18 @@ const getList = async () => {
loading.value = false;
console.log(e);
}
// 提交默认参数
if (currentOption.value) {
let params = {
[createLiveKeys.id_type]: currentOption.value,
};
commitInfo(params);
}
};
onMounted(() => {
onActivated(() => {
// 获取数字人列表
getList();
// 提交默认参数
commitInfo({
[createLiveKeys.id_type]: currentOption.value,
});
});
watch(
......@@ -250,6 +277,12 @@ watch(
height: 150px;
}
}
.create-digital-person-grid {
display: grid;
justify-content: space-between;
grid-template-columns: repeat(auto-fill, 150px);
grid-gap: 12px;
}
.card-active {
border: 2px solid #00dfb0;
}
......
......@@ -2,7 +2,9 @@
<div class="create-live-script-setting">
<div class="all-select">
<Select :options="scriptTypeList" v-model="currentOption" @change="scriptTypeChange"></Select>
<template v-if="currentOption == scriptTypeText">
<CheckBox v-model="isDisorganize" @change="checkboxChange">GPT洗稿</CheckBox>
</template>
<template v-if="isDev()">
<Button
@click="
......@@ -152,6 +154,7 @@
v-model="item.data"
:config="ossConfig"
label="选择音频"
accept="wav"
@change="uploadEdit"
></MultipleUpload>
</div>
......@@ -191,7 +194,7 @@
</template>
<script lang="tsx" setup>
import { computed, onMounted, reactive, ref, watch } from 'vue';
import { computed, onActivated, onMounted, reactive, ref, watch } from 'vue';
import Button from '@/components/Button.vue';
import MultipleUpload from '@/components/MultipleUpload';
import CheckBox from '@/components/CheckBox.vue';
......@@ -423,6 +426,7 @@ const updateTonesInfo = (tone_id: any, phonetic_timbres_id: any) => {
};
const updateInfo = (info: any) => {
if (Object.keys(info).length) {
let type = '';
let type_content = '';
let phonetic_timbres_id = '';
......@@ -433,6 +437,7 @@ const updateInfo = (info: any) => {
phonetic_timbres_id = info.phonetic_timbres_id;
tone_id = info.tone_id;
} else if (info.content) {
// 草稿
type = info.content.type;
type_content = info.content.type_content;
phonetic_timbres_id = info.content.phonetic_timbres_id ? info.content.phonetic_timbres_id : '';
......@@ -442,12 +447,27 @@ const updateInfo = (info: any) => {
if (type == scriptTypeText) {
// 文本
currentOption.value = scriptTypeText;
if (type_content) {
// 内容
textareaValue.value = type_content;
// textareaValue.value = type_content;
textScriptList.value = type_content;
}
// 洗稿
isDisorganize.value = info.is_disorganize ? true : false;
} else {
// 音频
currentOption.value = scriptTypePhonetics;
mp3Url.value = type_content;
// mp3Url.value = type_content;
if (type_content) {
audioScriptList.value = type_content.map((item: any) => {
return {
data: item,
};
});
} else {
audioScriptList.value = [];
}
if (phonetic_timbres_id) {
phoneticsValue.value = phonetic_timbres_id;
}
......@@ -459,6 +479,7 @@ const updateInfo = (info: any) => {
// 更新info
updateTonesInfo(tone_id, phonetic_timbres_id);
}
};
watch(
......@@ -483,10 +504,32 @@ watch(
phoneticsInfo.value = {};
textareaValue.value = '';
currentOption.value = scriptTypeText;
audioScriptList.value = [];
textScriptList.value = [];
scriptTypeChange(scriptTypeText + '');
},
);
watch(
() => soundColorValue.value,
(v) => {
if (!v) {
soundColorItemChange();
}
},
);
watch(
() => tonesValue.value,
(v) => {
if (v) {
disabled.value = false;
} else {
disabled.value = true;
}
},
);
const openSoundColor = () => {
if (tonesValue.value) {
// 允许打开
......@@ -526,15 +569,6 @@ const soundColorItemChange = (item: any = false) => {
}
};
watch(
() => soundColorValue.value,
(v) => {
if (!v) {
soundColorItemChange();
}
},
);
// 音频 音色提交
const phoneticsItemChange = (item: any) => {
phoneticsInfo.value = item;
......@@ -557,17 +591,6 @@ const scriptTypeChange = (id: string | number) => {
});
};
watch(
() => tonesValue.value,
(v) => {
if (v) {
disabled.value = false;
} else {
disabled.value = true;
}
},
);
const getList = async () => {
let res = await getTonesList();
lists.tones = res.tones;
......@@ -591,13 +614,18 @@ onMounted(async () => {
// 提交默认脚本类型
commitInfo({
[createLiveKeys.scriptType]: currentOption.value,
// 文本脚本的uuid
[createLiveKeys.scriptUuid]: getUuid(),
});
// 获取音色音调列表
getList();
});
onActivated(() => {
commitInfo({
// 文本脚本的uuid
[createLiveKeys.scriptUuid]: getUuid(),
});
});
</script>
<style lang="less">
......
......@@ -66,25 +66,26 @@ import ChoseDigitalPerson from './components/ChoseDigitalPerson.vue';
import HomeSvg from '@/assets/svg/createLive/home.svg';
import InteractSvg from '@/assets/svg/createLive/interact.svg';
import ScriptsSvg from '@/assets/svg/createLive/scripts.svg';
import { computed, onMounted, ref, onBeforeUnmount, onActivated } from 'vue';
import { getElBounding, show_message, DataType } from '@/utils/tool';
import { computed, onMounted, onBeforeMount, ref, onBeforeUnmount, onActivated, onDeactivated } from 'vue';
import { getElBounding, show_message, DataType, dimensionalConvert } from '@/utils/tool';
import { useStore } from 'vuex';
import { createLiveKeys, scriptTypeText, scriptTypePhonetics } from '@/service/CreateLive';
import { createLiveTask, getLiveTaskInfo, createDrafts, getDraftsDetail, liveTts } from '@/utils/api/userApi';
import { useRoute, useRouter } from 'vue-router';
import { useRoute, useRouter, onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router';
import routerConfig from '@/router/tool';
import { onUpdateLiveTask } from '@/service/Common';
import { createLiveRouteKey } from '@/constants/token';
import { callPyjsInWindow } from '@/utils/pyqt';
import { useLiveInfoSubmit } from '@/hooks/useStoreCommit';
import { processTextCallback } from './hooks/scripts';
import { processTextCallback } from '@/hooks/useScript';
import CustomException from '@/utils/error';
const { loading, initNum, currentSetp, openInterval, filterFiled, backHome, submitSuccessed, submit, initCreateStore } =
processTextCallback();
const [commitInfo] = useLiveInfoSubmit();
const store = useStore();
const route = useRoute();
const routeQuery = route.query;
// 离开页面前的query
const currentQuery = ref({});
const router = useRouter();
const liveImage = computed(() => store.getters['live/getLiveimage']);
// 创建直播的已有的字段
......@@ -173,19 +174,29 @@ const getEditInfo = async (id: any, type: string) => {
store.commit('live/setEditLive', res.data);
let params: any = {
[createLiveKeys.id]: res.data.digital_man_id,
[createLiveKeys.id_type]: '',
[createLiveKeys.scriptType]: res.data.type + '',
[createLiveKeys.textTones]: res.data.tone_id,
[createLiveKeys.commentMethod]: 1,
[createLiveKeys.interactiveLibrary]: res.data.interaction_ids,
};
if (res.data.type == '2') {
// 文本
params[createLiveKeys.textSoundColor] = res.data.phonetic_timbres_id;
params[createLiveKeys.textScriptValue] = res.data.type_content;
params[createLiveKeys.textScriptList] = [res.data.type_content];
params[createLiveKeys.isDisorganize] = res.data.is_disorganize ? true : false;
} else {
// 音频音色
params[createLiveKeys.phoneticsSoundColor] = res.data.phonetic_timbres_id;
params[createLiveKeys.phoneticsFile] = res.data.type_content;
params[createLiveKeys.audioScriptList] = res.data.type_content.map((item: any) => {
return {
data: item,
};
});
}
// 更新标题
if (res.data.name) {
store.commit('live/setName', res.data.name);
}
commitInfo(params);
}
......@@ -197,19 +208,31 @@ const getEditInfo = async (id: any, type: string) => {
let content = item.content;
let params: any = {
[createLiveKeys.id]: content.digital_man_id,
[createLiveKeys.id_type]: '',
[createLiveKeys.scriptType]: content.type + '',
[createLiveKeys.textTones]: content.tone_id,
[createLiveKeys.commentMethod]: 1,
[createLiveKeys.interactiveLibrary]: content.interaction_ids,
};
if (res.data.type == '2') {
// 文本
params[createLiveKeys.textSoundColor] = content.phonetic_timbres_id ? content.phonetic_timbres_id : '';
params[createLiveKeys.textScriptValue] = content.type_content ? content.type_content : '';
if (content.type_content) {
params[createLiveKeys.textScriptList] = [content.type_content];
}
} else {
// 音频音色
params[createLiveKeys.phoneticsSoundColor] = content.phonetic_timbres_id ? content.phonetic_timbres_id : '';
params[createLiveKeys.phoneticsFile] = content.type_content ? content.type_content : '';
if (content.type_content) {
params[createLiveKeys.phoneticsFile] = content.type_content.map((item: any) => {
return {
data: item,
};
});
}
}
// 更新标题
if (res.data.name) {
store.commit('live/setName', res.data.name);
}
commitInfo(params);
}
......@@ -317,14 +340,12 @@ const onSaveDrafts = async () => {
}
};
// 编辑保存
const onEditSave = async () => {
let status = currentModuleField();
if (status) {
// 可以提交
// 编辑时音频提交
const editAudioSave = async () => {
try {
let params = filterFiled();
loading.value = true;
let res: any = await onUpdateLiveTask(route.query.id, filterFiled());
let res: any = await onUpdateLiveTask(route.query.id, params);
if (res) {
if (route.query.type === 'edit') {
// 通知python删除对应的output.mp4
......@@ -340,44 +361,69 @@ const onEditSave = async () => {
loading.value = false;
console.log(e);
}
}
};
const confirm = async () => {
// 确定生成
if (!liveName.value) {
show_message('请输入标题');
return;
}
// 提交任务并洗稿
const submitTaskAndConfuse = async (type: string) => {
let item = createLiveInfo.value;
if (item[createLiveKeys.scriptType] == scriptTypeText) {
// 文本脚本
loading.value = true;
for (let i = 0; i < item[createLiveKeys.textScriptList].length; i++) {
// 转一维数组
let newList = dimensionalConvert(item[createLiveKeys.textScriptList]);
for (let i = 0; i < newList.length; i++) {
let row = newList[i];
let params = {
// 音色
phonetic_timbres_id: item[createLiveKeys.textSoundColor],
// 音调
tone_id: item[createLiveKeys.textTones],
content: item[createLiveKeys.textScriptList][i].content,
uuid: item[createLiveKeys.textScriptList][i].uuid,
content: row.content,
uuid: item[createLiveKeys.scriptUuid],
};
// 生成音频
let res: any = await liveTts(params);
if (res.code == 0) {
// 通过uuid找到对应的对象
let index = item[createLiveKeys.textScriptList].findIndex((it: any) => it.uuid == params.uuid);
let index = newList.findIndex((it: any) => it.uuid == params.uuid);
if (index !== -1) {
let list = JSON.parse(JSON.stringify(item[createLiveKeys.textScriptList]));
let list = JSON.parse(JSON.stringify(newList));
list[i].task_id = res.data.task_id;
commitInfo({
[createLiveKeys.textScriptList]: list,
});
}
} else {
throw new CustomException('音频任务提交失败');
}
}
// 开启轮询
openInterval(false);
openInterval(false, type);
};
// 编辑保存
const onEditSave = async () => {
let status = currentModuleField();
if (status) {
// 判断脚本类型
if (createLiveInfo.value[createLiveKeys.scriptType] == scriptTypeText) {
// 文本脚本
submitTaskAndConfuse('update');
} else {
editAudioSave();
}
}
};
const confirm = async () => {
// 确定生成
if (!liveName.value) {
show_message('请输入标题');
return;
}
let item = createLiveInfo.value;
if (item[createLiveKeys.scriptType] == scriptTypeText) {
// 提交并洗稿
submitTaskAndConfuse('create');
} else {
// 音频脚本
try {
......@@ -394,26 +440,60 @@ const confirm = async () => {
}
};
onMounted(() => {
const initPage = () => {
let type = route.query.type;
// 清空缓存数据
if (type === 'new') {
submitSuccessed('', false);
}
};
onBeforeMount(() => {
initPage();
});
const enterPageEvent = () => {
initPage();
let query = route.query;
let obj = getElBounding(publicTool.value);
toolHeight.value = obj.height;
if (routeQuery.id && routeQuery.type) {
if (query.id && query.type) {
// 获取编辑数据
getEditInfo(routeQuery.id, routeQuery.type);
getEditInfo(query.id, query.type);
}
store.commit('live/setName', route.query.title ? route.query.title : '');
// 记录本次路由
window.localStorage.setItem(createLiveRouteKey, JSON.stringify(route.query));
// 添加导航
let newQuery = JSON.parse(JSON.stringify(query));
if (newQuery.type === 'new') {
delete newQuery.type;
}
store.commit('navbar/setNavbar', {
path: routerConfig.createLive.path,
query: route.query,
query: newQuery,
});
});
};
// 缓存进入
onActivated(() => {
store.commit('live/setName', route.query.title ? route.query.title : '');
// 初始化页面的参数
if (currentQuery.value.type === 'new' && route.query.type === 'edit') {
submitSuccessed('', false);
}
enterPageEvent();
});
// 路由离开前保存query
onBeforeRouteLeave(() => {
currentQuery.value = route.query;
let type = currentQuery.value.type;
if (type === 'edit' || type === 'edit_drafts') {
submitSuccessed('', false);
}
});
// 缓存离开
// onDeactivated(() => {});
onBeforeUnmount(() => {
// 清空选择的数字人
store.commit('live/setLiveImage', '');
......
......@@ -98,6 +98,7 @@ const confirm = () => {
query: {
id: currentCard.value,
title: '',
type: 'new',
},
});
};
......
......@@ -158,6 +158,7 @@ const dialogConfirm = () => {
query: {
id: currentCard.value,
title: liveName.value,
type: 'new',
},
});
};
......
......@@ -105,7 +105,7 @@ export const getLiveInteraction = async (select: boolean = false) => {
};
// 更新直播内容
export const onUpdateLiveTask = async (id: number | string, data: any) => {
export const onUpdateLiveTask = async (id: any, data: any) => {
try {
let res: any = await updateLiveTask(id, data);
if (res.code == 0) {
......
......@@ -11,3 +11,12 @@ export const LIVE_AUDIT_STATUS = {
LIVE_AUDIT_STATUS_FINISH: 3, // 己完成
LIVE_AUDIT_STATUS_ERROR: 4, // 审核失败
};
/**
* 洗稿状态(直播页面下一个视频是否准备完毕)
*/
export const CONFUSE_STATUS = {
CONFUSE_STATUS_WAIT: 1, // 未提交
CONFUSE_STATUS_PROGRESS: 2, // 进行中
CONFUSE_STATUS_SUCCESS: 3, // 已完成
};
......@@ -33,13 +33,18 @@ type StateType = typeof state;
const mutations = {
setName(state: StateType, info: string) {
if (info) {
state.name = info;
} else {
state.name = '';
}
},
// 创建直播时的参数
setLiveInfo(state: StateType, info: any) {
Object.keys(info).forEach((item: any) => {
state.createLive[item] = info[item];
});
console.log(state.createLive);
},
initLiveInfo(state: StateType) {
state.createLive = initParams();
......
import routerConfig from '@/router/tool';
import { createLiveRouteKey } from '@/constants/token';
const imgs = {
home: new URL('../../assets/svg/home/home.svg', import.meta.url).href,
......@@ -43,6 +44,10 @@ const mutations = {
}
state.navbarList.push(info);
}
if (info.path == routerConfig.createLive.path) {
// 记录创建直播的参数
window.localStorage.setItem(createLiveRouteKey, JSON.stringify(info.query));
}
},
};
......
......@@ -361,9 +361,9 @@ export const liveContentRegenerateCallback = (data: any) => {
};
// 重新生成直播
export const liveTaskRegenerate = () => {
export const liveTaskRegenerate = (id: any, data: any) => {
const header = getHeader();
return request.post(`/api/live/task/{id}/regenerate`, '', {
return request.post(`/api/live/task/${id}/regenerate`, data, {
headers: {
...header,
},
......
......@@ -68,7 +68,6 @@ export async function audioMerge(filePaths) {
}
offset += Math.round(buffer.duration * sampleRate);
});
// 导出合并后的音频数据为 WAV 文件
const mergedData = exportBufferAsWav(mergedBuffer);
const blob = new Blob([mergedData], { type: 'audio/wav' });
......
import { show_message } from './tool';
class CustomException extends Error {
constructor(message) {
super(message);
this.name = 'CustomException';
show_message(message, 'error');
}
}
export default CustomException;
......@@ -263,3 +263,22 @@ export const downloadBlobFile = (blob: Blob, name: string = 'test') => {
// 清理 Blob URL
URL.revokeObjectURL(url);
};
// 二维数组转一维数组
export const dimensionalConvert = (list: any[]) => {
let convertList = [];
for (let i = 0; i < list.length; i++) {
let items = list[i];
if (DataType(items, 'array')) {
// 是数组
for (let j = 0; j < items.length; j++) {
let item = items[j];
convertList.push(item);
}
} else {
// 子元素不是数组,直接返回
return list;
}
}
return convertList;
};
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