Commit c7731fcb by haojie

洗稿

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