Commit 4bb22ea8 by haojie

动作

parent ebbd8963
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
.custom-real-upload-component { .custom-real-upload-component {
width: 572px; // width: 572px;
height: 200px; height: 200px;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
......
...@@ -237,6 +237,7 @@ export default defineComponent({ ...@@ -237,6 +237,7 @@ export default defineComponent({
url: '', url: '',
ref: null, ref: null,
}); });
Curfile.status = 1;
openpercentage(); openpercentage();
return alyOssUpload(props.config, file, UploadSuccessCallback, UploadErrorCallback, uuid); return alyOssUpload(props.config, file, UploadSuccessCallback, UploadErrorCallback, uuid);
}; };
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
:autoWidth="autoWidth" :autoWidth="autoWidth"
:placeholder="placeholder" :placeholder="placeholder"
:multiple="multiple" :multiple="multiple"
:align="align"
:clearable="clear"
@change="SelectChange" @change="SelectChange"
:popupProps="{ :popupProps="{
overlayClassName: [className, 'custom-select-popup'], overlayClassName: [className, 'custom-select-popup'],
...@@ -27,12 +29,16 @@ const props = withDefaults( ...@@ -27,12 +29,16 @@ const props = withDefaults(
className?: string; className?: string;
autoWidth?: boolean; autoWidth?: boolean;
multiple?: boolean; multiple?: boolean;
align?: string;
clear?: boolean;
}>(), }>(),
{ {
width: '50%', width: '50%',
placeholder: '请选择', placeholder: '请选择',
autoWidth: true, autoWidth: true,
multiple: false, multiple: false,
align: 'left',
clear: false,
}, },
); );
const emit = defineEmits(['update:modelValue', 'change']); const emit = defineEmits(['update:modelValue', 'change']);
...@@ -41,7 +47,11 @@ const SelectValue = ref(props.modelValue); ...@@ -41,7 +47,11 @@ const SelectValue = ref(props.modelValue);
watch( watch(
() => SelectValue.value, () => SelectValue.value,
(v) => { (v) => {
emit('update:modelValue', v); if (v) {
emit('update:modelValue', v);
} else {
emit('update:modelValue', '');
}
}, },
); );
watch( watch(
...@@ -117,13 +127,22 @@ const SelectChange = (value: string | any) => { ...@@ -117,13 +127,22 @@ const SelectChange = (value: string | any) => {
background-color: #181818; background-color: #181818;
border: none; border: none;
border-radius: 8px; border-radius: 8px;
.t-input__clear {
.t-icon {
color: #00dddd;
}
}
.t-input__inner { .t-input__inner {
text-align: center;
color: #ffffff; color: #ffffff;
&::placeholder { &::placeholder {
color: #888fa1; color: #888fa1;
} }
} }
&:hover {
.t-fake-arrow {
color: #00dddd;
}
}
} }
.t-is-focused { .t-is-focused {
box-shadow: 0px 0px 0px 1px #00dddd; box-shadow: 0px 0px 0px 1px #00dddd;
......
@import '@/style/variables';
.c-radio-group {
.da();
.default-radio {
.da();
.dot {
border-radius: 50%;
border: 1px solid #9f9f9f;
background: transparent;
width: 18px;
height: 18px;
cursor: pointer;
transition: all 0.2s;
}
.group-label {
font-size: @size-13;
color: #b4b4b4;
margin-left: 6px;
transition: all 0.2s;
}
}
.default-radio + .default-radio {
margin-left: 12px;
}
.radio-active {
.dot {
border-color: #04ae8a;
background: #04ae8a;
transition: all 0.2s;
}
.group-label {
color: #04ae8a;
transition: all 0.2s;
}
}
}
import './index.less';
import { computed, defineComponent } from 'vue';
export default defineComponent({
props: {
modelValue: [String, Number],
list: {
type: Array,
default: () => [],
},
cancel: {
type: Boolean,
default: false,
},
},
emits: ['update:modelValue'],
setup(props, { emit }) {
const currentValue = computed({
get() {
return props.modelValue;
},
set(value) {
if (props.cancel && currentValue.value == value) {
emit('update:modelValue', '');
} else {
emit('update:modelValue', value);
}
},
});
const groupEvent = (item: any) => {
currentValue.value = item.value;
};
return () => (
<div class="c-radio-group">
{props.list.map((item: any) => (
<div key={item.value} class={['default-radio', currentValue.value == item.value ? 'radio-active' : '']}>
<div class="dot" onClick={groupEvent.bind(this, item)}></div>
<div class="group-label">{item.label}</div>
</div>
))}
</div>
);
},
});
import { computed, onBeforeUnmount, ref, watch } from 'vue'; import { computed, onBeforeUnmount, ref, watch } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { createLiveKeys, createLiveVersion, filterFiled, getAudioStartTimeAndEndTime } from '@/service/CreateLive'; import { createLiveKeys, createLiveVersion, filterFiled, onAudioProcessed } from '@/service/CreateLive';
import { getLiveTtsCallback, createLiveTask, liveTts, liveTaskRegenerate } from '@/utils/api/userApi'; import { getLiveTtsCallback, createLiveTask, liveTts, liveTaskRegenerate } from '@/utils/api/userApi';
import { ecursionDeepCopy, isDev, show_message } from '@/utils/tool'; import { TableSortAsc, dimensionalConvert, ecursionDeepCopy, isDev, show_message } from '@/utils/tool';
import { useLiveInfoSubmit } from '@/hooks/useStoreCommit'; import { useLiveInfoSubmit } from '@/hooks/useStoreCommit';
import { onUpdateLiveTask, audioStart, uploadToAly } from '@/service/Common'; import { onUpdateLiveTask, audioStart, uploadToAly } 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, writeLog } from '@/utils/pyqt'; import { callPyjsInWindow, writeLog } from '@/utils/pyqt';
// 轮询处理文本脚本语音生成回调 // 轮询处理文本脚本语音生成回调
...@@ -45,6 +44,7 @@ export const processTextCallback = () => { ...@@ -45,6 +44,7 @@ export const processTextCallback = () => {
tone_id: item[createLiveKeys.textTones], tone_id: item[createLiveKeys.textTones],
content: list[i].content, content: list[i].content,
uuid: getTaskId(true), uuid: getTaskId(true),
id: i,
}; };
// 生成音频 // 生成音频
await liveTts(params); await liveTts(params);
...@@ -125,8 +125,11 @@ export const processTextCallback = () => { ...@@ -125,8 +125,11 @@ export const processTextCallback = () => {
} }
// 回首页 // 回首页
backHome(); backHome();
loading.value = false;
return true;
} }
loading.value = false; loading.value = false;
return false;
} catch (e) { } catch (e) {
writeLog({ writeLog({
name: '更新直播失败', name: '更新直播失败',
...@@ -134,6 +137,7 @@ export const processTextCallback = () => { ...@@ -134,6 +137,7 @@ export const processTextCallback = () => {
}); });
loading.value = false; loading.value = false;
console.log(e); console.log(e);
return false;
} }
} }
}; };
...@@ -224,18 +228,21 @@ export const processTextCallback = () => { ...@@ -224,18 +228,21 @@ export const processTextCallback = () => {
}); });
if (res.code == 0) { if (res.code == 0) {
if (isDev()) { if (isDev()) {
for (let i = 0; i < 3; i++) { for (let i = 0; i < 1; i++) {
let params = { let params = {
data: { data: {
audio_address: audio_address:
'http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/jupiter-flow/tmp/e56d8750eb3a44f9930f73703489acb1.wav?Expires=1692087730&OSSAccessKeyId=LTAIUpwNp2H7pBG5&Signature=FtKSld5Dn55po9GyTm%2BefRKmPqw%3D', 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-16fcc74a89-d3f1-4545-a17c-d155dfa7978f.wav',
task_id: 0, task_id: 0,
id: i,
}, },
}; };
res.data.push(params); res.data.push(params);
} }
} }
if (res.data.length) { if (res.data.length) {
// 根据id升序排列
res.data = TableSortAsc(res.data, 'data.id');
console.log('音频任务回调成功'); console.log('音频任务回调成功');
console.log(res.data); console.log(res.data);
if (!isConfuse) { if (!isConfuse) {
...@@ -243,8 +250,8 @@ export const processTextCallback = () => { ...@@ -243,8 +250,8 @@ export const processTextCallback = () => {
// 关闭定时器 // 关闭定时器
closeInterval(); closeInterval();
let list = JSON.parse(JSON.stringify(createLiveInfo.value[createLiveKeys.textScriptList])); let list = JSON.parse(JSON.stringify(createLiveInfo.value[createLiveKeys.textScriptList]));
let audio_list = []; for (let i = 0; i < res.data.length; i++) {
res.data.forEach((item: any) => { let item = res.data[i];
// 根据task_id更新数组对象 // 根据task_id更新数组对象
let data = item.data; let data = item.data;
if ( if (
...@@ -252,33 +259,41 @@ export const processTextCallback = () => { ...@@ -252,33 +259,41 @@ export const processTextCallback = () => {
data.audio_address && data.audio_address &&
(typeof data.task_id === 'string' || typeof data.task_id === 'number') (typeof data.task_id === 'string' || typeof data.task_id === 'number')
) { ) {
audio_list.push(data.audio_address); console.log(list, 'list');
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) {
list[index].audio_address = data.audio_address; list[index].audio_address = data.audio_address;
// 音频处理
let resultList = await audioStart([data.audio_address], true);
// 转一维
resultList = dimensionalConvert(resultList);
let newList = resultList.map((row: any) => {
return {
content: row.content,
movement_type: list[index].movement_type,
movement_name: list[index].movement_name,
};
});
// 要提交的数组
list[index].newList = newList;
commitInfo({ commitInfo({
[createLiveKeys.textScriptList]: list, [createLiveKeys.textScriptList]: list,
}); });
} else {
console.log('未找到对应的task_id');
} }
} else { } else {
show_message('缺少音频或id'); show_message('缺少音频或id');
} }
});
// 获取音频时长
let durationList = await getAudioStartTimeAndEndTime(res.data);
console.log(durationList, '不洗稿durationList');
if (!audio_list.length) {
throw new CustomException('没有要处理的音频');
} }
console.log('执行完毕,准备提交');
let resultList = await audioStart(audio_list, true);
// 修改store的type_content
commitInfo({
[createLiveKeys.textScriptValue]: resultList,
});
// 提交 // 提交
await submit(type); let status = await submit(type);
if (!status) {
show_message('创建失败');
loading.value = false;
return;
}
// 需要洗稿 // 需要洗稿
if (createLiveInfo.value[createLiveKeys.isDisorganize]) { if (createLiveInfo.value[createLiveKeys.isDisorganize]) {
...@@ -306,28 +321,15 @@ export const processTextCallback = () => { ...@@ -306,28 +321,15 @@ export const processTextCallback = () => {
} }
} }
} else { } else {
// 旧版洗稿回调,直播时用的是这个
if (res.data.length >= confuseLength) { if (res.data.length >= confuseLength) {
closeInterval(); closeInterval();
let audio_list = []; let list = await onAudioProcessed(res, ecursionDeepCopy(createLiveInfo.value));
// 洗稿任务
res.data.forEach((item: any) => {
let data = item.data;
if (data && data.audio_address) {
audio_list.push(data.audio_address);
} else {
writeLog({
naem: 'useScript-洗稿缺少参数',
value: data,
});
show_message('洗稿缺少参数');
}
});
let resultList = await audioStart(audio_list, true);
// 提交 // 提交
if (customRegenerate) { if (customRegenerate) {
await customRegenerate(resultList); await customRegenerate(list);
} else { } else {
await regenerate(resultList, successCallback); await regenerate(list, successCallback);
} }
loading.value = false; loading.value = false;
} }
......
...@@ -167,12 +167,6 @@ const mergeCallback = (params: any) => { ...@@ -167,12 +167,6 @@ const mergeCallback = (params: any) => {
onMounted(async () => { onMounted(async () => {
// 将通知方法注入window // 将通知方法注入window
injectWindow('mergeCallback', mergeCallback); injectWindow('mergeCallback', mergeCallback);
// 传递用户token
try {
window.pyjs.setToken(getUserCookie());
} catch (e) {
console.error('没有pyjs');
}
// if (isDev()) { // if (isDev()) {
// mergeCallback({ // mergeCallback({
......
...@@ -147,6 +147,7 @@ const submitAudioTask = async (list: any[]) => { ...@@ -147,6 +147,7 @@ const submitAudioTask = async (list: any[]) => {
tone_id: liveDetail.value.tone_id, tone_id: liveDetail.value.tone_id,
content: list[i].content, content: list[i].content,
uuid: currentConfuseId.value, uuid: currentConfuseId.value,
id: i,
}; };
// 生成音频 // 生成音频
let res: any = await liveTts(params); let res: any = await liveTts(params);
...@@ -524,7 +525,10 @@ const submitVideo = () => { ...@@ -524,7 +525,10 @@ const submitVideo = () => {
let index = realVideoList.value.findIndex((item: any) => !item.remove && !item.submit); let index = realVideoList.value.findIndex((item: any) => !item.remove && !item.submit);
if (index !== -1) { if (index !== -1) {
realVideoList.value[index].submit = true; realVideoList.value[index].submit = true;
window.pyjs.run(realVideoList.value[index].url, routeQuery.id, route.query.window_index, index); let list = realVideoList.value[index].url.map((item: any) => {
return item.url;
});
window.pyjs.run(list, routeQuery.id, route.query.window_index, index);
console.log(`本次提交-${index}`); console.log(`本次提交-${index}`);
console.log(realVideoList.value); console.log(realVideoList.value);
} else { } else {
...@@ -629,12 +633,6 @@ onMounted(async () => { ...@@ -629,12 +633,6 @@ onMounted(async () => {
// 将通知方法注入window // 将通知方法注入window
injectWindow('mergeCallback', mergeCallback); injectWindow('mergeCallback', mergeCallback);
injectWindow('closeLive', closeLive); injectWindow('closeLive', closeLive);
// 传递用户token
try {
window.pyjs.setToken(getUserCookie());
} catch (e) {
console.error('没有pyjs');
}
// 获取后台互动 // 获取后台互动
startLiveInterval(); startLiveInterval();
......
import './index.less'; import './index.less';
import { defineComponent, ref } from 'vue'; import { defineComponent } from 'vue';
import { LIVE_AUDIT_STATUS } from '@/service/Live'; import { LIVE_AUDIT_STATUS } from '@/service/Live';
import CardOneVue from '@/components/cardOne.vue'; import CardOneVue from '@/components/cardOne.vue';
import Button from '@/components/Button.vue'; import Button from '@/components/Button.vue';
......
...@@ -82,7 +82,7 @@ export default defineComponent({ ...@@ -82,7 +82,7 @@ export default defineComponent({
url: item.url, url: item.url,
digital_man_id: currentCard.value, digital_man_id: currentCard.value,
}; };
if (!item.videoCover) { if (item.videoCoverBlob) {
let result = await alyOssUpload( let result = await alyOssUpload(
ossConfig.value, ossConfig.value,
item.videoCoverBlob, item.videoCoverBlob,
...@@ -111,17 +111,19 @@ export default defineComponent({ ...@@ -111,17 +111,19 @@ export default defineComponent({
name: routerConfig.createAction.name, name: routerConfig.createAction.name,
query: {}, query: {},
}); });
reset();
// 重新获取生产记录
getMovement();
} }
} else { } else {
let res: any = await createLiveMovement(list); let res: any = await createLiveMovement(list);
if (res.code == 0) { if (res.code == 0) {
show_message('提交成功,等待审核', 'success'); show_message('提交成功,等待审核', 'success');
reset(); reset();
// 重新获取生产记录
getMovement();
} }
} }
// 重新获取生产记录
getMovement();
globalLoading.value = false; globalLoading.value = false;
} catch (e) { } catch (e) {
globalLoading.value = false; globalLoading.value = false;
......
...@@ -2,23 +2,34 @@ ...@@ -2,23 +2,34 @@
<Dialog v-model="visible" @confirm="confirm"> <Dialog v-model="visible" @confirm="confirm">
<div class="text-script-dialog-body"> <div class="text-script-dialog-body">
<div class="input-box"> <div class="input-box">
<div class="label">标题:</div> <div class="label center">标题:</div>
<CustomInput v-model="titleValue" align="left" placeholder="请输入标题"></CustomInput> <CustomInput v-model="titleValue" align="left" placeholder="请输入标题"></CustomInput>
</div> </div>
<div class="input-box"> <div class="input-box">
<div class="label">内容:</div> <div class="label">内容:</div>
<CustomTextarea v-model="contentValue"></CustomTextarea> <CustomTextarea v-model="contentValue"></CustomTextarea>
</div> </div>
<div class="input-box">
<div class="label center">动作:</div>
<Select v-model="currentSelect" align="left" clear :options="actionList" :autoWidth="false"></Select>
<div class="radio-group-parent">
<CustomRadio v-model="currentRadio" :list="radioGroup" cancel></CustomRadio>
</div>
</div>
</div> </div>
</Dialog> </Dialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { watch, ref } from 'vue'; import { watch, ref, onMounted } from 'vue';
import Select from '@/components/Select.vue';
import Dialog from '@/components/Dialog.vue'; import Dialog from '@/components/Dialog.vue';
import CustomInput from '@/components/input/index.vue'; import CustomInput from '@/components/input/index.vue';
import CustomTextarea from '@/components/textarea.vue'; import CustomTextarea from '@/components/textarea.vue';
import { show_message } from '@/utils/tool'; import { show_message } from '@/utils/tool';
import { getLiveMovementList } from '@/service/Common';
import { movementTypeStart, movementTypeEnd } from '@/service/CreateLive';
import CustomRadio from '@/components/radio';
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
modelValue: boolean; modelValue: boolean;
...@@ -34,7 +45,50 @@ const visible = ref(props.modelValue); ...@@ -34,7 +45,50 @@ const visible = ref(props.modelValue);
const titleValue = ref(''); const titleValue = ref('');
const contentValue = ref(''); const contentValue = ref('');
// 当前选择的动作
const currentSelect = ref('');
const actionList = ref([]);
const currentRadio = ref('');
// 单选列表
const radioGroup = [
{
label: '开头插入',
value: movementTypeStart,
},
{
label: '结尾插入',
value: movementTypeEnd,
},
];
const getAction = async () => {
let list = await getLiveMovementList(true);
actionList.value = list.map((item: any) => {
return {
label: item.name,
value: item.id,
url: item.url,
};
});
};
onMounted(() => {
getAction();
});
const confirm = () => { const confirm = () => {
let movement_name = '';
let movement_url = '';
if (currentSelect.value) {
// 找到对应的数据
let obj = actionList.value.find((item: any) => item.value == currentSelect.value);
if (obj) {
movement_name = obj.label;
movement_url = obj.url;
}
}
if (titleValue.value && contentValue.value) { if (titleValue.value && contentValue.value) {
const { info } = props; const { info } = props;
visible.value = false; visible.value = false;
...@@ -42,6 +96,10 @@ const confirm = () => { ...@@ -42,6 +96,10 @@ const confirm = () => {
title: titleValue.value, title: titleValue.value,
content: contentValue.value, content: contentValue.value,
index: typeof info.index === 'number' ? info.index : false, index: typeof info.index === 'number' ? info.index : false,
movement_id: currentSelect.value,
movement_type: currentRadio.value,
movement_name: movement_name,
movement_url: movement_url,
}); });
// 清空 // 清空
...@@ -58,6 +116,13 @@ watch( ...@@ -58,6 +116,13 @@ watch(
if (Object.keys(v).length) { if (Object.keys(v).length) {
titleValue.value = v.title; titleValue.value = v.title;
contentValue.value = v.content; contentValue.value = v.content;
currentSelect.value = v.movement_id;
currentRadio.value = v.movement_type;
} else {
titleValue.value = '';
contentValue.value = '';
currentSelect.value = '';
currentRadio.value = '';
} }
}, },
); );
...@@ -88,6 +153,13 @@ watch( ...@@ -88,6 +153,13 @@ watch(
font-size: @size-14; font-size: @size-14;
white-space: nowrap; white-space: nowrap;
} }
.center {
.dja();
}
.radio-group-parent {
margin-left: 12px;
.da();
}
} }
.input-box + .input-box { .input-box + .input-box {
margin-top: 12px; margin-top: 12px;
......
<template>
<Dialog v-model="visible" @confirm="confirm" className="audio-script-dialog">
<div class="audio-script-dialog-body">
<div class="input-box">
<div class="label center">标题:</div>
<CustomInput v-model="titleValue" align="left" placeholder="请输入标题"></CustomInput>
</div>
<div class="input-box">
<div class="label">内容:</div>
<div class="value">
<MultipleUpload
v-model="audioList"
:config="ossConfig"
:computedDuration="true"
label="选择音频"
:accept="audioAccept"
></MultipleUpload>
</div>
</div>
<div class="input-box">
<div class="label center">动作:</div>
<Select v-model="currentSelect" align="left" clear :options="actionList" :autoWidth="false"></Select>
<div class="radio-group-parent">
<CustomRadio v-model="currentRadio" :list="radioGroup" cancel></CustomRadio>
</div>
</div>
</div>
</Dialog>
</template>
<script lang="ts" setup>
import { watch, ref, onMounted } from 'vue';
import Select from '@/components/Select.vue';
import Dialog from '@/components/Dialog.vue';
import CustomInput from '@/components/input/index.vue';
import { show_message } from '@/utils/tool';
import { getLiveMovementList } from '@/service/Common';
import { movementTypeStart, movementTypeEnd } from '@/service/CreateLive';
import CustomRadio from '@/components/radio';
import MultipleUpload from '@/components/MultipleUpload';
import { audioAccept } from '@/constants/token';
const props = withDefaults(
defineProps<{
modelValue: boolean;
info: any;
ossConfig: any;
}>(),
{},
);
const emit = defineEmits(['update:modelValue', 'submit']);
const visible = ref(props.modelValue);
// 标题
const titleValue = ref('');
// 音频列表
const audioList = ref([]);
// 当前选择的动作
const currentSelect = ref('');
const actionList = ref([]);
const currentRadio = ref('');
// 单选列表
const radioGroup = [
{
label: '开头插入',
value: movementTypeStart,
},
{
label: '结尾插入',
value: movementTypeEnd,
},
];
const getAction = async () => {
let list = await getLiveMovementList(true);
actionList.value = list.map((item: any) => {
return {
label: item.name,
value: item.id,
url: item.url,
};
});
};
onMounted(() => {
getAction();
});
const confirm = () => {
if (!titleValue.value) {
show_message('标题必填');
return;
}
if (!audioList.value.length) {
show_message('音频至少上传一个');
return;
}
let movement_name = '';
let movement_url = '';
if (currentSelect.value) {
// 找到对应的数据
let obj = actionList.value.find((item: any) => item.value == currentSelect.value);
if (obj) {
movement_name = obj.label;
movement_url = obj.url;
}
}
const { info } = props;
visible.value = false;
emit('submit', {
title: titleValue.value,
audioList: audioList.value,
index: typeof info.index === 'number' ? info.index : false,
movement_id: currentSelect.value,
movement_type: currentRadio.value,
movement_name: movement_name,
movement_url: movement_url,
});
// 清空
titleValue.value = '';
};
watch(
() => props.info,
(v) => {
if (Object.keys(v).length) {
titleValue.value = v.title;
audioList.value = v.audioList;
currentSelect.value = v.movement_id;
currentRadio.value = v.movement_type;
} else {
titleValue.value = '';
audioList.value = [];
currentSelect.value = '';
currentRadio.value = '';
}
},
);
watch(
() => visible.value,
(v) => {
emit('update:modelValue', v);
},
);
watch(
() => props.modelValue,
(v) => {
visible.value = v;
},
);
</script>
<style lang="less">
@import '@/style/variables';
.audio-script-dialog {
.t-dialog {
width: auto;
}
}
.audio-script-dialog-body {
margin: 16px 0;
.input-box {
display: flex;
.label {
color: #fff;
font-size: @size-14;
white-space: nowrap;
}
.center {
.dja();
}
.value {
flex: 1;
.custom-multiple-upload {
background-color: rgb(30, 30, 30);
width: 778px;
height: 256px;
.real-upload-content {
width: 100%;
.custom-real-upload-component {
width: 100%;
}
}
}
}
.radio-group-parent {
margin-left: 12px;
.da();
}
}
.input-box + .input-box {
margin-top: 12px;
}
}
</style>
...@@ -124,6 +124,15 @@ ...@@ -124,6 +124,15 @@
{{ item.content }} {{ item.content }}
</div> </div>
</div> </div>
<div class="action-box">
<div class="label">动作:</div>
<div class="value">
{{ item.movement_name }}
</div>
<div class="tag" v-if="item.movement_type">
{{ item.movement_type == 1 ? '开头插入' : '结尾插入' }}
</div>
</div>
</div> </div>
</ScriptTemplate> </ScriptTemplate>
</template> </template>
...@@ -137,34 +146,52 @@ ...@@ -137,34 +146,52 @@
<div class="script-setting-upload flex1 narrow-scrollbar" v-show="currentOption === scriptTypePhonetics"> <div class="script-setting-upload flex1 narrow-scrollbar" v-show="currentOption === scriptTypePhonetics">
<!-- edit --> <!-- edit -->
<template v-for="(item, index) in audioScriptList" :key="index"> <template v-for="(item, index) in audioScriptList" :key="index">
<ScriptTemplate height="250px" :showEdit="false" @edit="uploadAudioEdit(index)" @delete="onDeleteAudio(index)"> <ScriptTemplate height="250px" @edit="uploadAudioEdit(item, index)" @delete="onDeleteAudio(index)">
<div class="script-template-body__audio-add"> <div class="script-template-body__text">
<MultipleUpload <div class="title-box">
v-model="item.data" <div class="label">标题:</div>
:config="ossConfig" <div class="value">{{ item.title }}</div>
:computedDuration="true" </div>
label="选择音频" <div class="content-box">
:accept="audioAccept" <div class="label">内容:</div>
@change="uploadEdit" <div class="value narrow-scrollbar">
></MultipleUpload> <div class="uploaded-audio-list">
<div v-for="row in item.audioList" :key="row.url">
<AudioSvg></AudioSvg>
<div>
{{ row.file.name }}
</div>
</div>
</div>
</div>
</div>
<div class="action-box">
<div class="label">动作:</div>
<div class="value">
{{ item.movement_name }}
</div>
<div class="tag" v-if="item.movement_type">
{{ item.movement_type == 1 ? '开头插入' : '结尾插入' }}
</div>
</div>
</div> </div>
</ScriptTemplate> </ScriptTemplate>
</template> </template>
<!-- create --> <!-- create -->
<ScriptTemplate :showTool="false" height="250px"> <ScriptTemplate :showTool="false">
<div class="script-template-body__audio-add"> <div class="script-template-body__text-add" @click="addAudioScript">
<MultipleUpload <img :src="imgs.add" alt="" />
v-model="mp3UrlList" <div class="label">添加音频</div>
:config="ossConfig"
:computedDuration="true"
label="选择音频"
:accept="audioAccept"
@change="createUploadFile"
></MultipleUpload>
</div> </div>
</ScriptTemplate> </ScriptTemplate>
</div> </div>
<TextScriptDialog v-model="textScriptVisible" @submit="textScriptSubmit" :info="editTextInfo"></TextScriptDialog> <TextScriptDialog v-model="textScriptVisible" @submit="textScriptSubmit" :info="editTextInfo"></TextScriptDialog>
<AudioScriptDialog
v-model="audioScriptVisible"
:ossConfig="ossConfig"
@submit="audioScriptSubmit"
:info="editAudioInfo"
></AudioScriptDialog>
<ConfirmDialog <ConfirmDialog
v-model="confirmDeleteVisible" v-model="confirmDeleteVisible"
title="确定要删除该声音吗?" title="确定要删除该声音吗?"
...@@ -180,6 +207,7 @@ ...@@ -180,6 +207,7 @@
<script lang="tsx" setup> <script lang="tsx" setup>
import { computed, onMounted, reactive, ref, watch, toRaw } from 'vue'; import { computed, onMounted, reactive, ref, watch, toRaw } from 'vue';
import AudioSvg from '@/assets/svg/upload/audio.svg';
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';
...@@ -190,6 +218,7 @@ import Select from '@/components/Select.vue'; ...@@ -190,6 +218,7 @@ import Select from '@/components/Select.vue';
import SelectionPopup from '@/components/SelectionPopup.vue'; import SelectionPopup from '@/components/SelectionPopup.vue';
import { show_message, isDev, ecursionDeepCopy } from '@/utils/tool'; import { show_message, isDev, ecursionDeepCopy } from '@/utils/tool';
import { audioAccept } from '@/constants/token'; import { audioAccept } from '@/constants/token';
import AudioScriptDialog from './audioScriptDialog.vue';
import { import {
createLiveKeys, createLiveKeys,
scriptTypeList, scriptTypeList,
...@@ -201,6 +230,7 @@ import { useLiveInfoSubmit } from '@/hooks/useStoreCommit'; ...@@ -201,6 +230,7 @@ import { useLiveInfoSubmit } from '@/hooks/useStoreCommit';
import { getUploadConfig, getTonesList } from '@/service/Common'; import { getUploadConfig, getTonesList } from '@/service/Common';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { v4 } from 'uuid';
import useCopy from '@/hooks/useCopy'; import useCopy from '@/hooks/useCopy';
const { doCopy } = useCopy(); const { doCopy } = useCopy();
...@@ -232,6 +262,7 @@ const audioScriptList = ref([]); ...@@ -232,6 +262,7 @@ const audioScriptList = ref([]);
const scriptSettingText = ref<HTMLDivElement>(); const scriptSettingText = ref<HTMLDivElement>();
// 文本编辑时的行信息 // 文本编辑时的行信息
const editTextInfo = ref({}); const editTextInfo = ref({});
const editAudioInfo = ref({});
// 文本脚本删除时选择的下标 // 文本脚本删除时选择的下标
const deleteTextId = ref(); const deleteTextId = ref();
// 确认删除弹窗 // 确认删除弹窗
...@@ -266,6 +297,7 @@ const disabled = ref(true); ...@@ -266,6 +297,7 @@ const disabled = ref(true);
// 文本脚本弹窗 // 文本脚本弹窗
const textScriptVisible = ref(false); const textScriptVisible = ref(false);
const audioScriptVisible = ref(false);
// 阿里云上传配置 // 阿里云上传配置
const ossConfig = ref({}); const ossConfig = ref({});
...@@ -284,20 +316,6 @@ const textareaValue = ref(''); ...@@ -284,20 +316,6 @@ const textareaValue = ref('');
const currentOption = ref(scriptTypeText); const currentOption = ref(scriptTypeText);
// 音频脚本上传后
const createUploadFile = (list: any[], oldList: any[]) => {
// 添加到数组中
audioScriptList.value.push({
data: oldList,
});
// 提交到store
uploadChange();
setTimeout(() => {
// 清空当前url
mp3UrlList.value = [];
}, 0);
};
// 音频脚本编辑后 // 音频脚本编辑后
const uploadEdit = (list: any[], oldList: any[]) => { const uploadEdit = (list: any[], oldList: any[]) => {
uploadChange(); uploadChange();
...@@ -315,18 +333,11 @@ const onDeleteAudio = (index: number) => { ...@@ -315,18 +333,11 @@ const onDeleteAudio = (index: number) => {
}; };
// 编辑按钮 音频脚本 // 编辑按钮 音频脚本
const uploadAudioEdit = (index: number) => { const uploadAudioEdit = (item: any, index: number) => {
// 调用对应的上传事件 item.index = index;
if (uploadRef.value && uploadRef.value.length) { // 打开弹窗
let element: HTMLDivElement = uploadRef.value[index].$el; editAudioInfo.value = item;
if (element) { audioScriptVisible.value = true;
// 找到上传元素
let clickElement = element.getElementsByClassName('custom-upload-click-box');
if (clickElement && clickElement.length) {
clickElement[0].click();
}
}
}
}; };
// 洗稿checkbox变化 // 洗稿checkbox变化
...@@ -343,6 +354,11 @@ const addTextScript = () => { ...@@ -343,6 +354,11 @@ const addTextScript = () => {
textScriptVisible.value = true; textScriptVisible.value = true;
}; };
const addAudioScript = () => {
editAudioInfo.value = {};
audioScriptVisible.value = true;
};
// 编辑脚本 // 编辑脚本
const editTextScript = (item: any, index: number) => { const editTextScript = (item: any, index: number) => {
item.index = index; item.index = index;
...@@ -350,6 +366,8 @@ const editTextScript = (item: any, index: number) => { ...@@ -350,6 +366,8 @@ const editTextScript = (item: any, index: number) => {
textScriptVisible.value = true; textScriptVisible.value = true;
}; };
// 编辑音频脚本
// 删除文本脚本 // 删除文本脚本
const deleteTextScript = (index: number) => { const deleteTextScript = (index: number) => {
deleteTextId.value = index; deleteTextId.value = index;
...@@ -367,11 +385,15 @@ const confirmDeleteText = () => { ...@@ -367,11 +385,15 @@ const confirmDeleteText = () => {
const textScriptSubmit = (params: any) => { const textScriptSubmit = (params: any) => {
if (params.title && params.content) { if (params.title && params.content) {
// 创建一个uuid // 创建一个uuid
params.uuid = createLiveInfo.value[createLiveKeys.scriptUuid]; params.uuid = v4();
if (typeof params.index === 'number') { if (typeof params.index === 'number') {
// 编辑 // 编辑
textScriptList.value[params.index].title = params.title; textScriptList.value[params.index].title = params.title;
textScriptList.value[params.index].content = params.content; textScriptList.value[params.index].content = params.content;
textScriptList.value[params.index].movement_id = params.movement_id;
textScriptList.value[params.index].movement_type = params.movement_type;
textScriptList.value[params.index].movement_name = params.movement_name;
textScriptList.value[params.index].movement_url = params.movement_url;
// 其他参数都要清掉 // 其他参数都要清掉
// 任务id // 任务id
textScriptList.value[params.index].task_id = ''; textScriptList.value[params.index].task_id = '';
...@@ -385,6 +407,18 @@ const textScriptSubmit = (params: any) => { ...@@ -385,6 +407,18 @@ const textScriptSubmit = (params: any) => {
} }
}; };
// 提交音频脚本
const audioScriptSubmit = (params: any) => {
console.log(params);
if (typeof params.index === 'number') {
// 编辑模式
audioScriptList.value[params.index] = params;
} else {
audioScriptList.value.push(params);
}
uploadChange();
};
// 文本脚本内容提交到store // 文本脚本内容提交到store
const submitTextScript = () => { const submitTextScript = () => {
commitInfo({ commitInfo({
...@@ -439,7 +473,6 @@ const updateInfo = (info: any) => { ...@@ -439,7 +473,6 @@ const updateInfo = (info: any) => {
currentOption.value = scriptTypeText; currentOption.value = scriptTypeText;
if (type_content) { if (type_content) {
// 内容 // 内容
// textareaValue.value = type_content;
textScriptList.value = type_content; textScriptList.value = type_content;
} }
// 洗稿 // 洗稿
...@@ -457,16 +490,7 @@ const updateInfo = (info: any) => { ...@@ -457,16 +490,7 @@ const updateInfo = (info: any) => {
} else { } else {
// 草稿 // 草稿
if (type_content) { if (type_content) {
audioScriptList.value = type_content.map((item: any) => { audioScriptList.value = type_content;
item.forEach((it: any) => {
it.audio_url = it.content;
it.status = true;
it.url = it.content;
});
return {
data: item,
};
});
} else { } else {
audioScriptList.value = []; audioScriptList.value = [];
} }
...@@ -722,6 +746,77 @@ onMounted(async () => { ...@@ -722,6 +746,77 @@ onMounted(async () => {
.flex1 { .flex1 {
flex: 1 1 auto; flex: 1 1 auto;
} }
.script-template-body__text-add {
height: 100%;
.dja();
flex-direction: column;
cursor: pointer;
img {
width: 40px;
height: 40px;
margin-bottom: 12px;
}
.label {
font-size: @size-18;
color: #b4b4b4;
font-weight: 600;
}
}
.script-template-body__text {
.dj();
flex-direction: column;
height: 100%;
.title-box,
.content-box {
font-size: @size-14;
display: flex;
.label {
white-space: nowrap;
}
}
.action-box {
color: #b4b4b4;
margin-top: 16px;
.da();
.tag {
margin-left: 20px;
border-radius: 4px;
background: #303030;
.dja();
color: #04ae8a;
font-size: @size-12;
font-weight: 600;
padding: 3px 10px 3px 11px;
}
}
.title-box {
color: #fff;
}
.content-box {
color: #b4b4b4;
margin-top: 16px;
flex: 1;
overflow: hidden;
.value {
width: 100%;
height: 100%;
word-break: break-all;
overflow-y: auto;
.uploaded-audio-list {
width: 100%;
.da();
flex-wrap: wrap;
row-gap: 20px;
margin-left: -20px;
& > * {
.dja();
flex-direction: column;
margin-left: 20px;
}
}
}
}
}
.script-setting-text { .script-setting-text {
overflow-y: auto; overflow-y: auto;
transition: 0.3s; transition: 0.3s;
...@@ -734,49 +829,6 @@ onMounted(async () => { ...@@ -734,49 +829,6 @@ onMounted(async () => {
} }
} }
} }
.script-template-body__text {
.dj();
flex-direction: column;
height: 100%;
.title-box,
.content-box {
font-size: @size-14;
display: flex;
.label {
white-space: nowrap;
}
}
.title-box {
color: #fff;
}
.content-box {
color: #b4b4b4;
margin-top: 16px;
flex: 1;
overflow: hidden;
.value {
height: 100%;
word-break: break-all;
overflow-y: auto;
}
}
}
.script-template-body__text-add {
height: 100%;
.dja();
flex-direction: column;
cursor: pointer;
img {
width: 40px;
height: 40px;
margin-bottom: 12px;
}
.label {
font-size: @size-18;
color: #b4b4b4;
font-weight: 600;
}
}
} }
.script-setting-upload { .script-setting-upload {
overflow-y: auto; overflow-y: auto;
...@@ -798,13 +850,6 @@ onMounted(async () => { ...@@ -798,13 +850,6 @@ onMounted(async () => {
} }
} }
} }
.custom-multiple-upload {
height: 100%;
background: transparent;
.custom-uploading-stauts {
padding-top: 12px;
}
}
} }
} }
} }
......
...@@ -72,7 +72,7 @@ import ChoseDigitalPerson from './components/ChoseDigitalPerson.vue'; ...@@ -72,7 +72,7 @@ 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, onBeforeMount, ref, onBeforeUnmount, onActivated } from 'vue'; import { computed, onBeforeMount, ref, onBeforeUnmount, onActivated, toRaw } from 'vue';
import { import {
getElBounding, getElBounding,
show_message, show_message,
...@@ -224,6 +224,12 @@ const getEditInfo = async (id: any, type: string) => { ...@@ -224,6 +224,12 @@ const getEditInfo = async (id: any, type: string) => {
[createLiveKeys.interactiveLibrary]: res.data.interaction_ids, [createLiveKeys.interactiveLibrary]: res.data.interaction_ids,
}; };
if (res.data.type == '2') { if (res.data.type == '2') {
console.log(res.data.type_content);
res.data.type_content.forEach((item: any) => {
item.movement_id = item.extend.movement_id;
item.movement_type = item.extend.movement_type;
item.movement_name = item.extend.movement_name;
});
// 文本 // 文本
params[createLiveKeys.textSoundColor] = res.data.phonetic_timbres_id; params[createLiveKeys.textSoundColor] = res.data.phonetic_timbres_id;
params[createLiveKeys.textScriptList] = [res.data.type_content]; params[createLiveKeys.textScriptList] = [res.data.type_content];
...@@ -232,7 +238,7 @@ const getEditInfo = async (id: any, type: string) => { ...@@ -232,7 +238,7 @@ const getEditInfo = async (id: any, type: string) => {
// 音频音色 // 音频音色
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] = mergeSameAudio(res.data.type_content); params[createLiveKeys.audioScriptList] = mergeSameAudio(ecursionDeepCopy(toRaw(res.data.type_content)));
} }
// 更新标题 // 更新标题
if (res.data.name) { if (res.data.name) {
...@@ -263,24 +269,7 @@ const getEditInfo = async (id: any, type: string) => { ...@@ -263,24 +269,7 @@ const getEditInfo = async (id: any, type: string) => {
// 音频音色 // 音频音色
params[createLiveKeys.phoneticsSoundColor] = content.phonetic_timbres_id ? content.phonetic_timbres_id : ''; params[createLiveKeys.phoneticsSoundColor] = content.phonetic_timbres_id ? content.phonetic_timbres_id : '';
if (content.type_content) { if (content.type_content) {
let newContent = ecursionDeepCopy(content.type_content); params[createLiveKeys.audioScriptList] = content.type_content;
// 过滤出child
newContent = newContent.map((item: any) => {
item.forEach((it: any) => {
it.children = [];
let children = it.content.split('|');
children.forEach((child) => {
let obj = {
audio_url: child,
};
it.children.push(obj);
});
});
return {
data: item,
};
});
params[createLiveKeys.audioScriptList] = newContent;
} }
} }
// 更新标题 // 更新标题
...@@ -377,6 +366,8 @@ const onSave = () => { ...@@ -377,6 +366,8 @@ const onSave = () => {
// 保存为草稿 // 保存为草稿
const onSaveDrafts = async () => { const onSaveDrafts = async () => {
let params = filterFiled(getCreateLiveInfo()); let params = filterFiled(getCreateLiveInfo());
// 单独修改草稿内容
params.type_content = createLiveInfo.value[createLiveKeys.audioScriptList];
try { try {
loading.value = true; loading.value = true;
let res: any = await createDrafts(params); let res: any = await createDrafts(params);
...@@ -415,13 +406,8 @@ const audioScriptEditSubmit = async () => { ...@@ -415,13 +406,8 @@ const audioScriptEditSubmit = async () => {
const editAudioSave = async () => { const editAudioSave = async () => {
try { try {
loading.value = true; loading.value = true;
if (audioScriptVersion == 'v1') { // v2
await audioSplit(); audioConvert('update');
await audioScriptEditSubmit();
} else {
// v2
audioConvert('update');
}
} catch (e) { } catch (e) {
writeLog({ writeLog({
name: 'createLive editAudioSave error', name: 'createLive editAudioSave error',
...@@ -447,7 +433,9 @@ const submitTaskAndConfuse = async (type: string) => { ...@@ -447,7 +433,9 @@ const submitTaskAndConfuse = async (type: string) => {
// 音调 // 音调
tone_id: item[createLiveKeys.textTones], tone_id: item[createLiveKeys.textTones],
content: row.content, content: row.content,
uuid: item[createLiveKeys.scriptUuid], uuid: row.uuid,
parent_uuid: item[createLiveKeys.scriptUuid],
id: i,
}; };
// 生成音频 // 生成音频
let res: any = await liveTts(params); let res: any = await liveTts(params);
...@@ -483,57 +471,6 @@ const onEditSave = async () => { ...@@ -483,57 +471,6 @@ const onEditSave = async () => {
} }
}; };
// 音频切割v1
const audioSplit = async () => {
for (let i = 0; i < createLiveInfo.value[createLiveKeys.audioScriptList].length; i++) {
let item = createLiveInfo.value[createLiveKeys.audioScriptList][i];
for (let j = 0; j < item.data.length; j++) {
let row = item.data[j];
if (row.children && row.children.length > 1) {
// 编辑时没有修改参数
continue;
}
if (
row.duration &&
row.duration > audioSplitNum &&
row.content &&
row.content.indexOf('|') == -1 &&
row.old_content &&
!row.file?.raw
) {
console.log('大于5分钟,开始下载文件');
// 没有文件时,下载
let file = await getFile(row.old_content);
row.file = {};
row.file.raw = file;
console.log(row.file);
}
if (row.file && row.file.raw) {
// 文件时长
let fileDuration = await getDurationOfAudioFile(row.file.raw);
console.log(fileDuration, '文件时长');
if (fileDuration > audioSplitNum) {
// 开始切割前先判断文件类型
let result = await splitAudio(row.file.raw, audioSplitNum);
if (result.length) {
// 上传阿里云--加个判断,没有长度抛出异常
let alyList = await uploadToAly(result);
let list = [];
alyList.forEach((aly: any) => {
aly.forEach((alyRow: any) => {
list.push(alyRow.content);
});
});
// console.log(list, 'list');
// 一维数组
row.new_content = list.join('|');
}
}
}
}
}
};
// python转换音频回调 // python转换音频回调
const convertCallback = (convertInfo: any) => { const convertCallback = (convertInfo: any) => {
console.log('转换回调', convertInfo); console.log('转换回调', convertInfo);
...@@ -542,9 +479,9 @@ const convertCallback = (convertInfo: any) => { ...@@ -542,9 +479,9 @@ const convertCallback = (convertInfo: any) => {
let audioScriptList = createLiveInfo.value[createLiveKeys.audioScriptList]; let audioScriptList = createLiveInfo.value[createLiveKeys.audioScriptList];
// 根据切割前的链接匹配更新 // 根据切割前的链接匹配更新
for (let i = 0; i < audioScriptList.length; i++) { for (let i = 0; i < audioScriptList.length; i++) {
let item = audioScriptList[i]; let item = audioScriptList[i].audioList;
for (let j = 0; j < item.data.length; j++) { for (let j = 0; j < item.length; j++) {
let row = item.data[j]; let row = item[j];
if (getAudioUrl(row) == convertInfo.url) { if (getAudioUrl(row) == convertInfo.url) {
// 更新url // 更新url
let key = getAudioUrlKey(row); let key = getAudioUrlKey(row);
...@@ -579,9 +516,9 @@ const splitCallback = (splitInfo: any) => { ...@@ -579,9 +516,9 @@ const splitCallback = (splitInfo: any) => {
let audioScriptList = createLiveInfo.value[createLiveKeys.audioScriptList]; let audioScriptList = createLiveInfo.value[createLiveKeys.audioScriptList];
// 根据切割前的链接匹配更新 // 根据切割前的链接匹配更新
for (let i = 0; i < audioScriptList.length; i++) { for (let i = 0; i < audioScriptList.length; i++) {
let item = audioScriptList[i]; let item = audioScriptList[i].audioList;
for (let j = 0; j < item.data.length; j++) { for (let j = 0; j < item.length; j++) {
let row = item.data[j]; let row = item[j];
if (getAudioUrl(row) == splitInfo.url) { if (getAudioUrl(row) == splitInfo.url) {
row.new_content = splitInfo.list.join('|'); row.new_content = splitInfo.list.join('|');
row.py_split_status = true; row.py_split_status = true;
...@@ -639,9 +576,9 @@ const audioConvert = async (type: string) => { ...@@ -639,9 +576,9 @@ const audioConvert = async (type: string) => {
// 清空总任务数 // 清空总任务数
audioConvertTaskTotal.value = 0; audioConvertTaskTotal.value = 0;
for (let i = 0; i < list.length; i++) { for (let i = 0; i < list.length; i++) {
let item = list[i]; let item = list[i].audioList;
for (let j = 0; j < item.data.length; j++) { for (let j = 0; j < item.length; j++) {
let row = item.data[j]; let row = item[j];
if (row.children && row.children.length > 1) { if (row.children && row.children.length > 1) {
// 编辑时没有修改参数 // 编辑时没有修改参数
continue; continue;
...@@ -651,12 +588,13 @@ const audioConvert = async (type: string) => { ...@@ -651,12 +588,13 @@ const audioConvert = async (type: string) => {
let suffix = getFileSuffixInUrl(audio_url); let suffix = getFileSuffixInUrl(audio_url);
if (suffix === 'wav') { if (suffix === 'wav') {
console.log('是wav文件,开始转换', audio_url); console.log('是wav文件,开始转换', audio_url);
audioConvertToPython(row, type); await audioConvertToPython(row, type);
} else { } else {
console.log('不是wav', audio_url); console.log('不是wav', audio_url);
} }
} }
} }
console.log(`共有${audioConvertTaskTotal.value}个文件要转换格式`);
if (audioConvertTaskTotal.value === 0) { if (audioConvertTaskTotal.value === 0) {
// 没有要转换的,直接切割 // 没有要转换的,直接切割
audioSplitV2(type); audioSplitV2(type);
...@@ -669,9 +607,9 @@ const audioSplitV2 = async (type: string) => { ...@@ -669,9 +607,9 @@ const audioSplitV2 = async (type: string) => {
// 清空总次数 // 清空总次数
audioSplitTaskTotal.value = 0; audioSplitTaskTotal.value = 0;
for (let i = 0; i < list.length; i++) { for (let i = 0; i < list.length; i++) {
let item = list[i]; let item = list[i].audioList;
for (let j = 0; j < item.data.length; j++) { for (let j = 0; j < item.length; j++) {
let row = item.data[j]; let row = item[j];
if (row.children && row.children.length > 1) { if (row.children && row.children.length > 1) {
// 编辑时没有修改参数 // 编辑时没有修改参数
continue; continue;
...@@ -746,13 +684,8 @@ const audioScriptLiveTaskSubmit = async () => { ...@@ -746,13 +684,8 @@ const audioScriptLiveTaskSubmit = async () => {
const audioSubmit = async () => { const audioSubmit = async () => {
try { try {
loading.value = true; loading.value = true;
if (audioScriptVersion == 'v1') { // v2版本,提交到python处理
await audioSplit(); audioConvert('create');
await audioScriptLiveTaskSubmit();
} else {
// v2版本,提交到python处理
audioConvert('create');
}
} catch (e) { } catch (e) {
writeLog({ writeLog({
name: 'createLive audioSubmit error', name: 'createLive audioSubmit error',
......
...@@ -229,7 +229,9 @@ const startTest = async () => { ...@@ -229,7 +229,9 @@ const startTest = async () => {
onMounted(() => { onMounted(() => {
// 发送token,即使重新登录也会回到首页再次发送 // 发送token,即使重新登录也会回到首页再次发送
callPyjsInWindow('setToken', userToken.value); callPyjsInWindow('setToken', {
token: userToken.value,
});
// 获取我的数字人 // 获取我的数字人
getList(); getList();
startTest(); startTest();
......
...@@ -281,12 +281,6 @@ const mergeCallback = (params: any) => { ...@@ -281,12 +281,6 @@ const mergeCallback = (params: any) => {
onMounted(async () => { onMounted(async () => {
// 将通知方法注入window // 将通知方法注入window
injectWindow('mergeCallback', mergeCallback); injectWindow('mergeCallback', mergeCallback);
// 传递用户token
try {
window.pyjs.setToken(getUserCookie());
} catch (e) {
console.error('没有pyjs');
}
// if (isDev()) { // if (isDev()) {
// mergeCallback({ // mergeCallback({
......
...@@ -169,13 +169,10 @@ export const audioStart = async (list: any[], dimensional: boolean = true) => { ...@@ -169,13 +169,10 @@ export const audioStart = async (list: any[], dimensional: boolean = true) => {
// 合并后的文件上传 // 合并后的文件上传
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('上传完毕');
// 是否一维数组 // 是否一维数组
if (dimensional) { if (dimensional) {
console.log(result);
return result; return result;
} else { } else {
console.log([result]);
return [result]; return [result];
} }
} }
...@@ -236,10 +233,14 @@ export const uploadToAly = async (fileList: File[]) => { ...@@ -236,10 +233,14 @@ export const uploadToAly = async (fileList: File[]) => {
}; };
// 获取动作列表 // 获取动作列表
export const getLiveMovementList = async () => { export const getLiveMovementList = async (filter: boolean = false) => {
try { try {
let res: any = await getLiveMovement(); let res: any = await getLiveMovement();
if (res.code == 0) { if (res.code == 0) {
if (filter) {
// 过滤出成功的
return res.data.filter((item: any) => item.audit_status == LIVE_AUDIT_STATUS.LIVE_AUDIT_STATUS_FINISH);
}
return res.data; return res.data;
} }
return []; return [];
......
import { mergedArray, isDev, show_message, dimensionalConvert, DataType } from '@/utils/tool'; import {
mergedArray,
isDev,
show_message,
dimensionalConvert,
DataType,
TableSortAsc,
ecursionDeepCopy,
} from '@/utils/tool';
import { liveContentRegenerateCallback, liveTts, getLiveTtsCallback, liveTaskRegenerate } from '@/utils/api/userApi'; import { liveContentRegenerateCallback, liveTts, getLiveTtsCallback, liveTaskRegenerate } from '@/utils/api/userApi';
import { audioStart } from '@/service/Common'; import { audioStart } from '@/service/Common';
import store from '@/store'; import store from '@/store';
...@@ -32,7 +40,7 @@ export const createLiveKeys = { ...@@ -32,7 +40,7 @@ export const createLiveKeys = {
commentMethod: 'commentMethod', // 评论方式 commentMethod: 'commentMethod', // 评论方式
interactiveLibrary: 'interactiveLibrary', // 互动库 interactiveLibrary: 'interactiveLibrary', // 互动库
isDisorganize: 'is_disorganize', // 是否洗稿 isDisorganize: 'is_disorganize', // 是否洗稿
scriptUuid: 'script_uuid', // 文本脚本生成的uuid scriptUuid: 'script_uuid', // 文本脚本生成的uuid
}; };
// 脚本类型 // 脚本类型
...@@ -53,19 +61,75 @@ export const scriptTypeList = [ ...@@ -53,19 +61,75 @@ export const scriptTypeList = [
export const typeTones = 1; // 音调 export const typeTones = 1; // 音调
export const typeSoundColor = 2; // 音色 export const typeSoundColor = 2; // 音色
// 动作类型
export const movementTypeStart = 1; // 开头插入
export const movementTypeEnd = 2; // 结尾插入
// 合并同类项音频 // 合并同类项音频
export const mergeSameAudio = (content: any[]) => { export const mergeSameAudio = (content: any[]) => {
let list = mergedArray(content); let list = [];
return list.map((item: any) => { content.forEach((item: any, index: number) => {
let title = '';
let url = '';
let movement_name = '';
let movement_type = null;
let movement_id = null;
// 找到第一个old
let oldList = item.filter((it: any) => it.is_old);
if (oldList.length) {
title = oldList[0].extend.title;
url = oldList[0].audio_url;
movement_name = oldList[0].extend.movement_name;
movement_type = oldList[0].extend.movement_type;
movement_id = oldList[0].extend.movement_id;
}
// 获取audioList
let audioList = [];
oldList.forEach((it: any) => {
let params = {
file: {
name: it.name,
},
uuid: it.uuid,
url: it.audio_url,
duration: it.duration,
status: true,
};
audioList.push(params);
});
// 找出所有 is_old == 0的,根据uuid存放到 is_old ==1的对象中
item.forEach((it: any) => { item.forEach((it: any) => {
if (it.audio_url) { for (let i = 0; i < audioList.length; i++) {
it.url = it.audio_url; let audioRow = audioList[i];
// 初始化children
if (!audioRow.children) {
audioRow.children = [];
}
if (it.uuid == audioRow.uuid && !it.is_old) {
let params = {
file: {
name: it.name,
},
duration: it.duration,
url: it.audio_url,
};
audioRow.children.push(params);
}
} }
}); });
return {
data: item, list.push({
}; audioList: audioList,
title: title,
url: url,
movement_name: movement_name,
movement_type: movement_type,
movement_id: movement_id,
});
}); });
return list;
}; };
// 获取洗稿回调 // 获取洗稿回调
...@@ -91,23 +155,7 @@ export const onRewriteCallback = async (id: string) => { ...@@ -91,23 +155,7 @@ export const onRewriteCallback = async (id: string) => {
// //
res.data = [ res.data = [
{ {
content: ` content: `大家好!欢迎来到今天的直播!我是你们的主持人,今天我将为大家带来一场精彩的直播节目`,
大家好!欢迎来到今天的直播!我是你们的主持人,今天我将为大家带来一场精彩的直播节目。在这里,我们将分享一些有趣的内容,并回答你们的问题。
首先,让我们来聊一聊今天的主题。今天我们将重点聚焦在XX领域(根据直播主题填写),这是一个非常热门、有趣且前沿的领域。我们将了解最新的发展动态、分享一些实用的技巧,并回答你们提出的问题。
对于新加入直播的朋友,特别欢迎你们!如果你们有任何问题或者想要了解更多关于XX的信息,请随时在评论区留言,我将尽力回答你们的问题。
在这里,我们鼓励大家积极互动。请大家在评论区留下你们的想法、观点和问题。我会选择一些与主题相关的问题进行回答,在回答问题时我会尽量深入浅出,以确保每个人都能够理解。
也请大家相互尊重,遵守礼貌。如果有令人不舒服的言论或者不适当的内容,请及时举报,我们会及时处理。
接下来,让我们一起进入今天的正题吧!不管你是刚开始接触XX,还是已经有一定了解,请相信你们在这里能够获得更多知识、更多的收获。
再次感谢大家的到来和支持,让我们一起度过这个精彩的时刻!祝愿大家在本次直播中有所收获,也希望大家能够在评论区互相交流,共同进步。
谢谢大家!现在,让我们开始今天的直播吧!
`,
}, },
]; ];
} }
...@@ -147,6 +195,7 @@ export const submitAudioTask = async (list: any[], item: any, uuid: string) => { ...@@ -147,6 +195,7 @@ export const submitAudioTask = async (list: any[], item: any, uuid: string) => {
tone_id: item[createLiveKeys.textTones], tone_id: item[createLiveKeys.textTones],
content: list[i].content, content: list[i].content,
uuid: uuid, uuid: uuid,
id: i,
}; };
// 生成音频 // 生成音频
await liveTts(params); await liveTts(params);
...@@ -208,25 +257,33 @@ export const filterFiled = (item: any, type: string = '') => { ...@@ -208,25 +257,33 @@ export const filterFiled = (item: any, type: string = '') => {
// 脚本内容 // 脚本内容
if (item[createLiveKeys.scriptType] == scriptTypeText) { if (item[createLiveKeys.scriptType] == scriptTypeText) {
// 文本 // 文本
params.type_content = item[createLiveKeys.textScriptValue]; // 文本内容--先转一维数组
// 转换格式 let newList = dimensionalConvert(item[createLiveKeys.textScriptList]);
// 先二维转一维 params.type_content = newList.map((row: any) => {
params.type_content = dimensionalConvert(params.type_content); return {
let list = []; movement: {
params.type_content.forEach((item: any) => { id: row.movement_id,
list.push([item]); type: row.movement_type,
name: row.movement_name,
url: row.movement_url,
},
// 提交的数组
list: row.newList,
};
}); });
params.type_content = list;
console.log(params.type_content, '文本 type_content'); console.log(params.type_content, '文本 type_content');
// 音色id // 音色id
params.phonetic_timbres_id = item[createLiveKeys.textSoundColor]; params.phonetic_timbres_id = item[createLiveKeys.textSoundColor];
// 文本内容--先转一维数组
let newList = dimensionalConvert(item[createLiveKeys.textScriptList]); params.content = newList.map((row: any, index: number) => {
params.content = newList.map((row: any) => {
return { return {
title: row.title, title: row.title,
content: row.content, content: row.content,
movement_id: row.movement_id,
movement_type: row.movement_type,
movement_name: row.movement_name,
movement_url: row.movement_url,
}; };
}); });
} else { } else {
...@@ -241,7 +298,7 @@ export const filterFiled = (item: any, type: string = '') => { ...@@ -241,7 +298,7 @@ export const filterFiled = (item: any, type: string = '') => {
// 音频 // 音频
params.type_content = item[createLiveKeys.audioScriptList].map((audioScript: any) => { params.type_content = item[createLiveKeys.audioScriptList].map((audioScript: any) => {
let list = []; let list = [];
audioScript.data.forEach((it: any) => { audioScript.audioList.forEach((it: any) => {
let params: any = { let params: any = {
content: '', content: '',
old_content: '', old_content: '',
...@@ -304,7 +361,19 @@ export const filterFiled = (item: any, type: string = '') => { ...@@ -304,7 +361,19 @@ export const filterFiled = (item: any, type: string = '') => {
list.push(params); list.push(params);
}); });
return list; let movement: any = {
id: audioScript.movement_id,
type: audioScript.movement_type,
name: audioScript.movement_name,
url: audioScript.movement_url,
};
return {
movement: movement,
list: list,
extend: {
title: audioScript.title,
},
};
}); });
console.log(params.type_content, '音频 type_content'); console.log(params.type_content, '音频 type_content');
// 音色id // 音色id
...@@ -375,6 +444,45 @@ export const getAudioStartTimeAndEndTime = async (list: any[]) => { ...@@ -375,6 +444,45 @@ export const getAudioStartTimeAndEndTime = async (list: any[]) => {
} }
}; };
// 洗稿音频回调处理
export const onAudioProcessed = async (res: any, liveInfo: any) => {
let list = [];
for (let i = 0; i < res.data.length; i++) {
let item = res.data[i];
let data = item.data;
if (data && data.audio_address) {
let resultList = await audioStart([data.audio_address], true);
// 转一维
resultList = dimensionalConvert(resultList);
if (!resultList.length) {
show_message('洗稿失败');
writeLog('洗稿回调中音频下载失败-audioStart');
return;
}
let textScriptList = dimensionalConvert(liveInfo[createLiveKeys.textScriptList]);
list.push({
movement: {
id: textScriptList[i].movement_id,
type: textScriptList[i].movement_type,
name: textScriptList[i].movement_name,
url: textScriptList[i].movement_url,
},
list: resultList.map((row: any) => {
return {
content: row.content,
movement_type: textScriptList[i].movement_type,
movement_name: textScriptList[i].movement_name,
};
}),
});
} else {
console.log('洗稿缺少参数');
show_message('洗稿缺少参数');
}
}
return list;
};
// 洗稿获取音频回调 // 洗稿获取音频回调
export const getAudioCallback = (audio_task_id: string, len: number, liveInfo: any, live_id: any) => { export const getAudioCallback = (audio_task_id: string, len: number, liveInfo: any, live_id: any) => {
let interval = null; let interval = null;
...@@ -393,38 +501,28 @@ export const getAudioCallback = (audio_task_id: string, len: number, liveInfo: a ...@@ -393,38 +501,28 @@ export const getAudioCallback = (audio_task_id: string, len: number, liveInfo: a
}); });
if (res.code == 0) { if (res.code == 0) {
if (isDev()) { if (isDev()) {
let params = { let params: any = {
data: { data: {
audio_address: audio_address:
'http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/jupiter-flow/tmp/e56d8750eb3a44f9930f73703489acb1.wav?Expires=1692087730&OSSAccessKeyId=LTAIUpwNp2H7pBG5&Signature=FtKSld5Dn55po9GyTm%2BefRKmPqw%3D', 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-16fcc74a89-d3f1-4545-a17c-d155dfa7978f.wav',
task_id: 0, task_id: 0,
}, },
}; };
for (let i = 0; i < 3; i++) { for (let i = 0; i < 1; i++) {
params.data.id = i;
res.data.push(params); res.data.push(params);
} }
} }
if (res.data.length) { if (res.data.length) {
// 根据id升序排列
res.data = TableSortAsc(res.data, 'data.id');
console.log('音频任务回调成功'); console.log('音频任务回调成功');
console.log(res.data); console.log(res.data);
if (res.data.length >= len) { if (res.data.length >= len) {
closeInterval(); closeInterval();
let audioList = []; let list = await onAudioProcessed(res, liveInfo);
res.data.forEach(async (item: any, index: number) => {
let data = item.data;
if (data && data.audio_address) {
audioList.push(data.audio_address);
} else {
console.log('洗稿缺少参数');
show_message('洗稿缺少参数');
}
});
// 获取音频时长
let durationList = await getAudioStartTimeAndEndTime(res.data);
console.log(durationList, '洗稿durationList');
let resultList = await audioStart(audioList, true);
// 提交 // 提交
await regenerate(resultList, liveInfo, live_id); await regenerate(list, liveInfo, live_id);
} }
} }
} }
......
...@@ -81,10 +81,18 @@ export const TableSort = (list: any, field: string) => { ...@@ -81,10 +81,18 @@ export const TableSort = (list: any, field: string) => {
// 升序 // 升序
export const TableSortAsc = (list: any, field: string) => { export const TableSortAsc = (list: any, field: string) => {
let maxIndex, temp; let maxIndex, temp;
const getValue = (obj: any, path: string) => {
const keys = path.split('.');
let value = obj;
for (const key of keys) {
value = value[key];
}
return value;
};
for (let i = 0; i < list.length - 1; i++) { for (let i = 0; i < list.length - 1; i++) {
maxIndex = i; maxIndex = i;
for (let j = i + 1; j < list.length; j++) { for (let j = i + 1; j < list.length; j++) {
if (list[j][field] < list[maxIndex][field]) { if (getValue(list[j], field) < getValue(list[maxIndex], field)) {
maxIndex = j; maxIndex = j;
} }
} }
...@@ -453,7 +461,7 @@ export const mergedArray = (arr: any[], key: string = 'uuid', first: string = 'i ...@@ -453,7 +461,7 @@ export const mergedArray = (arr: any[], key: string = 'uuid', first: string = 'i
result.push(...existingObj); result.push(...existingObj);
} }
newSubArray.forEach((obj) => { newSubArray.forEach((obj) => {
const existingIndex = result.findIndex((it) => it.uuid === obj.uuid && !obj[first] && !obj.removed); const existingIndex = result.findIndex((it) => it[key] === obj[key] && !obj[first] && !obj.removed);
if (existingIndex !== -1) { if (existingIndex !== -1) {
// 标记 // 标记
obj.removed = true; obj.removed = true;
......
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