Commit 81203f07 by haojie

音频脚本逻辑修改前最后一次提交

parent f5bb479e
...@@ -49,7 +49,7 @@ import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'; ...@@ -49,7 +49,7 @@ import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import Loading from '@/components/Loading/FirstCircle.vue'; import Loading from '@/components/Loading/FirstCircle.vue';
import { onBeforeRouteLeave } from 'vue-router'; import { onBeforeRouteLeave } from 'vue-router';
import { injectWindow } from '@/utils/pyqt'; import { callPyjsInWindow, injectWindow } from '@/utils/pyqt';
import { scriptTypePhonetics } from '@/service/CreateLive'; import { scriptTypePhonetics } from '@/service/CreateLive';
const props = withDefaults( const props = withDefaults(
...@@ -126,6 +126,8 @@ const closeInterval = () => { ...@@ -126,6 +126,8 @@ const closeInterval = () => {
const confirm = () => { const confirm = () => {
openInterval(); openInterval();
onPlay(); onPlay();
// 通知python开始播放了
// callPyjsInWindow('')
}; };
// 主视频可以播放 // 主视频可以播放
......
...@@ -57,6 +57,7 @@ export default function () { ...@@ -57,6 +57,7 @@ export default function () {
if (res.code == 0 && res.data.length) { if (res.code == 0 && res.data.length) {
// 是否为error // 是否为error
if (res.data[0] === 'error') { if (res.data[0] === 'error') {
console.log('不需要洗稿了');
stopConfuse.value = true; stopConfuse.value = true;
} else { } else {
console.log('洗稿回调成功'); console.log('洗稿回调成功');
......
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 } from '@/service/CreateLive'; import { createLiveKeys, createLiveVersion, filterFiled, getAudioStartTimeAndEndTime } 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 { ecursionDeepCopy, isDev, show_message } from '@/utils/tool';
import { useLiveInfoSubmit } from '@/hooks/useStoreCommit'; import { useLiveInfoSubmit } from '@/hooks/useStoreCommit';
...@@ -224,6 +224,7 @@ export const processTextCallback = () => { ...@@ -224,6 +224,7 @@ export const processTextCallback = () => {
}); });
if (res.code == 0) { if (res.code == 0) {
if (isDev()) { if (isDev()) {
for (let i = 0; i < 3; i++) {
let params = { let params = {
data: { data: {
audio_address: audio_address:
...@@ -231,7 +232,6 @@ export const processTextCallback = () => { ...@@ -231,7 +232,6 @@ export const processTextCallback = () => {
task_id: 0, task_id: 0,
}, },
}; };
for (let i = 0; i < 3; i++) {
res.data.push(params); res.data.push(params);
} }
} }
...@@ -244,8 +244,6 @@ export const processTextCallback = () => { ...@@ -244,8 +244,6 @@ 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 = []; let audio_list = [];
// 本次任务不是洗稿任务才修改store
if (!isConfuse) {
res.data.forEach((item: any) => { res.data.forEach((item: any) => {
// 根据task_id更新数组对象 // 根据task_id更新数组对象
let data = item.data; let data = item.data;
...@@ -266,6 +264,9 @@ export const processTextCallback = () => { ...@@ -266,6 +264,9 @@ export const processTextCallback = () => {
show_message('缺少音频或id'); show_message('缺少音频或id');
} }
}); });
// 获取音频时长
let durationList = await getAudioStartTimeAndEndTime(res.data);
console.log(durationList, '不洗稿durationList');
if (!audio_list.length) { if (!audio_list.length) {
throw new CustomException('没有要处理的音频'); throw new CustomException('没有要处理的音频');
...@@ -304,7 +305,6 @@ export const processTextCallback = () => { ...@@ -304,7 +305,6 @@ export const processTextCallback = () => {
submitSuccessed(); submitSuccessed();
} }
} }
}
} else { } else {
if (res.data.length >= confuseLength) { if (res.data.length >= confuseLength) {
closeInterval(); closeInterval();
......
...@@ -3,19 +3,28 @@ ...@@ -3,19 +3,28 @@
overlayClassName="placement-user-info" overlayClassName="placement-user-info"
placement="bottom-left" placement="bottom-left"
trigger="click" trigger="click"
:attach="getDomId"
:showArrow="false" :showArrow="false"
v-model:visible="user_popup_visible" v-model:visible="user_popup_visible"
> >
<template #content> <template #content>
<div class="s-header-user-info-dropdown"> <div
class="s-header-user-info-dropdown"
:style="{
width: headerUserInfo ? headerUserInfo.clientWidth + 'px' : '',
}"
>
<div class="user-info-dropdown-footer" @click="logout"> <div class="user-info-dropdown-footer" @click="logout">
<img :src="Imgs.logout" alt="" /> <img :src="Imgs.logout" alt="" />
<div class="dropdown-footer-text">退出</div> <div class="dropdown-footer-text">退出</div>
</div> </div>
</div> </div>
</template> </template>
<div class="custom-header-user-info"> <div class="custom-header-user-info" ref="headerUserInfo">
<UserSvg></UserSvg> <div class="user-name">
{{ userInfo.email ?? '' }}
</div>
<img :src="Imgs.user" alt="" />
<div class="user-message-dot" v-if="mes_num">{{ mes_num }}</div> <div class="user-message-dot" v-if="mes_num">{{ mes_num }}</div>
<div v-else></div> <div v-else></div>
</div> </div>
...@@ -24,19 +33,24 @@ ...@@ -24,19 +33,24 @@
<script setup lang="ts"> <script setup lang="ts">
import { Popup as TPopup } from 'tdesign-vue-next'; import { Popup as TPopup } from 'tdesign-vue-next';
import UserSvg from '@/assets/svg/header/user.svg';
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
const Imgs = { const Imgs = {
logout: new URL('../../assets/svg/user/userdropdown/logout.svg', import.meta.url).href, logout: new URL('../../assets/svg/user/userdropdown/logout.svg', import.meta.url).href,
user: new URL('../../assets/svg/header/user.svg', import.meta.url).href,
}; };
// 消息数量 // 消息数量
const mes_num = ref<number>(0); const mes_num = ref<number>(0);
const store = useStore(); const store = useStore();
const userInfo = computed(() => store.getters['user/userInfo']); const userInfo = computed(() => store.getters['user/userInfo']);
const headerUserInfo = ref(null);
const user_popup_visible = ref<boolean>(false); const user_popup_visible = ref<boolean>(false);
const getDomId = () => {
return headerUserInfo.value;
};
onMounted(() => { onMounted(() => {
if (!Object.keys(userInfo.value).length) { if (!Object.keys(userInfo.value).length) {
store.dispatch('user/getUserInfo'); store.dispatch('user/getUserInfo');
...@@ -115,9 +129,19 @@ const logout = () => { ...@@ -115,9 +129,19 @@ const logout = () => {
} }
} }
.custom-header-user-info { .custom-header-user-info {
border: 1px solid #7a7a7a;
border-radius: 8px;
padding: 4px 8px;
.dja(space-between); .dja(space-between);
& > :not(:last-child) { img {
margin: 0 8px; width: 30px;
height: 30px;
}
.user-name {
color: white;
font-size: @size-16;
font-weight: 600;
margin-right: 8px;
} }
.user-message-dot { .user-message-dot {
position: absolute; position: absolute;
......
...@@ -502,6 +502,7 @@ const audioSplit = async () => { ...@@ -502,6 +502,7 @@ const audioSplit = async () => {
// 音频提交 // 音频提交
const audioSubmit = async () => { const audioSubmit = async () => {
// 切割
try { try {
loading.value = true; loading.value = true;
await audioSplit(); await audioSplit();
......
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
</template> </template>
<script lang="tsx" setup> <script lang="tsx" setup>
import { onMounted, reactive, ref } from 'vue'; import { computed, onMounted, reactive, ref } from 'vue';
import Loading from '@/components/loading.vue'; import Loading from '@/components/loading.vue';
import DigitalPeopleDiaog from './components/digitalPeopleDiaog.vue'; import DigitalPeopleDiaog from './components/digitalPeopleDiaog.vue';
import CardOne from '@/components/cardOne.vue'; import CardOne from '@/components/cardOne.vue';
...@@ -79,12 +79,15 @@ import routerConfig from '@/router/tool'; ...@@ -79,12 +79,15 @@ import routerConfig from '@/router/tool';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { getDigitalPeopleList, uploadToAly } from '@/service/Common'; import { getDigitalPeopleList, uploadToAly } from '@/service/Common';
import Button from '@/components/Button.vue'; import Button from '@/components/Button.vue';
import { callPyjsInWindow } from '@/utils/pyqt'; import { callPyjsInWindow, injectWindow } from '@/utils/pyqt';
import { jumpToCreateLivePage } from '@/router/jump'; import { jumpToCreateLivePage } from '@/router/jump';
import { audioMerge } from '@/utils/audio'; import { audioMerge, downloadAudioList } from '@/utils/audio';
import { randomIntFormList } from '@/utils/tool';
import { useStore } from 'vuex';
const router = useRouter(); const router = useRouter();
const store = useStore();
const userToken = computed(() => store.getters['user/token']);
// 当前tab栏 // 当前tab栏
const currentTab = ref('1'); const currentTab = ref('1');
// 弹窗状态 // 弹窗状态
...@@ -194,26 +197,35 @@ const getList = async () => { ...@@ -194,26 +197,35 @@ const getList = async () => {
} }
}; };
const startTest = async () => { const startTest = async () => {
let list = [ // let list = [
'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-114e482462-6047-47be-a30c-b85a17c95665.mp3', // // 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-114e482462-6047-47be-a30c-b85a17c95665.mp3',
'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-11efe3f1ea-b445-42e2-93b0-39a70fb7c6f5.mp3', // // 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-11efe3f1ea-b445-42e2-93b0-39a70fb7c6f5.mp3',
'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-11dd2372d8-73ff-4526-bf59-b1618a3f218f.mp3', // // 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-11dd2372d8-73ff-4526-bf59-b1618a3f218f.mp3',
// 'http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/jupiter-flow/tmp/ad08fa0a70ae4ea88d11ad5e394ce045.wav?Expires=1692149777&OSSAccessKeyId=LTAIUpwNp2H7pBG5&Signature=D93qMT1DovslSOVa9oufV2cGZxE%3D', // 'http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/jupiter-flow/tmp/ad08fa0a70ae4ea88d11ad5e394ce045.wav?Expires=1692149777&OSSAccessKeyId=LTAIUpwNp2H7pBG5&Signature=D93qMT1DovslSOVa9oufV2cGZxE%3D',
// 'http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/jupiter-flow/tmp/ad08fa0a70ae4ea88d11ad5e394ce045.wav?Expires=1692149777&OSSAccessKeyId=LTAIUpwNp2H7pBG5&Signature=D93qMT1DovslSOVa9oufV2cGZxE%3D', // 'http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/jupiter-flow/tmp/ad08fa0a70ae4ea88d11ad5e394ce045.wav?Expires=1692149777&OSSAccessKeyId=LTAIUpwNp2H7pBG5&Signature=D93qMT1DovslSOVa9oufV2cGZxE%3D',
]; // ];
let blob = await audioMerge(list); // let blob = await audioMerge(list);
console.log(blob); // console.log(blob);
if (blob) { // if (blob) {
// uploadToAly([blob]); // // uploadToAly([blob]);
} else { // } else {
console.log('文件错误'); // console.log('文件错误');
} // }
// let list = [
// 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-114e482462-6047-47be-a30c-b85a17c95665.mp3',
// 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-11efe3f1ea-b445-42e2-93b0-39a70fb7c6f5.mp3',
// 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-11dd2372d8-73ff-4526-bf59-b1618a3f218f.mp3',
// ];
// const { blobList } = await downloadAudioList(list);
// console.log(blobList, '下载完毕,传给python');
// callPyjsInWindow('mergeAudio', blobList, false, 0, false);
}; };
onMounted(() => { onMounted(() => {
// 获取我的数字人 // 获取我的数字人
getList(); getList();
startTest(); startTest();
callPyjsInWindow('setToken', userToken.value);
}); });
</script> </script>
......
...@@ -4,6 +4,7 @@ import { audioStart } from '@/service/Common'; ...@@ -4,6 +4,7 @@ import { audioStart } from '@/service/Common';
import store from '@/store'; import store from '@/store';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { writeLog } from '@/utils/pyqt'; import { writeLog } from '@/utils/pyqt';
import { getDurationOfAudioFile } from '@/utils/audio';
/** /**
* 创建直播的版本 * 创建直播的版本
...@@ -243,6 +244,7 @@ export const filterFiled = (item: any, type: string = '') => { ...@@ -243,6 +244,7 @@ export const filterFiled = (item: any, type: string = '') => {
params.content = audioConversion(it.children); params.content = audioConversion(it.children);
params.old_content = it.audio_url; params.old_content = it.audio_url;
} else { } else {
// 创建
if (typeof it === 'string') { if (typeof it === 'string') {
params.content = it; params.content = it;
params.old_content = it; params.old_content = it;
...@@ -303,6 +305,45 @@ export const regenerate = async (list: any[], item: any, live_id: any) => { ...@@ -303,6 +305,45 @@ export const regenerate = async (list: any[], item: any, live_id: any) => {
} }
}; };
// 计算音频块列表的开始时间和结束时间
export const getAudioStartTimeAndEndTime = async (list: any[]) => {
try {
let durationList = [];
for (let i = 0; i < list.length; i++) {
let data = list[i].data;
let params: any = {
audio_url: data.audio_address,
};
// 计算音频块的起始与结束时间点
let duration = await getDurationOfAudioFile(data.audio_address);
console.log(duration);
params.duration = duration;
// 默认值
params.start = 0;
params.end = duration;
durationList.forEach((it: any) => {
// 开始时间
params.start += it.duration;
});
durationList.push(params);
if (i !== 0) {
durationList.forEach((it: any, index: number) => {
// 不包括自己
if (index !== durationList.length - 1) {
// 结束时间
durationList[i].end += it.duration;
}
});
}
}
return durationList;
} catch (e) {
console.log(e);
}
};
// 洗稿获取音频回调 // 洗稿获取音频回调
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;
...@@ -337,18 +378,20 @@ export const getAudioCallback = (audio_task_id: string, len: number, liveInfo: a ...@@ -337,18 +378,20 @@ export const getAudioCallback = (audio_task_id: string, len: number, liveInfo: a
console.log(res.data); console.log(res.data);
if (res.data.length >= len) { if (res.data.length >= len) {
closeInterval(); closeInterval();
let audio_list = []; let audioList = [];
// 洗稿任务 res.data.forEach(async (item: any, index: number) => {
res.data.forEach((item: any) => {
let data = item.data; let data = item.data;
if (data && data.audio_address) { if (data && data.audio_address) {
audio_list.push(data.audio_address); audioList.push(data.audio_address);
} else { } else {
console.log('洗稿缺少参数'); console.log('洗稿缺少参数');
show_message('洗稿缺少参数'); show_message('洗稿缺少参数');
} }
}); });
let resultList = await audioStart(audio_list, true); // 获取音频时长
let durationList = await getAudioStartTimeAndEndTime(res.data);
console.log(durationList, '洗稿durationList');
let resultList = await audioStart(audioList, true);
// 提交 // 提交
await regenerate(resultList, liveInfo, live_id); await regenerate(resultList, liveInfo, live_id);
} }
......
import audiobufferToWav from 'audiobuffer-to-wav'; import audiobufferToWav from 'audiobuffer-to-wav';
import { writeLog } from '@/utils/pyqt'; import { callPyjsInWindow, writeLog } from '@/utils/pyqt';
// import lamejs from 'lamejs'; // import lamejs from 'lamejs';
import { getFile } from './tool'; import { getFile } from './tool';
import audioConversion from '@/worker/audioConversion.js?worker'; import audioConversion from '@/worker/audioConversion.js?worker';
...@@ -10,11 +10,25 @@ export const createAudioContext = () => { ...@@ -10,11 +10,25 @@ export const createAudioContext = () => {
const audioContext = createAudioContext(); const audioContext = createAudioContext();
// 等待python合并mp3文件
export const pyAudioMerge = async (list: Blob[]) => {
// <Blob>
return new Promise((reslove) => {
callPyjsInWindow('mergeAudio', list);
reslove(111);
});
};
// 获取音频文件的时长 // 获取音频文件的时长
export const getDurationOfAudioFile = (file: File) => { export const getDurationOfAudioFile = (file: File | string) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const audio = new Audio(); let audio = null;
if (typeof file === 'string') {
audio = new Audio(file);
} else {
audio = new Audio();
audio.src = URL.createObjectURL(file); audio.src = URL.createObjectURL(file);
}
audio.onloadedmetadata = () => { audio.onloadedmetadata = () => {
resolve(audio.duration); resolve(audio.duration);
...@@ -200,8 +214,10 @@ export async function audioMerge(filePaths: string[]) { ...@@ -200,8 +214,10 @@ export async function audioMerge(filePaths: string[]) {
return blob; return blob;
} else if (fileType == 'mp3') { } else if (fileType == 'mp3') {
// mp3--耗时操作,放入worker中 // mp3--耗时操作,放入worker中
const blob = await mp3Worker(blobList); // const blob = await mp3Worker(blobList);
return blob; // return blob;
// 通知python处理
await pyAudioMerge(blobList);
} }
} catch (error) { } catch (error) {
writeLog({ writeLog({
......
...@@ -24,12 +24,25 @@ export const injectWindow = (key: string, value: any, parent: string = '') => { ...@@ -24,12 +24,25 @@ export const injectWindow = (key: string, value: any, parent: string = '') => {
/** /**
* 调用python指定方法 * 调用python指定方法
*/ */
export const callPyjsInWindow = (name: string, value: any = '', callback: boolean = false, timeout: number = 1000) => { export const callPyjsInWindow = (
name: string,
value: any = '',
callback: boolean = false,
timeout: number = 1000,
toJson: boolean = true,
) => {
try { try {
const getValue = () => {
if (toJson) {
return JSON.stringify(value);
} else {
return value;
}
};
if (callback) { if (callback) {
// 返回一个Promise // 返回一个Promise
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
window.pyjs[name](JSON.stringify(value), function (response: any) { window.pyjs[name](getValue(), function (response: any) {
// 在这里处理返回的值 // 在这里处理返回的值
resolve(response); resolve(response);
}); });
...@@ -38,7 +51,7 @@ export const callPyjsInWindow = (name: string, value: any = '', callback: boolea ...@@ -38,7 +51,7 @@ export const callPyjsInWindow = (name: string, value: any = '', callback: boolea
}, timeout); }, timeout);
}); });
} }
return window.pyjs[name](JSON.stringify(value)); return window.pyjs[name](getValue());
} catch (e) { } catch (e) {
writeLog({ writeLog({
name: 'call python error', name: 'call python error',
......
...@@ -358,8 +358,18 @@ export const randomInt = (min: number, max: number) => { ...@@ -358,8 +358,18 @@ export const randomInt = (min: number, max: number) => {
// 从数组中随机取一个值 // 从数组中随机取一个值
export const randomIntFormList = (list: any[]) => { export const randomIntFormList = (list: any[]) => {
try {
let index = randomInt(0, list.length - 1); let index = randomInt(0, list.length - 1);
return list[index]; return list[index];
} catch (e) {
writeLog({
name: '从列表中取随机值失败',
value: list,
error: e,
});
console.log(e);
return list[0];
}
}; };
// 循环耗时测试 // 循环耗时测试
......
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