瀏覽代碼

1

dev_YWQ
congzc 2 年之前
父節點
當前提交
488e77b80f
共有 4 個檔案被更改,包括 363 行新增49 行删除
  1. +17
    -6
      src/apis/createVideo.js
  2. +1
    -1
      src/layout/components/AppMain.vue
  3. +203
    -0
      src/router/index copy.ts
  4. +142
    -42
      src/views/createVideo/index.vue

+ 17
- 6
src/apis/createVideo.js 查看文件

@@ -67,10 +67,11 @@ export function uploadProgressApi(videoId) {
* @params videoId * @params videoId
* @returns data * @returns data
*/ */
export function saveAudioApi(videoId) {
export function saveAudioApi(data) {
return request({ return request({
url: `/api/voiceMaterial/save?videoId=${videoId}`,
method: 'GET',
url: `/api/voiceMaterial/save`,
method: 'post',
data
}) })
} }


@@ -99,16 +100,26 @@ export function chooseTypeApi(id) {
}) })
} }



/**
* @description 试听
* @params id
* @returns data
*/
export function previewAudioApi(genTxt, voiceId, voiceStyle) {
return request({
url: `api/voiceMould/preview?genTxt=${genTxt}&voiceId=${voiceId}&voiceStyle=${voiceStyle}`,
method: 'GET',
})
}


