Commit 5dab215b authored by Administrator's avatar Administrator

add index_en

parent 6dd93cc2
<script setup lang="ts">
import { onMounted, reactive, ref } from "vue";
import { Sunny, UploadFilled } from "@element-plus/icons-vue";
import { ElMessage, genFileId,
type UploadInstance,
type UploadProps,
type UploadRawFile } from "element-plus";
import text2videoService from "@/api/service/text2videoService";
import utils from "@/utils/utils";
import { useManyValues } from './compositions/useManyValues'
const debug = ref(import.meta.env.MODE === 'production' ? false : true);
const loading = ref(false);
const dialogVisible = ref(false);
const dialogData = ref("");
const default_data = useManyValues();
const form = reactive({
screen: default_data.screen,
if_need_subtitle: default_data.if_need_subtitle,
chatgpt_prompt: "",
chatgpt_answer: "",
chatgpt_answer_roles: <Wm.RolesItem[]>[],
adapt_result_json: <Wm.ScriptsItem[]>[],
task_id: "",
final_video: "",
});
const sd_prompt_prefix = default_data.sd_prompt_prefix;
const sd_negative_prompt_prefix = default_data.sd_negative_prompt_prefix;
const tyqw = {'api': 'tyqw', 'name':'通义千问'};
const baichuan = {'api': 'langchain', 'name':'baichuan2-7b'};
const qwen = {'api': 'langchain', 'name':'Qwen-7B-Chat'};
const wenan_llm = qwen.api
const wenan_llm_name = qwen.name
const role_llm = tyqw.api
const role_llm_name = tyqw.name
const role_keywords_llm = qwen.api
const role_keywords_llm_name = qwen.name
const tuili_llm = qwen.api
const tuili_llm_name = qwen.name
const fanyi_llm = qwen.api
const fanyi_llm_name = qwen.name
onMounted(() => {
// 初始化示例数据
onChangeScreen(form.screen);
});
const delay = (ms: any) => new Promise(res => setTimeout(res, ms));
const onSubmitGpt = () => {
text2videoService
.submitGpt(form.chatgpt_prompt, wenan_llm)
.then((result: string) => {
console.log(form.chatgpt_prompt);
console.log(result);
form.chatgpt_answer = result;
})
.catch((error: any) => {
// console.error(error);
ElMessage({
message: error,
type: "error",
});
});
};
const onAdaptRoles = async () => {
if (!form.chatgpt_answer || form.chatgpt_answer.length == 0) {
ElMessage({
message: "文案不能为空",
type: "error",
});
return;
}
loading.value = true;
// 推理角色
form.chatgpt_answer_roles = [];
try {
const adapt_restrict = `
Instructions:
Please understand this story and provide all the characters in it, with multiple characters separated by commas`;
let roles = await text2videoService.submitGpt("story:\n" + form.chatgpt_answer + "\n" + adapt_restrict, role_llm);
roles = roles.replace(/。/g, '').replace(/、/g, ',')
console.log(roles)
const roles_arr = roles.split(/[,,]/);
console.log(roles_arr)
async function processRoles() {
for (const one_role of roles_arr) {
await delay(100);
const adapt_keyword_restrict = `
Instructions:
Please understand this story and provide the keywords for the character "${one_role.trim()}" (gender (can be supplemented with imagination, but must have it), age (can be supplemented with imagination, but must have it),
Skin color (can be supplemented with imagination, but must have it), clothing (can be supplemented with imagination, but must have it), hairstyle (can be supplemented with imagination, but must have it),
Hair color (can be supplemented with imagination, but must have it), facial color (can be supplemented with imagination, but must have it), facial features (can be supplemented with imagination, but must have it).
Requirement:
Keywords are separated by commas.
As long as the keyword is returned, no additional explanatory text is required.`;
let keywords = await text2videoService.submitGpt(form.chatgpt_answer + "\n" + adapt_keyword_restrict, role_keywords_llm);
keywords = keywords.replace(/。/g, '').replace(/、/g, ',')
form.chatgpt_answer_roles.push({
"角色": one_role.trim(),
"角色关键词": keywords.trim()+",dressed"
});
}
}
try {
await processRoles();
console.log(form.chatgpt_answer_roles)
} catch (error) {
ElMessage({
message: String(error),
type: "error"
});
} finally {
loading.value = false; // 最终关闭loading(无论成功或失败)
}
} catch (error) {
ElMessage({
message: String(error),
type: "error",
});
} finally {
// 最终关闭loading(无论成功或失败)
loading.value = false;
}
};
const onAdapt = async () => {
if (!form.chatgpt_answer || form.chatgpt_answer.length == 0) {
ElMessage({
message: "文案不能为空",
type: "error",
});
return;
}
loading.value = true;
form.task_id = utils.genDateTimeStr();
console.log(form.task_id)
// 按标点拆分成分镜
const sentences = utils.splitTextEn(form.chatgpt_answer);
console.log(sentences.length)
// 分镜
form.adapt_result_json = []
for (let i = 0; i < sentences.length; i++) {
form.adapt_result_json.push({
"编号": (i + 1).toString(),
"场景描述": sentences[i].trim(),
"场景关键词": "",
"角色": "",
"角色关键词": "",
"画面描述词": "",
"本镜配图": "",
"local_image_path": "",
});
}
console.log(form.adapt_result_json)
async function processScenes() {
for (const item of form.adapt_result_json) {
await onAdaptOne(item);
await delay(100);
await onDrawOne(item);
}
}
try {
await processScenes();
ElMessage({
message: "all scene ok",
type: "success"
});
console.log(form.adapt_result_json);
} catch (error) {
ElMessage({
message: String(error),
type: "error"
});
} finally {
loading.value = false; // 最终关闭loading(无论成功或失败)
}
};
const onAdaptOne = async (item: any) => {
if (!item.场景描述) {
ElMessage({
message: "分镜场景描述不能为空",
type: "error",
});
return;
}
// 推理关键词
try {
const adapt_restrict = `
Instructions:
Please understand this story and provide the keywords for the scene "${item.场景描述}" (era (can be supplemented with imagination, but must be present), space (can be supplemented with imagination, but must be present),
Time period (imagination can be used to supplement, but it must be present), geographical environment (imagination can be used to supplement, but it must be present), weather (imagination can be used to supplement, but it must be present),
Items (can be supplemented with imagination, but must be present), characters (can be supplemented with imagination, but must be present), camera angles (can be supplemented with imagination, but must be present).
Requirement:
Keywords are separated by commas.
As long as the keyword is returned, no additional explanatory text is required.
`;
const keywords = await text2videoService.submitGpt("story:\n" + form.chatgpt_answer + "\nall characters:\n"+ JSON.stringify(form.chatgpt_answer_roles)+"\n" + adapt_restrict);
// console.log(keywords)
const keywords_obj = utils.formatJsonObj(keywords.replace(/```json/g, '').replace(/```/g, ''))
// console.log(keywords_obj)
item.场景关键词 = JSON.stringify(keywords_obj[0]["Scene Keywords"]).replace(/"/g, '');
if (form.chatgpt_answer_roles.length === 0) {
// 总角色为空
item.角色 = '';
item.角色关键词 = '';
} else {
// 总角色不为空
item.角色 = JSON.stringify(keywords_obj[0]["Role"]).replace(/"/g, '');
item.角色关键词 = JSON.stringify(keywords_obj[0]["Role Keywords"]).replace(/"/g, '');
}
} catch (error) {
ElMessage({
message: String(error),
type: "error",
});
}
};
const onDrawOne = async (item: any) => {
if (!item.场景描述 && !item.场景关键词) {
ElMessage({
message: "场景描述和场景关键词不能都为空",
type: "error",
});
return;
}
// 翻译+画图
if (!form.task_id) {
form.task_id = utils.genDateTimeStr();
console.log(form.task_id)
}
try {
let temp_prompt = ""
if (item.场景描述) {temp_prompt = temp_prompt + `Scene description is: ${item.场景描述}\n`};
if (item.场景关键词) {temp_prompt = temp_prompt + `Scene keywords are: ${item.场景关键词}\n`};
if (item.角色) {temp_prompt = temp_prompt + `Characters in the scene are: ${item.角色}\n`};
if (item.角色关键词) {temp_prompt = temp_prompt + `Character keywords are: ${item.角色关键词}\n`};
const sd_describe = await text2videoService.submitGpt(
`${temp_prompt}
Instructions:
Please understand the above content and return an English description.`, fanyi_llm
);
item.画面描述词 = sd_describe;
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();
item.local_image_path = sd_img.local_image_path;
} catch (error) {
ElMessage({
message: String(error),
type: "error",
});
}
};
const onGenVideo = () => {
if (!form.adapt_result_json || form.adapt_result_json.length == 0 ) {
ElMessage({
message: "必要信息不能为空,请重新执行",
type: "error",
});
return;
}
let is_all_ok = true;
form.adapt_result_json.map(item => {
if (item.编号 == "" || item.场景描述 == "" || item.local_image_path == "") {
ElMessage({
message: `分镜 ${item.编号} 的必要信息为空,请重新执行`,
type: "error",
});
is_all_ok = false;
}
});
if (!is_all_ok) return;
console.log(form.adapt_result_json);
const video_param_detail = form.adapt_result_json.map(item => {
return {
idx: item.编号,
text: item.场景描述,
img_path: item.local_image_path
};
});
const video_param = {
task_id: form.task_id,
if_need_subtitle: form.if_need_subtitle,
lang: 'en',
task_info: video_param_detail,
}
text2videoService
.submitGenVideo(video_param)
.then((result: string) => {
console.log(result);
form.final_video = "";
form.final_video = result+"?v="+utils.genDateTimeStr();
})
.catch((error: any) => {
// console.error(error);
ElMessage({
message: error,
type: "error",
});
});
};
const clean_demo = () => {
form.chatgpt_prompt = "";
form.chatgpt_answer = "";
form.chatgpt_answer_roles = <Wm.RolesItem[]>[];
form.adapt_result_json = <Wm.ScriptsItem[]>[];
form.task_id = "";
form.final_video = "";
}
const clean_roles = () => {
form.chatgpt_answer_roles = <Wm.RolesItem[]>[];
}
const onChangeScreen = (val: string) => {
if (debug.value == true) {
if (val == "竖屏") {
form.task_id = default_data.en_vertical_data.task_id;
form.chatgpt_prompt = default_data.en_vertical_data.chatgpt_prompt;
form.chatgpt_answer = default_data.en_vertical_data.chatgpt_answer;
form.chatgpt_answer_roles = default_data.en_vertical_data.chatgpt_answer_roles;
form.adapt_result_json = default_data.en_vertical_data.adapt_result_json;
form.final_video = default_data.en_vertical_data.final_video;
}
}
}
const showsdprompt = (item: any) => {
// alert(item.画面描述词)
dialogData.value = item.画面描述词+ "," +sd_prompt_prefix+'===== negative ====='+sd_negative_prompt_prefix;
dialogVisible.value = true; // 打开对话框
}
const upload = ref<UploadInstance>()
const actionUrl = ref(
import.meta.env.MODE === 'production'
? '/file'
: import.meta.env.VITE_APP_BASE_API + '/file'
)
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();
form.adapt_result_json[id].local_image_path = val.data[0].path;
ElMessage({
message: '上传成功',
type: 'success'
})
} else {
ElMessage({
message: '上传失败',
type: 'error'
})
}
}
const handleExceed: UploadProps['onExceed'] = (files) => {
upload.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
upload.value!.handleStart(file)
upload.value!.submit()
}
</script>
<template>
<main class="home-container">
<!-- 标题 -->
<el-divider content-position="left">text2video</el-divider>
<el-form :model="form" label-width="114px" v-loading="loading">
<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-group>
</div>
</el-form-item>
<el-form-item>
<el-button type="success" @click="clean_demo">清除所有数据</el-button>
</el-form-item>
<!-- Prompt到文案 -->
<!-- <el-form-item label="Prompt">
<el-input v-model="form.chatgpt_prompt" :autosize="true" type="textarea" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmitGpt">生成文案({{wenan_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}})、推理角色关键词({{role_keywords_llm_name}})</el-button>
<el-button plain @click="clean_roles">清空总角色列表</el-button>
</el-form-item>
<el-form-item label="角色">
<el-table :data="form.chatgpt_answer_roles" border style="width: 100%; z-index: calc(var(--el-table-index) -1)">
<el-table-column prop="角色" label="角色">
<template v-slot="scope">
<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-input v-model="scope.row.角色关键词" :autosize="true" type="textarea"></el-input>
</template>
</el-table-column>
</el-table>
</el-form-item>
<!-- 分镜 -->
<el-form-item>
<el-button type="primary" @click="onAdapt">分镜、推理场景关键词({{tuili_llm_name}})、英文描述({{fanyi_llm_name}})、绘图</el-button>
</el-form-item>
<el-form-item label="分镜">
<el-table :data="form.adapt_result_json" border style="width: 100%; z-index: calc(var(--el-table-index) -1)">
<el-table-column prop="编号" label="编号" width="60" />
<el-table-column prop="场景描述" label="场景描述">
<template v-slot="scope">
<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-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-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-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"
/>
</div>
</template>
</el-table-column>
<el-table-column width="120" label="操作" align="center">
<!--
<template v-slot:header>
<el-button type="danger" size="default" @click="">批量绘制所有图片</el-button>
</template>
-->
<template v-slot="scope">
<div style="margin: 10px 0"><el-button type="primary" size="default" @click="onAdaptOne(scope.row)">推理关键词</el-button></div>
<div style="margin: 10px 0"><el-button type="primary" size="default" @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">上传图片</el-button>
</el-upload>
<div style="margin: 10px 0"><el-button plain @click="showsdprompt(scope.row)">debug</el-button></div>
<el-dialog
v-model=dialogVisible
width="80%"
>
<p>{{ dialogData }}</p>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false">ok</el-button>
</div>
</template>
</el-dialog>
</template>
</el-table-column>
</el-table>
</el-form-item>
<!-- 生成视频 -->
<el-form-item>
<el-button type="primary" @click="onGenVideo">生成视频</el-button>
</el-form-item>
<el-form-item>
<video :src="form.final_video" controls></video>
</el-form-item>
</el-form>
</main>
</template>
<style lang="scss" scoped>
.home-container {
width: 100%;
}
</style>
<style lang="scss">
.home-container {
.el-table .el-table__cell {
z-index: calc(var(--el-table-index) -1);
}
}
</style>
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