Commit 1b6b2a08 by haojie

创建音色页面重复请求的问题

parent 13b6278a
......@@ -62,6 +62,7 @@
</template>
<script setup lang="ts">
import { liveDefaultVolume } from '@/constants/token';
import ConfirmDialog from '@/components/ConfirmDialog.vue';
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { useStore } from 'vuex';
......@@ -148,7 +149,7 @@ const showActionEndVideo = ref(false);
const actionEndVideo = ref('');
// 初始音量
const initVolume = 1;
const initVolume = liveDefaultVolume;
// 第一个视频的音量
const firstVideoVolume = ref(initVolume);
// 第二个视频的音量
......
......@@ -146,6 +146,9 @@ export const videoAccept = 'mp4';
// 音频切割间隔时长
export const audioSplitDuration = 300;
// 直播页面音视频默认音量
export const liveDefaultVolume = 1;
// 是否使用测试uuid
export const getTestUuid = () => {
let isTest = false;
......
<template>
<div class="start-live-audio-box">
<div class="start-live-audio-content">
<div class="label">音频脚本</div>
<div class="play-audio-box">
<div class="line">
<PlayAudioSvg></PlayAudioSvg>
<Button theme="opacity" style="color: #fff" v-if="true" @click="showTextarea">查看文字脚本</Button>
</div>
<div class="custom-video-progress">
<CustomProgress :value="modelValue"></CustomProgress>
</div>
</div>
<div v-if="textareaStatus">
<CustomTextarea :disabled="true" class="reset-live-audio-textarea" v-model="textareaValue"></CustomTextarea>
</div>
</div>
<div class="start-live-audio-footer">
<div class="live-status">
<div class="live-icon">
<LiveSvg></LiveSvg>
</div>
<span>
<template v-if="route.query.is_live == '1'"> 直播中 </template>
<template v-else> 未开播 </template>
</span>
</div>
<div class="stop" v-if="route.query.is_live == '1'">
<!-- <span class="start-time">00:52:20</span> -->
<Button theme="opacity" @click="closeLive">关闭直播</Button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import CustomProgress from '@/components/Progress.vue';
import CustomTextarea from '@/components/textarea.vue';
import Button from '@/components/Button.vue';
import LiveSvg from '@/assets/svg/home/live.svg';
import PlayAudioSvg from '@/assets/svg/home/playAudio.svg';
import { closeLiveTask } from '@/utils/api/userApi';
import { ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import routerConfig from '@/router/tool';
import { show_message } from '@/utils/tool';
import { useStore } from 'vuex';
import { callPyjsInWindow } from '@/utils/pyqt';
const props = withDefaults(
defineProps<{
url: string;
value?: string;
modelValue: number;
}>(),
{
value: '',
},
);
const store = useStore();
const route = useRoute();
const router = useRouter();
const canPlay = ref(false);
watch(
() => props.url,
(v) => {
if (v) {
canPlay.value = true;
}
},
);
watch(
() => props.value,
(v) => {
if (v) {
textareaValue.value = v;
} else {
textareaValue.value = '';
}
},
);
const textareaStatus = ref(false);
const textareaValue = ref(props.value);
const changeRouteQuery = () => {
router.replace({
path: routerConfig.startLive.path,
name: routerConfig.startLive.name,
query: {
...route.query,
is_live: '0',
},
});
};
const showTextarea = () => {
textareaStatus.value = true;
};
const closeLive = async () => {
try {
let res: any = await closeLiveTask(route.query.id);
if (res.code == 0) {
show_message('关播成功', 'success');
// 通知视频暂停播放
store.commit('live/setLiveVideoStatus', {
play: false,
});
changeRouteQuery();
// 通知python刷新所有首页的直播列表
callPyjsInWindow('reloadLiveTaskList');
}
} catch (e) {
console.log(e);
}
};
</script>
<style lang="less">
@import '@/style/variables.less';
.start-live-audio-box {
display: flex;
flex-direction: column;
padding: 0 4px;
.start-live-audio-content {
flex: 1;
margin-top: 40px;
border-radius: 0px 3px 3px 3px;
border: 1px solid #464646;
background: #1e1e1e;
padding: 12px;
.label {
font-size: @size-15;
color: #fff;
margin-bottom: 12px;
}
.play-audio-box {
border-radius: 8px;
background: linear-gradient(355deg, #00b58f 0%, rgba(255, 255, 255, 0.8) 100%, rgba(255, 255, 255, 0.9) 100%);
height: 120px;
padding: 12px;
.dj(space-around);
flex-direction: column;
.line {
.dja(space-between);
}
}
.reset-live-audio-textarea {
margin-top: 12px;
.t-textarea__inner {
border-radius: 8px;
background: #454545;
font-size: @size-14;
}
}
}
.start-live-audio-footer {
font-size: @size-15;
color: #00cca2;
padding: 20px 0;
.dja(space-between);
.stop {
.dja();
.start-time {
font-size: @size-14;
color: #bababa;
font-weight: 600;
margin-right: 12px;
}
}
.live-status {
.da();
.live-icon {
background: #04ae8a;
border-radius: 50%;
width: 40px;
height: 40px;
.dja();
}
& > :last-child {
margin-left: 8px;
}
}
}
}
</style>
......@@ -97,9 +97,9 @@ import Button from '@/components/Button.vue';
import Textarea from '@/components/textarea.vue';
import SelectionPopup from '@/components/SelectionPopup.vue';
import { show_message } from '@/utils/tool';
import { onMounted, reactive, ref, watch } from 'vue';
import { onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue';
import { getTonesList } from '@/service/Common';
import { liveInteractionReply, closeLiveTask } from '@/utils/api/userApi';
import { liveInteractionReply, closeLiveTask, getHumanReplyCallback } from '@/utils/api/userApi';
import { useRoute, useRouter } from 'vue-router';
import routerConfig from '@/router/tool';
import { useStore } from 'vuex';
......@@ -109,6 +109,8 @@ const store = useStore();
const router = useRouter();
const route = useRoute();
let interval = null;
const lists = reactive({
tones: [],
soundColor: [],
......@@ -146,6 +148,11 @@ const changeRouteQuery = () => {
});
};
// 播放音频
const submiAudio = (url: string) => {
emit('createAudio', url);
};
// 关闭直播
const closeLive = async () => {
try {
......@@ -167,7 +174,40 @@ const closeLive = async () => {
}
};
// 获取人工回复回调
const getCallback = async () => {
try {
const res: any = await getHumanReplyCallback(route.query.id);
if (res.code == 0 && res.data.url) {
// 播放
submiAudio(res.data.url);
closeInterval();
loading.value = false;
}
} catch (e) {
console.log(e);
}
};
// 打开定时器
const openInterval = () => {
interval = window.setInterval(() => {
getCallback();
}, 3000);
};
// 关闭
const closeInterval = () => {
window.clearInterval(interval);
clearInterval(interval);
interval = null;
};
const submit = async () => {
if (loading.value) {
show_message('请等待上一条回复完成');
return;
}
if (!textTonesValue.value) {
show_message('音调必选');
return;
......@@ -180,17 +220,13 @@ const submit = async () => {
tone_id: textTonesValue.value,
};
let res: any = await liveInteractionReply(route.query.id, params);
if (res.code == 0 && res.data.status) {
console.log('播放音频');
// 播放音频
emit('createAudio', res.data.status);
} else {
console.log('没有音频', res.data);
console.log(route.query.id, params);
if (res.code == 0) {
// 开启轮询
openInterval();
}
loading.value = false;
} catch (e) {
loading.value = false;
closeInterval();
console.log(e);
}
};
......@@ -224,6 +260,10 @@ onMounted(async () => {
lists.tones = res.tones;
lists.soundColor = res.soundColor;
});
onBeforeUnmount(() => {
closeInterval();
});
</script>
<style lang="less">
......
......@@ -2,12 +2,19 @@
<div class="custom-interactive-response-page">
<Human @createAudio="createAudio"></Human>
<div v-show="false">
<audio :src="audioFile" ref="audioRef" @canplay="audioCanplay" @ended="audioEnded"></audio>
<audio
:volume="liveDefaultVolume"
:src="audioFile"
ref="audioRef"
@canplay="audioCanplay"
@ended="audioEnded"
></audio>
</div>
</div>
</template>
<script lang="ts" setup>
import { liveDefaultVolume } from '@/constants/token';
import { onBeforeUnmount, onMounted, ref } from 'vue';
import Human from './components/human.vue';
import { useRoute } from 'vue-router';
......
......@@ -236,14 +236,22 @@ export default function () {
const changeVideo = (url: string, index: number | boolean = false) => {
hideVideo.play = false;
hideVideo.playEnd = false;
if (hideVideo.url !== url) {
hideVideo.url = url;
}
if (index !== false) {
hideVideo.videoIndex = index;
}
};
// 找到所有已经播放完毕的主视频
let playEndVideos = realVideoList.value.filter((row: any, index: number) => {
if (row.remove && row.result && row.status) {
let playEndVideos = realVideoList.value.map((row: any, index: number) => {
if (row.remove && row.result && row.status && typeof index === 'number') {
return index;
}
});
// 再次过滤
playEndVideos = playEndVideos.map((row: any, index: number) => {
if (typeof index === 'number') {
return index;
}
});
......@@ -637,7 +645,6 @@ export default function () {
// 最后一个不是主视频,才有uuid
uuid = lastRow.uuid;
}
console.log(actionUrl, '动作列表');
realVideoList.value.push({
// 主视频列表
url: mainUrl,
......
......@@ -2,7 +2,7 @@
<div class="image-custom-my-person-box">
<Loading v-show="loading"></Loading>
<div class="my-vocal-items">
<template v-for="item in personList.list" :key="item.id">
<template v-for="item in list" :key="item.id">
<template v-if="item.audit_status == LIVE_AUDIT_STATUS.LIVE_AUDIT_STATUS_FINISH || true">
<div class="my-person-loading-item">
<Audio
......@@ -36,8 +36,8 @@
</div>
</template>
</template>
<template v-for="(item, index) in personList.list" :key="item.id">
<i v-if="index != personList.list.length - 1"></i>
<template v-for="(item, index) in list" :key="item.id">
<i v-if="index != list.length - 1"></i>
</template>
</div>
<ConfirmDialog v-model="confirmDialog" title="确认删除吗?" @confirm="confirm"></ConfirmDialog>
......@@ -49,56 +49,29 @@ import ChangeName from '@/components/changeName.vue';
import Audio from '@/components/Audio.vue';
import ConfirmDialog from '@/components/ConfirmDialog.vue';
import Loading from '@/components/loading.vue';
import { onActivated, reactive, ref } from 'vue';
import { getTonesList } from '@/service/Common';
import { ref } from 'vue';
import { LIVE_AUDIT_STATUS } from '@/service/Live';
const personList = reactive({
list: [],
});
const props = withDefaults(
defineProps<{
list: any[];
loading: boolean;
}>(),
{},
);
const emit = defineEmits(['playAudio']);
const confirmDialog = ref(false);
const loading = ref(false);
const isFirstRequest = ref(true);
// 音频开始直播
// 音频开始播放
const startPlay = (id: number) => {
// 修改play状态
personList.list.forEach((item: any) => {
if (item.id == id) {
item.play_status = true;
} else {
item.play_status = false;
}
});
emit('playAudio', id);
};
// 确认删除
const confirm = () => {
//
};
// 获取我的数字人列表
const getList = async () => {
try {
loading.value = true;
let res: any = await getTonesList(false);
res.soundColor.forEach((item: any) => {
item.play_status = false;
});
personList.list = res.soundColor;
loading.value = false;
} catch (e) {
loading.value = false;
console.log(e);
}
};
onActivated(() => {
if (isFirstRequest.value) {
getList();
}
});
</script>
<style lang="less">
......
<template>
<div class="image-custom-record">
<div class="record-items" v-for="item in recordList.list" :key="item.id">
<div class="record-items" v-for="item in list" :key="item.id">
<div class="left">
<Audio
:url="item.audio_url"
......@@ -29,46 +29,22 @@
<script lang="tsx" setup>
import Audio from '@/components/Audio.vue';
import { onMounted, reactive, ref } from 'vue';
import { getTonesList } from '@/service/Common';
import { ref } from 'vue';
import CustomizationStatus from '@/components/CustomizationStatus';
const recordList = reactive({
list: [],
});
const loading = ref(false);
// 获取我的数字人列表
const getList = async () => {
try {
loading.value = true;
let res: any = await getTonesList(false);
res.soundColor.forEach((item: any) => {
item.play_status = false;
});
recordList.list = res.soundColor;
loading.value = false;
} catch (e) {
loading.value = false;
console.log(e);
}
};
const props = withDefaults(
defineProps<{
list: any[];
loading: boolean;
}>(),
{},
);
const emit = defineEmits(['playAudio']);
// 音频开始播放
const startPlay = (id: number) => {
// 修改play状态
recordList.list.forEach((item: any) => {
if (item.id == id) {
item.play_status = true;
} else {
item.play_status = false;
}
});
emit('playAudio', id);
};
onMounted(() => {
getList();
});
</script>
<style lang="less">
......
......@@ -11,10 +11,10 @@
>
<CustomTabs v-model="currentTab" theme="dark2">
<CustomTabPanel name="1" label="我的音色">
<MyDigitalPerson></MyDigitalPerson>
<MyDigitalPerson :list="personList.list" :loading="loading" @playAudio="myAudioPlay"></MyDigitalPerson>
</CustomTabPanel>
<CustomTabPanel name="2" label="生成记录">
<Record></Record>
<Record :list="personList.record" :loading="loading" @playAudio="recordAudioPlay"></Record>
</CustomTabPanel>
</CustomTabs>
</Customizable>
......@@ -34,11 +34,12 @@ import MyDigitalPerson from './components/MyDigitalPerson.vue';
import CustomTabs from '@/components/CustomTabs';
import CustomTabPanel from '@/components/CustomTabPanel';
import Customizable from '@/components/Customizable';
import { ref, onMounted, onActivated } from 'vue';
import { ref, onMounted, onActivated, reactive } from 'vue';
import { customizedPhoneticSubmission } from '@/utils/api/userApi';
import { show_message } from '@/utils/tool';
import { dimensionalConvert, show_message } from '@/utils/tool';
import { useStore } from 'vuex';
import routerConfig from '@/router/tool';
import { getTonesList } from '@/service/Common';
const store = useStore();
......@@ -48,6 +49,11 @@ const imgs = {
};
const currentTab = ref('1');
const personList = reactive({
list: [],
record: [],
});
const loading = ref(false);
const getIcon = () => {
return <img src={imgs.speak} style="" />;
......@@ -79,6 +85,47 @@ const submit = async (params: any) => {
}
};
// 获取我的数字人列表
const getList = async () => {
try {
loading.value = true;
let res: any = await getTonesList(false);
res.soundColor.forEach((item: any) => {
item.play_status = false;
});
personList.list = res.soundColor;
// 复制一份给记录列表
personList.record = dimensionalConvert(res.soundColor);
loading.value = false;
} catch (e) {
loading.value = false;
console.log(e);
}
};
// 我的音色开始播放
const myAudioPlay = (id: number) => {
// 修改play状态
personList.list.forEach((item: any) => {
if (item.id == id) {
item.play_status = true;
} else {
item.play_status = false;
}
});
};
// 音色记录开始播放
const recordAudioPlay = (id: number) => {
personList.record.forEach((item: any) => {
if (item.id == id) {
item.play_status = true;
} else {
item.play_status = false;
}
});
};
onMounted(() => {
store.commit('navbar/setNavbar', {
path: routerConfig.VocalCustomization.path,
......@@ -86,6 +133,7 @@ onMounted(() => {
});
onActivated(() => {
getList();
store.commit('navbar/setNavbar', {
path: routerConfig.VocalCustomization.path,
});
......
......@@ -258,6 +258,16 @@ export const liveInteractionReply = (id: string | number, data) => {
});
};
// 获取人工回复回调
export const getHumanReplyCallback = (id: any) => {
const header = getHeader();
return request.get(`/api/live/interaction/${id}/reply`, {
headers: {
...header,
},
});
};
// 形象定制提交
export const customizedImageSubmission = (data: any) => {
const header = getHeader();
......
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