/** /**
* @description 保存生成视频数据 * @description 保存生成视频数据
* @params data * @params data
* @returns data * @returns data
*/ */
export function userPhotoVideoApi(data) {
export function saveOrUpdateApi(data) {
return request({ return request({
url: `/api/userPhotoVideo`,
url: `/api/userPhotoVideo/saveOrUpdate`,
method: 'POST', method: 'POST',
data data
}) })


+ 1
- 1
src/layout/components/AppMain.vue 查看文件

@@ -6,7 +6,7 @@ const tagsViewStore = useTagsViewStore();


<template> <template>
<section class="app-main"> <section class="app-main">
<router-view v-slot="{ Component, route }">
<router-view :key="route" v-slot="{ Component, route }">
<transition name="router-fade" mode="out-in"> <transition name="router-fade" mode="out-in">
<keep-alive :include="tagsViewStore.cachedViews"> <keep-alive :include="tagsViewStore.cachedViews">
<component :is="Component" :key="route.fullPath" /> <component :is="Component" :key="route.fullPath" />


+ 203
- 0
src/router/index copy.ts 查看文件

@@ -0,0 +1,203 @@
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
import { getCurrentInstance } from "vue";

export const Layout = () => import("@/layout/index.vue");

// 静态路由
export const constantRoutes: RouteRecordRaw[] = [
{
path: "/redirect",
component: Layout,
meta: { hidden: true },
children: [
{
path: "/redirect/:path(.*)",
component: () => import("@/views/redirect/index.vue"),
},
],
},
// 登录
{
path: "/login",
component: () => import("@/views/login/index.vue"),
meta: { hidden: true },
name:'login'
},
{
path: "/signSucceed",
component: () => import("@/views/signSucceed/index.vue"),
meta: { hidden: true },
},
// 创建视频
{
path: "/",
component: Layout,
redirect: "/createVideo",
children: [
{
path: "createVideo",
component: () => import("@/views/createVideo/index.vue"),
name: "createVideo",
meta: {
title: "createVideo",
icon: "homepage",
affix: true,
name: "createVideo.title",
},
},
],
},
// 视频列表
{
path: "/",
component: Layout,
redirect: "/myCreating",
children: [
{
path: "myCreating",
component: () => import("@/views/myCreating/index.vue"),
name: "myCreating",
meta: {
title: "myCreating",
icon: "homepage",
affix: true,
name: "myCreating.title",
},
},
],
},
// 个人账户
{
path: "/",
component: Layout,
redirect: "/myAccount",
children: [
{
path: "myAccount",
component: () => import("@/views/myAccount/index.vue"),
name: "myAccount",
meta: {
title: "myAccount",
icon: "homepage",
affix: true,
name: "account.title",
},
},
],
},
// 商店
{
path: "/",
component: Layout,
redirect: "/myStore",
children: [
{
path: "myStore",
component: () => import("@/views/myStore/index.vue"),
name: "myStore",
meta: {
title: "myStore",
icon: "homepage",
affix: true,
name: "shop.title",
},
},
],
},

// {
// path: "/dashboard",
// component: Layout,
// redirect: "/dashboard",
// children: [
// {
// path: "dashboard",
// component: () => import("@/views/dashboard/index.vue"),
// name: "Dashboard",
// meta: { title: "dashboard", icon: "homepage", affix: true },
// },
// {
// path: "401",
// component: () => import("@/views/error-page/401.vue"),
// meta: { hidden: true },
// },
// {
// path: "404",
// component: () => import("@/views/error-page/404.vue"),
// meta: { hidden: true },
// },
// ],
// },

// 外部链接
/*{
path: '/external-link',
component: Layout,
children: [
{
path: 'https://www.cnblogs.com/haoxianrui/',
meta: { title: '外部链接', icon: 'link' }
}
]
}*/
// 多级嵌套路由
/* {
path: '/nested',
component: Layout,
redirect: '/nested/level1/level2',
name: 'Nested',
meta: {title: '多级菜单', icon: 'nested'},
children: [
{
path: 'level1',
component: () => import('@/views/nested/level1/index.vue'),
name: 'Level1',
meta: {title: '菜单一级'},
redirect: '/nested/level1/level2',
children: [
{
path: 'level2',
component: () => import('@/views/nested/level1/level2/index.vue'),
name: 'Level2',
meta: {title: '菜单二级'},
redirect: '/nested/level1/level2/level3',
children: [
{
path: 'level3-1',
component: () => import('@/views/nested/level1/level2/level3/index1.vue'),
name: 'Level3-1',
meta: {title: '菜单三级-1'}
},
{
path: 'level3-2',
component: () => import('@/views/nested/level1/level2/level3/index2.vue'),
name: 'Level3-2',
meta: {title: '菜单三级-2'}
}
]
}
]
},
]
}*/
];

/**
* 创建路由
*/
const router = createRouter({
history: createWebHashHistory(),
routes: constantRoutes as RouteRecordRaw[],
// 刷新时,滚动条位置还原
// 2023-5-23 添加平滑滚动 YWQ
scrollBehavior: () => ({ behavior: "smooth", left: 0, top: 0 }),
});

/**
* 重置路由
*/
export function resetRouter() {
router.replace({ path: "/login" });
}

export default router;

+ 142
- 42
src/views/createVideo/index.vue 查看文件

@@ -129,7 +129,13 @@
type="textarea" type="textarea"
:placeholder="$t('createVideo.aiText')" :placeholder="$t('createVideo.aiText')"
/> />
<div @click="insertIcon">🕗</div>
<span
class="pointer"
@click="getPreviewAudio"
style="margin-right: 10px; font-size: 30px"
>🕬</span
>
<span class="pointer" @click="insertIcon">🕗</span>
</div> </div>
<p>{{ $t("createVideo.languages") }}</p> <p>{{ $t("createVideo.languages") }}</p>
<!-- 语言 --> <!-- 语言 -->
@@ -188,9 +194,12 @@
:value="item" :value="item"
/> />
</el-select> </el-select>
<el-button color="#000" type="primary">{{
$t("createVideo.generateVideo")
}}</el-button>
<el-button @click="saveOrUpdate(1)" color="#000" type="primary">
<my-loading :isLoading="createLoading"></my-loading>
<span v-if="!createLoading">{{
$t("createVideo.generateVideo")
}}</span></el-button
>
</div> </div>
</el-tab-pane> </el-tab-pane>
<!-- ------------------------ 2 --> <!-- ------------------------ 2 -->
@@ -199,23 +208,24 @@
<!-- 上传视频 --> <!-- 上传视频 -->
<p> <p>
<el-icon class="icon-VideoCamera"><i-ep-VideoCamera /></el-icon> <el-icon class="icon-VideoCamera"><i-ep-VideoCamera /></el-icon>
上传
上传
</p> </p>
<div class="uploadVideo"> <div class="uploadVideo">
+ +
<input <input
accept="audio/*"
type="file" type="file"
ref="fileInput" ref="fileInput"
@click="e.target.value = null" @click="e.target.value = null"
@change="handleFileChange" @change="handleFileChange"
/> />
<video
<!-- <video
style="position: absolute; top: 0" style="position: absolute; top: 0"
v-if="videoSrc" v-if="videoSrc"
:src="videoSrc" :src="videoSrc"
ref="videoPlayer" ref="videoPlayer"
controls controls
></video>
></video> -->
</div> </div>
<!-- 录制MP3上传语音 --> <!-- 录制MP3上传语音 -->
<p> <p>
@@ -244,13 +254,16 @@
</div> </div>
<!-- <button @click="playRecording">播放录音</button> --> <!-- <button @click="playRecording">播放录音</button> -->
<audio v-if="audioUrl" controls :src="audioUrl"></audio> <audio v-if="audioUrl" controls :src="audioUrl"></audio>
<button v-if="audioUrl" @click="uploadAudio" class="pointer">
<!-- <button v-if="audioUrl" @click="uploadAudio" class="pointer">
上传音频 上传音频
</button>
</button> -->
</div> </div>
<el-button color="#000" type="primary">{{
$t("createVideo.generateVideo")
}}</el-button>
<el-button @click="saveOrUpdate(2)" color="#000" type="primary">
<my-loading :isLoading="createLoading"></my-loading>
<span v-if="!createLoading">{{
$t("createVideo.generateVideo")
}}</span>
</el-button>
</div> </div>
</el-tab-pane> </el-tab-pane>
<!-- ----------------------- 3 --> <!-- ----------------------- 3 -->
@@ -321,6 +334,9 @@
</el-tabs> </el-tabs>
</div> </div>
</div> </div>

<!-- 试听的mp3 -->
<audio autoplay :src="previewAudioUrl"></audio>
</template> </template>


<script setup> <script setup>
@@ -334,6 +350,9 @@ import {
saveAudioApi, saveAudioApi,
voiceTotalApi, voiceTotalApi,
chooseTypeApi, chooseTypeApi,
saveOrUpdateApi,
createVideoApi,
previewAudioApi,
} from "@/apis/createVideo"; } from "@/apis/createVideo";
import Recorder from "js-audio-recorder"; //mp3插件 import Recorder from "js-audio-recorder"; //mp3插件
import imageCompression from "browser-image-compression"; //压缩图片插件 import imageCompression from "browser-image-compression"; //压缩图片插件
@@ -366,7 +385,7 @@ function ChangeShowFaceList(index) {
} }
showFace.value = index; showFace.value = index;
} }
const faceItemActive = ref(); //高亮处理
const faceItemActive = ref(); //高亮处理和当前选择图片的ID
// 点击aifece // 点击aifece
function setImgUrl(url, id) { function setImgUrl(url, id) {
faceItemActive.value = id; faceItemActive.value = id;
@@ -478,6 +497,31 @@ async function chooseStyle() {
soundStyle.value = null; soundStyle.value = null;
soundStyleOptions.value = item.style; soundStyleOptions.value = item.style;
} }

// 试听
const previewAudioUrl = ref(null);
async function getPreviewAudio() {
if (!textareaContent.value) {
ElMessage.error("您还没有输入文案");
return;
}
if (!sound.value) {
ElMessage.error("您还没有选择声音");
return;
}

try {
const res = await previewAudioApi(
textareaContent.value,
sound.value,
soundStyle.value
);
previewAudioUrl.value = res.data.data;
console.log(previewAudioUrl.value);
} catch (error) {
ElMessage.error(error);
}
}
//#endregion //#endregion


//#region 录制MP3上传语音 //#region 录制MP3上传语音
@@ -488,7 +532,7 @@ const parameter = {
}; };
const recorder = new Recorder(parameter); const recorder = new Recorder(parameter);
const isRecording = ref(true); const isRecording = ref(true);
const audioUrl = ref(null);
const audioUrl = ref(null); // audio控件的url
const audioData = ref(""); const audioData = ref("");
const videoId = ref(null); //上传mp3的videoId,创建视频会用到 const videoId = ref(null); //上传mp3的videoId,创建视频会用到


