Commit 72ce5042 authored by 周成波's avatar 周成波

update

parent b734b417
......@@ -9,6 +9,8 @@ type MyMarkType = Record<number, MyMarkInterface | string>
export const useManyValues = () => {
const screen = "竖屏";
const horizontal_img_size = {width: "960", height: "540"};
const vertical_img_size = {width: "540", height: "960"};
const if_need_subtitle = "false";
const sd_prompt_prefix = `(dressed:1.5),best quality,masterpiece,realistic,HDR,UHD,8K,best quality,highres,absurdres,realistic,masterpiece,
......@@ -67,7 +69,7 @@ export const useManyValues = () => {
const vertical_data = {
task_id: "20240220181602687",
chatgpt_prompt: `生成一个50字的科幻小故事,阿凡达系列`,
chatgpt_answer: `"嘿,你绝对猜不到!一只松鼠竟敢挑战国宝熊猫,就为了争夺一块蛋糕!" 在宁静的森林里,一场奇特的食物大战正在上演。一只机灵的小松鼠,眼尖地发现了一块香气扑鼻的奶油蛋糕,正惬意地躺在熊猫阿宝的竹篮里。蛋糕上的水果点缀和醇厚的奶油似乎在向小松鼠招手,它的口水都快流成一条小溪了。 而慵懒的大熊猫阿宝,本打算用这块蛋糕作为午后小憩的甜点,却没料到这位“飞檐走壁”的小贼会来挑战他的权威。只见松鼠灵活地穿梭在树枝间,伺机抢夺那块诱人的蛋糕,而熊猫阿宝则憨态可掬地试图守护这份甜蜜。 于是乎,一场别开生面的蛋糕争夺战就此展开,松鼠施展浑身解数,上蹿下跳,熊猫阿宝也不甘示弱,笨拙中透着狡黠,场面既紧张又逗趣。这场较量究竟谁能胜出?是身手矫健的小松鼠,还是憨萌可爱的熊猫阿宝?一切悬念,都围绕着那块美味的蛋糕徐徐展开……`,
chatgpt_answer: `在宁静的森林里。一场奇特的食物大战正在上演。一只机灵的小松鼠。眼尖地发现了一块香气扑鼻的奶油蛋糕,正惬意地躺在熊猫阿宝的竹篮里。蛋糕上的水果点缀和醇厚的奶油似乎在向小松鼠招手,它的口水都快流成一条小溪了。`,
chatgpt_answer_roles: [],
adapt_result_json: [],
final_video: ``,
......@@ -258,6 +260,8 @@ export const useManyValues = () => {
return {
screen: screen,
horizontal_img_size: horizontal_img_size,
vertical_img_size: vertical_img_size,
sd_prompt_prefix: sd_prompt_prefix,
sd_negative_prompt_prefix: sd_negative_prompt_prefix,
llms: llms,
......
<script setup lang="ts">
import { onMounted, reactive, ref, nextTick } from "vue";
import { Sunny, UploadFilled } from "@element-plus/icons-vue";
import { ElMessage, genFileId,
import {
ElMessage, genFileId,
type UploadInstance,
type UploadProps,
type UploadRawFile } from "element-plus";
type UploadRawFile
} from "element-plus";
import text2videoService from "@/api/service/text2videoService";
import utils from "@/utils/utils";
import { useManyValues } from './compositions/useManyValues'
......@@ -16,6 +18,7 @@ const dialogData = ref("");
const default_data = useManyValues();
const form = reactive({
screen: default_data.screen,
img_size: <Wm.ImgSize>{},
if_need_subtitle: default_data.if_need_subtitle,
chatgpt_prompt: "",
chatgpt_answer: "",
......@@ -57,6 +60,12 @@ onMounted(() => {
} else {
pwdCheckDialogVisible.value = true;
}
// 初始化宽高
if (form.screen == "横屏") {
form.img_size = default_data.horizontal_img_size;
} else {
form.img_size = default_data.vertical_img_size;
}
});
const delay = (ms: any) => new Promise(res => setTimeout(res, ms));
......@@ -364,10 +373,10 @@ const onAdaptOneSceneRoles = async (item: any) => {
const temp_arr = item.角色.split(/[,,、]/);
const temp_arr_length = temp_arr.length;
////// 如果本镜的角色大于1个,则只保留没有出现过的角色,且保证只有一个
if(temp_arr_length > 1) {
if (temp_arr_length > 1) {
////// 获取本镜之前的所有角色
let role_history = "";
form.adapt_result_json.forEach( scene => {
form.adapt_result_json.forEach(scene => {
if (Number(scene.编号) < Number(item.编号)) {
role_history += scene.角色 + ",";
}
......@@ -415,7 +424,7 @@ const onAdaptOneSceneRoles = async (item: any) => {
}
}
// 如果找不到相同的,则模糊匹配
if (! temp_role_kws) {
if (!temp_role_kws) {
for (const i of form.chatgpt_answer_roles) {
if (i["角色"].includes(one_item_role.trim()) || one_item_role.includes(i["角色"].trim())) {
temp_role_kws = `${i["角色关键词"]}`;
......@@ -496,20 +505,14 @@ const onDrawOne = async (item: any) => {
item.画面描述词 = item.场景关键词英文 + "," + item.角色关键词英文;
const sd_prompt = item.画面描述词 + "," + sd_prompt_prefix;
let width = "960";
let height = "540";
if (form.screen == "竖屏") {
width = "540";
height = "960";
}
// console.log(sd_prompt);
// console.log(sd_negative_prompt_prefix);
const sampler_index = "DPM++ SDE Karras";
const seed = "-1";
const steps = "6";
const cfg_scale = "2";
const sd_img = await text2videoService.submitSD(form.task_id, item.编号, sd_prompt, sd_negative_prompt_prefix, width, height, sampler_index, seed, steps, cfg_scale);
item.本镜配图 = sd_img.domain_image_path+"?v="+utils.genDateTimeStr();
const sd_img = await text2videoService.submitSD(form.task_id, item.编号, sd_prompt, sd_negative_prompt_prefix, form.img_size.width, form.img_size.height, sampler_index, seed, steps, cfg_scale);
item.本镜配图 = sd_img.domain_image_path + "?v=" + utils.genDateTimeStr();
item.local_image_path = sd_img.local_image_path;
} catch (error) {
ElMessage({
......@@ -522,7 +525,7 @@ const onDrawOne = async (item: any) => {
const onGenVideo = () => {
if (!form.adapt_result_json || form.adapt_result_json.length == 0 ) {
if (!form.adapt_result_json || form.adapt_result_json.length == 0) {
ElMessage({
message: "必要信息不能为空,请重新执行",
type: "error",
......@@ -550,8 +553,8 @@ const onGenVideo = () => {
});
let para_rate = `${voice_rate.value}%`;
let para_volume = `${voice_volume.value}%`;
if(voice_rate.value >= 0){para_rate = `+${para_rate}`}
if(voice_volume.value >= 0){para_volume = `+${para_volume}`}
if (voice_rate.value >= 0) { para_rate = `+${para_rate}` }
if (voice_volume.value >= 0) { para_volume = `+${para_volume}` }
const video_param = {
task_id: form.task_id,
if_need_subtitle: form.if_need_subtitle,
......@@ -575,7 +578,7 @@ const onGenVideo = () => {
.then((result: string) => {
console.log(result);
form.final_video = "";
form.final_video = result+"?v="+utils.genDateTimeStr();
form.final_video = result + "?v=" + utils.genDateTimeStr();
})
.catch((error: any) => {
// console.error(error);
......@@ -639,15 +642,28 @@ const upload = ref<UploadInstance>()
const actionUrl = ref(
import.meta.env.MODE === 'production'
? '/file'
: import.meta.env.VITE_APP_BASE_API + '/file'
? '/file/upload_pic_and_modify'
: import.meta.env.VITE_APP_BASE_API + '/file/upload_pic_and_modify'
)
// 在分镜自定义上传图片时发现个bug
// 第一次上传没问题,但重复进行上传,会更新到最后一行上去。
// 奇怪,没找到原因。暂时先通过迂回的方法来处理。
let first_has_uploaded = false;
const handleUploadSuccess = (val: Wm.UploadResult) => {
if (val.code == 0){
// console.log(val)
const id = parseInt(val.message) - 1;
form.adapt_result_json[id].本镜配图 = val.data[0].url+"?v="+utils.genDateTimeStr();
if (val.code == 0) {
console.log(val)
let id = parseInt(val.message) - 1;
///// 迂回解决上述bug /////
// if (id == 0) { first_has_uploaded = true; }
// if (first_has_uploaded && id == form.adapt_result_json.length - 1) {
// console.log(first_has_uploaded);
// console.log(id);
// console.log(form.adapt_result_json.length);
// id = 0;}
/////////////////////////
form.adapt_result_json[id].本镜配图 = val.data[0].url + "?v=" + utils.genDateTimeStr();
form.adapt_result_json[id].local_image_path = val.data[0].path;
ElMessage({
message: '上传成功',
......@@ -661,7 +677,12 @@ const handleUploadSuccess = (val: Wm.UploadResult) => {
}
}
const handleExceed: UploadProps['onExceed'] = (files) => {
const onClearOnePic = (item: any) => {
item.本镜配图 = "";
item.local_image_path = "";
};
const handleUploadExceed: UploadProps['onExceed'] = (files) => {
upload.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
......@@ -669,6 +690,13 @@ const handleExceed: UploadProps['onExceed'] = (files) => {
upload.value!.submit()
}
const handleUploadError = (error: Error) => {
ElMessage({
message: String(error.message),
type: "error",
});
}
const onPwdCheckDialog = () => {
text2videoService
.submitPwdCheck(pwdCheckValue.value)
......@@ -697,7 +725,7 @@ const onDeleteOne = (item: any) => {
form.adapt_result_json = form.adapt_result_json.filter(item => item.编号 !== delete_no);
// 重新对记录进行编号
form.adapt_result_json = form.adapt_result_json.map((item, index) => {
return {...item, 编号: (index + 1).toString()};
return { ...item, 编号: (index + 1).toString() };
});
} catch (error) {
ElMessage({
......@@ -716,8 +744,8 @@ const onDeleteOne = (item: any) => {
<el-form-item>
<div>
<el-radio-group v-model="form.screen" @change="onChangeScreen">
<el-radio label="横屏" size="large" border/>
<el-radio label="竖屏" size="large" border/>
<el-radio label="横屏" size="large" border />
<el-radio label="竖屏" size="large" border />
</el-radio-group>
</div>
</el-form-item>
......@@ -729,15 +757,15 @@ const onDeleteOne = (item: any) => {
<el-input v-model="form.chatgpt_prompt" :autosize="true" type="textarea" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmitGpt">生成文案({{wen_an_llm.name}}</el-button>
<el-button type="primary" @click="onSubmitGpt">生成文案({{ wen_an_llm.name }}</el-button>
</el-form-item>
<el-form-item label="文案">
<el-input v-model="form.chatgpt_answer" :autosize="true" type="textarea" />
</el-form-item>
<!-- 角色 -->
<el-form-item>
<el-button type="primary" @click="onAdaptRoles">推理角色({{role_llm.name}}</el-button>
<el-button type="primary" @click="onAdaptRolesKeywords">推理角色关键词({{role_keywords_llm.name}}</el-button>
<el-button type="primary" @click="onAdaptRoles">推理角色({{ role_llm.name }}</el-button>
<el-button type="primary" @click="onAdaptRolesKeywords">推理角色关键词({{ role_keywords_llm.name }}</el-button>
<el-button plain @click="clean_roles">清空总角色列表</el-button>
</el-form-item>
<el-form-item label="角色">
......@@ -750,12 +778,8 @@ const onDeleteOne = (item: any) => {
<el-table-column prop="属性" label="属性" width="300">
<template v-slot="scope">
<el-select v-model="scope.row.属性" filterable allow-create :reserve-keyword="false">
<el-option
v-for="item in default_data.role_attribute_options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
<el-option v-for="item in default_data.role_attribute_options" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</template>
</el-table-column>
......@@ -774,8 +798,8 @@ const onDeleteOne = (item: any) => {
<!-- 分镜 -->
<el-form-item>
<el-button type="primary" @click="onAdapt">分镜</el-button>
<el-button type="primary" @click="onAdaptScene">推理场景({{tuili_llm.name}})</el-button>
<el-button type="primary" @click="onAdaptSceneRoles">推理场景中的角色({{tuili_keyword_llm.name}})</el-button>
<el-button type="primary" @click="onAdaptScene">推理场景({{ tuili_llm.name }})</el-button>
<el-button type="primary" @click="onAdaptSceneRoles">推理场景中的角色({{ tuili_keyword_llm.name }})</el-button>
<el-button type="primary" @click="onDraw">绘图</el-button>
<el-button plain @click="clean_scenes">清空分镜列表</el-button>
</el-form-item>
......@@ -791,27 +815,26 @@ const onDeleteOne = (item: any) => {
<template v-slot="scope">
<el-text class="mx-1" size="small">{{ scope.row.场景关键词 }}</el-text>
<hr style="border: none; border-top: 1px dashed #999; margin: 5px 0;">
<el-text class="mx-1" size="small">{{ scope.row.场景关键词英文 }}</el-text>
<el-input v-model="scope.row.场景关键词英文" :autosize="true" type="textarea"></el-input>
</template>
</el-table-column>
<el-table-column prop="角色" label="角色">
<template v-slot="scope">
<el-text class="mx-1" size="small">{{ scope.row.角色 }}<br/>{{ scope.row.info }}</el-text>
<el-text class="mx-1" size="small">{{ scope.row.角色 }}<br />{{ scope.row.info }}</el-text>
</template>
</el-table-column>
<el-table-column prop="角色关键词" label="角色关键词">
<template v-slot="scope">
<el-text class="mx-1" size="small">{{ scope.row.角色关键词 }}</el-text>
<hr style="border: none; border-top: 1px dashed #999; margin: 5px 0;">
<el-text class="mx-1" size="small">{{ scope.row.角色关键词英文 }}</el-text>
<el-input v-model="scope.row.角色关键词英文" :autosize="true" type="textarea"></el-input>
</template>
</el-table-column>
<el-table-column prop="本镜配图" label="本镜配图" width="300">
<template v-slot="scope">
<div>
<el-image :src="scope.row.本镜配图" :zoom-rate="1.2" :max-scale="1.5" :min-scale="0.5"
:preview-src-list="[scope.row.本镜配图]" fit="cover" :hide-on-click-modal="true"
/>
:preview-src-list="[scope.row.本镜配图]" fit="cover" :hide-on-click-modal="true" />
</div>
</template>
</el-table-column>
......@@ -825,24 +848,15 @@ const onDeleteOne = (item: any) => {
<div style="margin: 5px 0"><el-button type="primary" size="small" @click="onAdaptOneScene(scope.row)">推理场景</el-button></div>
<div style="margin: 5px 0"><el-button type="primary" size="small" @click="onAdaptOneSceneRoles(scope.row)">推理角色</el-button></div>
<div style="margin: 5px 0"><el-button type="primary" size="small" @click="onDrawOne(scope.row)">绘图</el-button></div>
<el-upload
class="upload-demo"
ref="upload"
list-type="picture"
:show-file-list="false"
:limit="1"
:action="actionUrl"
:on-success="handleUploadSuccess"
:on-exceed="handleExceed"
:data="{item_id: scope.row.编号}"
>
<el-button type="primary" size="small">上传图片</el-button>
<el-upload class="upload-demo" ref="upload" list-type="picture" :show-file-list="false" :limit="1"
accept=".png,.PNG,.jpg,.JPG,.jpeg,.JPEG,.gif,.GIF,.bmp,.BMP"
:action="actionUrl" :on-success="handleUploadSuccess" :on-exceed="handleUploadExceed"
:on-error="handleUploadError" :data="{ item_id: scope.row.编号, width: form.img_size.width, height: form.img_size.height }">
<el-button type="primary" size="small" @click="console.log(scope.row.编号)">上传图片</el-button>
</el-upload>
<!-- <div style="margin: 5px 0"><el-button plain size="small" @click="onClearOnePic(scope.row)">清除图片</el-button></div> -->
<div style="margin: 5px 0"><el-button plain size="small" @click="showsdprompt(scope.row)">debug</el-button></div>
<el-dialog
v-model=dialogVisible
width="80%"
>
<el-dialog v-model=dialogVisible width="80%">
<p>{{ dialogData }}</p>
<template #footer>
<div class="dialog-footer">
......@@ -858,66 +872,56 @@ const onDeleteOne = (item: any) => {
<!-- 生成视频 -->
<el-form-item label="设置">
<span style="margin: 0 20px">TTS语速:</span>
<el-slider v-model="voice_rate" show-input :min="-50" :max="50" :marks="default_data.marks" style="width: 900px" />
<el-slider v-model="voice_rate" show-input :min="-50" :max="50" :marks="default_data.marks"
style="width: 900px" />
</el-form-item>
<el-form-item>
<span style="margin: 0 20px">TTS音量:</span>
<el-slider v-model="voice_volume" show-input :min="-80" :max="80" :marks="default_data.marks" style="width: 900px" />
<el-slider v-model="voice_volume" show-input :min="-80" :max="80" :marks="default_data.marks"
style="width: 900px" />
</el-form-item>
<el-form-item>
<span style="margin: 20px 20px 0 20px">TTS语音:</span>
<el-select v-model="voice" placeholder="Select" style="width: 400px; margin-top: 20px;">
<el-option
v-for="item in default_data.voices"
:key="item.value"
:label="item.value"
:value="item.value"
>
<el-option v-for="item in default_data.voices" :key="item.value" :label="item.value" :value="item.value">
<span style="float: left">{{ item.value }}</span>
<span
style="
<span style="
float: right;
color: var(--el-text-color-secondary);
font-size: 13px;
"
>{{ item.label }}</span>
">{{ item.label }}</span>
</el-option>
</el-select>
<audio :src="'src/assets/edge-tts-voices/' + voice + '.mp3'" controls style="height: 30px; margin: 20px 0 0 10px;"></audio>
<audio :src="'src/assets/edge-tts-voices/' + voice + '.mp3'" controls
style="height: 30px; margin: 20px 0 0 10px;"></audio>
</el-form-item>
<el-form-item>
<span style="margin: 0 20px">背景音乐:</span>
<el-select v-model="bgm" placeholder="无" style="width: 400px;">
<el-option
v-for="item in default_data.bgm"
:key="item.value"
:label="item.value"
:value="item.value"
>
<el-option v-for="item in default_data.bgm" :key="item.value" :label="item.value" :value="item.value">
<span style="float: left">{{ item.label }}</span>
<span
style="
<span style="
float: right;
color: var(--el-text-color-secondary);
font-size: 13px;
"
>{{ item.value }}</span>
">{{ item.value }}</span>
</el-option>
</el-select>
<audio :src="'src/assets/bgm/' + bgm + '.mp3'" controls style="height: 30px; margin-left:10px;"></audio>
</el-form-item>
<el-form-item>
<span style="margin: 0 20px">背景音量:</span>
<el-slider v-model="bgm_volume" show-input :step="0.1" :min="0" :max="2" :marks="default_data.bgm_volume_marks" style="width: 600px" />
<el-slider v-model="bgm_volume" show-input :step="0.1" :min="0" :max="2" :marks="default_data.bgm_volume_marks"
style="width: 600px" />
</el-form-item>
<el-form-item>
<span style="margin: 20px 20px">字幕合成:</span>
<el-switch v-model="form.if_need_subtitle" active-value="true" inactive-value="false"/>
<el-switch v-model="form.if_need_subtitle" active-value="true" inactive-value="false" />
<div v-if="JSON.parse(form.if_need_subtitle.toLowerCase())">
<span style="margin-left:30px;">字体颜色:</span>
<el-color-picker v-model="sub_font_color"/>
<el-color-picker v-model="sub_font_color" />
<span style="margin-left:30px;">字体背景:</span>
<el-color-picker v-model="sub_bg_color"/>
<el-color-picker v-model="sub_bg_color" />
<span style="margin-left:30px;">字体大小:</span>
<el-input-number v-model="sub_font_size" :min="1" :max="50" controls-position="right" />
<span style="margin-left:30px;">在屏幕上的位置:</span>
......@@ -932,19 +936,15 @@ const onDeleteOne = (item: any) => {
</el-form-item>
</el-form>
<!-- 授权密码框 -->
<el-dialog
v-model=pwdCheckDialogVisible
title="请输入密码"
width="20%"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
>
<el-dialog v-model=pwdCheckDialogVisible title="请输入密码" width="20%" :close-on-click-modal="false"
:close-on-press-escape="false" :show-close="false">
<el-form :model="form">
<el-form-item label="密码">
<el-input v-model="pwdCheckValue" autocomplete="off" type="password" show-password @keyup.enter="onPwdCheckDialog()" />
<el-input v-model="pwdCheckValue" autocomplete="off" type="password" show-password
@keyup.enter="onPwdCheckDialog()" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="onPwdCheckDialog()">ok</el-button>
......
declare namespace Wm {
interface ImgSize {
"width": string,
"height": string,
}
interface ScriptsItem {
"编号": string,
"场景描述": string,
......
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