@@ -520,65 +564,121 @@ const playRecording = () => {
} }
}; };
// 上传音频 // 上传音频
async function uploadAudio(params) {
async function uploadAudio() {
createLoading.value = true;
let formData = new FormData(); let formData = new FormData();
const timestamp = Date.now(); const timestamp = Date.now();
formData.append("file", audioData.value, timestamp + ".mp3"); formData.append("file", audioData.value, timestamp + ".mp3");
try { try {
const res = await videoUpload(formData); const res = await videoUpload(formData);
videoId.value = res.data.videoId; videoId.value = res.data.videoId;
ElMessage.success("上传成功!");
if (res) {
// ElMessage.success("上传成功!");
} else {
ElMessage.error("音频上传失败!");
return;
}
// 查询进度
intervalId = setInterval(() => {
uploadProgress(res.data.videoId);
}, 1000);
// ElMessage.success("上传成功!");
} catch (error) { } catch (error) {
ElMessage.error(error); ElMessage.error(error);
} }
} }
//#endregion ------------------------------------ //#endregion ------------------------------------


//#region 上传视频功能
//#region 上传频功能
const fileInput = ref(null); const fileInput = ref(null);
const videoSrc = ref(null);
// const videoId = ref(null);

let intervalId = null; // 用于存储 setInterval 的返回值 let intervalId = null; // 用于存储 setInterval 的返回值
const handleFileChange = async () => { const handleFileChange = async () => {
const file = fileInput.value.files[0]; const file = fileInput.value.files[0];
if (file) { if (file) {
const videoUrl = URL.createObjectURL(file); const videoUrl = URL.createObjectURL(file);
videoSrc.value = videoUrl;

let formData = new FormData();
const timestamp = Date.now();
formData.append("file", file, timestamp + ".mp3");
try {
const res = await videoUpload(formData);
// videoId.value = res.videoId;
if (res) {
ElMessage.success("上传成功!");
} else {
ElMessage.error("上传失败!");
return;
}
// 查询进度
intervalId = setInterval(() => {
uploadProgress(res.data.videoId);
}, 1000);
} catch (error) {
ElMessage.error(error);
}
audioUrl.value = videoUrl;
audioData.value = file;
} }
}; };
// 获取视频上传进度 // 获取视频上传进度
const afterSaveAudioId = ref(null);
async function uploadProgress(videoId) { async function uploadProgress(videoId) {
const res = await uploadProgressApi(videoId); const res = await uploadProgressApi(videoId);
if (res.data == "complete") { if (res.data == "complete") {
clearInterval(intervalId); clearInterval(intervalId);
const res2 = await saveAudioApi(videoId);
try {
const res2 = await saveAudioApi({ videoId: videoId });
afterSaveAudioId.value = res2.data.id; // 得到id
} catch (error) {
ElMessage.error(error);
}
// 定义参数
const saveOrUpdateData = {
personPhotoId: faceItemActive.value, //任务照片id,
voiceFrom: tabFrom.value, //:声音来源 1:来自选择模板,2:来自用户上传
paperwork: textareaContent.value, //文案
speakTypeStr: soundStyle.value, //声音风格
voiceMouldId: sound.value, //选择声音id voiceFrom=1 时必传
voiceMaterialId: afterSaveAudioId.value, //上传音频且保存音频后得到的id voiceFrom=2 时必传
};
try {
const res3 = await saveOrUpdateApi(saveOrUpdateData); // 保存数据
const res4 = await createVideoApi({ id: res3.data.id }); // 生成视频
if (res4.message == "success") {
ElMessage.success("视频正在生成,请耐心等待");
}
createLoading.value = false;
} catch (error) {
ElMessage.error(error);
createLoading.value = false;
}
} }
} }
//#endregion -------------------------------------- //#endregion --------------------------------------


//#region 生成视频 //#region 生成视频
// tab栏切换
const tabFrom = ref(1);
const createLoading = ref(false);
// 上传音频后,得到videoId // 上传音频后,得到videoId

// 保存数据
async function saveOrUpdate(index) {
if (createLoading.value == true) {
return;
}
tabFrom.value = index;
const saveOrUpdateData = {
personPhotoId: faceItemActive.value, //任务照片id,
voiceFrom: tabFrom.value, //:声音来源 1:来自选择模板,2:来自用户上传
paperwork: textareaContent.value, //文案
speakTypeStr: soundStyle.value, //声音风格
voiceMouldId: sound.value, //选择声音id voiceFrom=1 时必传
voiceMaterialId: afterSaveAudioId.value, //上传音频且保存音频后得到的id voiceFrom=2 时必传
};
if (index == 1) {
createLoading.value = true;
try {
const res2 = await saveOrUpdateApi(saveOrUpdateData); // 保存数据
const res3 = await createVideoApi({ id: res2.data.id }); // 生成视频
if (res3.message == "success") {
ElMessage.success("视频正在生成,请耐心等待");
}
createLoading.value = false;
} catch (error) {
ElMessage.error(error);
createLoading.value = false;
}
}
if (index == 2) {
try {
const res1 = await uploadAudio(); // 上传音频
} catch (error) {
ElMessage.error(error);
createLoading.value = false;
}
}
}
//#endregion ---------------------------- //#endregion ----------------------------


//#region //#region


Loading…
取消
儲存