index.vue 33.6 KB
Newer Older
Administrator's avatar
Administrator committed
1
<script setup lang="ts">
周成波's avatar
周成波 committed
2
import { onMounted, reactive, ref, nextTick } from "vue";
周成波's avatar
周成波 committed
3
import { Sunny, UploadFilled } from "@element-plus/icons-vue";
4 5 6 7
import { ElMessage, genFileId,
  type UploadInstance,
  type UploadProps,
  type UploadRawFile } from "element-plus";
周成波's avatar
周成波 committed
8 9
import text2videoService from "@/api/service/text2videoService";
import utils from "@/utils/utils";
周成波's avatar
周成波 committed
10
import { useManyValues } from './compositions/useManyValues'
Administrator's avatar
Administrator committed
11

12
const debug = ref(import.meta.env.MODE === 'production' ? false : true);
周成波's avatar
周成波 committed
13
const loading = ref(false);
14 15
const dialogVisible = ref(false);
const dialogData = ref("");
周成波's avatar
周成波 committed
16
const default_data = useManyValues();
Administrator's avatar
Administrator committed
17
const form = reactive({
周成波's avatar
周成波 committed
18 19
  screen: default_data.screen,
  if_need_subtitle: default_data.if_need_subtitle,
周成波's avatar
周成波 committed
20 21
  chatgpt_prompt: "",
  chatgpt_answer: "",
22
  chatgpt_answer_roles: <Wm.RolesItem[]>[],
23
  all_roles: "",
周成波's avatar
周成波 committed
24 25 26
  adapt_result_json: <Wm.ScriptsItem[]>[],
  task_id: "",
  final_video: "",
Administrator's avatar
Administrator committed
27
});
周成波's avatar
周成波 committed
28 29
const sd_prompt_prefix = default_data.sd_prompt_prefix;
const sd_negative_prompt_prefix = default_data.sd_negative_prompt_prefix;
周成波's avatar
周成波 committed
30

周成波's avatar
周成波 committed
31 32 33 34 35 36 37 38
const wen_an_llm = default_data.llms.tyqw_online;
const role_llm = default_data.llms.tyqw_online;
const role_keywords_llm = default_data.llms.qwen_local;
const tuili_llm = default_data.llms.qwen_local;
const tuili_keyword_llm = default_data.llms.tyqw_online;
const fanyi_llm = default_data.llms.qwen_local;

const voice_rate = ref(-10)
周成波's avatar
周成波 committed
39 40
const voice_volume = ref(0)
const voice = ref("zh-CN-YunjianNeural")
周成波's avatar
周成波 committed
41
const bgm = ref("解忧曲")
42 43 44
const bgm_volume = ref(0.3)
const pwdCheckDialogVisible = ref(false);
const pwdCheckValue = ref("")
周成波's avatar
周成波 committed
45
const sub_font_color = ref("#FFFF00")
周成波's avatar
周成波 committed
46 47
const sub_font_size = ref(25)
const sub_position = ref(0.4)
周成波's avatar
周成波 committed
48

49

周成波's avatar
周成波 committed
50
onMounted(() => {
51
  // 初始化示例数据
周成波's avatar
周成波 committed
52
  onChangeScreen(form.screen);
53 54 55 56 57 58
  // 初始化密码框
  if (debug.value == true) {
    pwdCheckDialogVisible.value = false;
  } else {
    pwdCheckDialogVisible.value = true;
  }
周成波's avatar
周成波 committed
59 60
});

周成波's avatar
周成波 committed
61 62
const delay = (ms: any) => new Promise(res => setTimeout(res, ms));

周成波's avatar
周成波 committed
63 64
const onSubmitGpt = () => {
  text2videoService
周成波's avatar
周成波 committed
65
    .submitLLM(form.chatgpt_prompt, wen_an_llm.api)
周成波's avatar
周成波 committed
66
    .then((result: string) => {
67 68
      console.log(form.chatgpt_prompt);
      console.log(result);
周成波's avatar
周成波 committed
69
      form.chatgpt_answer = result;
周成波's avatar
周成波 committed
70 71 72
    })
    .catch((error: any) => {
      // console.error(error);
Administrator's avatar
Administrator committed
73
      ElMessage({
周成波's avatar
周成波 committed
74
        message: error,
周成波's avatar
周成波 committed
75 76 77 78
        type: "error",
      });
    });
};
周成波's avatar
周成波 committed
79

80 81 82 83 84 85 86 87 88
const onAdaptRoles = async () => {
  if (!form.chatgpt_answer || form.chatgpt_answer.length == 0) {
    ElMessage({
      message: "文案不能为空",
      type: "error",
    });
    return;
  }
  // 推理角色
周成波's avatar
周成波 committed
89
  form.chatgpt_answer_roles = [];
周成波's avatar
周成波 committed
90 91 92 93 94 95 96 97 98 99
  const adapt_restrict = `请理解这个故事:“${form.chatgpt_answer}”,给出这个故事中的所有角色,多个角色以逗号分隔。\n要求:只返回角色名称即可,不要添加其他的内容。`;
  let roles = await text2videoService.submitLLM(adapt_restrict, role_llm.api);
  form.all_roles = roles.replace(/。|(|)/g, '').replace(/、/g, ',');
  console.log(form.all_roles);
  const roles_arr = form.all_roles.split(/[,,]/);
  console.log(roles_arr);
  // 推理属性
  const attribute_options = default_data.role_attribute_options.map(option => option.value);
  for (const one_role of roles_arr) {
    // const adapt_attribute_restrict = `根据这个故事:“${form.chatgpt_answer}”,你认为这个角色:“${one_role}”是“${String(attribute_options)}”中的哪一种?请返回选择的结果。\n要求:只返回选择的结果即可,不要添加其他的内容。`;
周成波's avatar
周成波 committed
100 101
    // const adapt_attribute_restrict = `你认为这个角色:“${one_role}”是“${String(attribute_options)}”中的哪一种?请返回选择的结果。\n要求:只返回选择的结果即可,不要添加其他的内容。`;
    const adapt_attribute_restrict = `故事全文:“${form.chatgpt_answer}”,请理解故事全文,然后判断:“${one_role}”是“${String(attribute_options)}”中的哪一种?请返回选择的结果。\n要求:只返回选择的结果即可,不要添加其他的内容。`;
周成波's avatar
周成波 committed
102 103 104 105
    let attribute = await text2videoService.submitLLM(adapt_attribute_restrict, role_keywords_llm.api);
    form.chatgpt_answer_roles.push({
      "角色": one_role.trim(),
      "角色关键词": "",
周成波's avatar
周成波 committed
106
      "角色关键词英文": "",
周成波's avatar
周成波 committed
107 108 109 110 111
      "属性": attribute,
    });
  }
  console.log(form.chatgpt_answer_roles)
};
周成波's avatar
周成波 committed
112

周成波's avatar
周成波 committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133

const onAdaptRolesKeywords = async () => {
  if (!form.chatgpt_answer_roles || form.chatgpt_answer_roles.length == 0) {
    ElMessage({
      message: "总角色不能为空",
      type: "error",
    });
    return;
  }
  for (const one_role of form.chatgpt_answer_roles) {
    if (!one_role.属性) {
      ElMessage({
        message: `请选择 ${one_role.角色} 的属性`,
        type: "error",
      });
      return;
    }
  }
  loading.value = true;
  // 推理角色关键词
  try {
周成波's avatar
周成波 committed
134
    async function processRoles() {
周成波's avatar
周成波 committed
135
      for (const one_role of form.chatgpt_answer_roles) {
周成波's avatar
周成波 committed
136
        await delay(100);
周成波's avatar
周成波 committed
137 138 139 140 141 142 143
        let adapt_keyword_restrict = `请理解这个故事:“${form.chatgpt_answer}”,给出其中这个角色“${one_role.角色}”的关键词,以逗号分隔。包括但不限于:`;
        let temp_restrict = "";
        if (one_role.属性.includes("人")) {
          temp_restrict = `性别(可以发挥想象进行补充,但一定要有), 年龄(可以发挥想象进行补充,但一定要有),
           肤色(可以发挥想象进行补充,但一定要有), 衣服(可以发挥想象进行补充,但一定要有), 发型(可以发挥想象进行补充,但一定要有),
           发色(可以发挥想象进行补充,但一定要有), 脸色(可以发挥想象进行补充,但一定要有), 五官特点(可以发挥想象进行补充,但一定要有)`;
        } else {
144 145 146
          let temp_restrict_pre = "";
          if (one_role.属性.includes("动物")) { temp_restrict_pre = `哪一种动物(可以发挥想象进行补充,但一定要有),` }
          temp_restrict = `${temp_restrict_pre} 体型(可以发挥想象进行补充,但一定要有), 颜色(可以发挥想象进行补充,但一定要有),
周成波's avatar
周成波 committed
147 148 149 150 151 152 153 154 155
           四肢(可以发挥想象进行补充,但一定要有), 五官特点(可以发挥想象进行补充,但一定要有),
           身体(皮毛,羽毛,鳞片,肤色等,可以发挥想象进行补充,没有就不提供)`;
        }
        adapt_keyword_restrict = adapt_keyword_restrict + temp_restrict + "。回答限制在30个字左右。";
        let keywords = await text2videoService.submitLLM(adapt_keyword_restrict, role_keywords_llm.api);
        keywords = keywords.replace(/。/g, '').replace(/、/g, ',');
        one_role.角色关键词 = keywords;

        await delay(100);
156 157 158 159
        // const adapt_attribute_restrict_en = `你现在扮演专业的英语翻译的角色。请将这段文字“${keywords}”翻译为英语。\n要求:只返回英语即可,不要返回其他内容。`;
        // let keywords_en = await text2videoService.submitLLM(adapt_attribute_restrict_en, role_keywords_llm.api);
        let keywords_en = await text2videoService.submitTranslateToEn(keywords);
        console.log(keywords_en)
周成波's avatar
周成波 committed
160
        keywords_en = utils.filterChineseAndPunctuation(keywords_en.replace(/"/g, ''));
周成波's avatar
周成波 committed
161
        one_role.角色关键词英文 = keywords_en;
162
      }
周成波's avatar
周成波 committed
163 164 165
    }
    try {
      await processRoles();
166
      console.log(form.chatgpt_answer_roles)
周成波's avatar
周成波 committed
167 168 169 170 171
    } catch (error) {
      ElMessage({
        message: String(error),
        type: "error"
      });
172 173 174 175 176 177 178 179 180 181 182 183
    }
  } catch (error) {
    ElMessage({
      message: String(error),
      type: "error",
    });
  } finally {
    // 最终关闭loading(无论成功或失败)
    loading.value = false;
  }
};

周成波's avatar
周成波 committed
184

周成波's avatar
周成波 committed
185
const onAdapt = async () => {
周成波's avatar
周成波 committed
186
  if (!form.chatgpt_answer || form.chatgpt_answer.length == 0) {
周成波's avatar
周成波 committed
187
    ElMessage({
周成波's avatar
周成波 committed
188
      message: "文案不能为空",
周成波's avatar
周成波 committed
189 190 191
      type: "error",
    });
    return;
周成波's avatar
周成波 committed
192
  }
周成波's avatar
周成波 committed
193 194 195 196 197 198 199 200 201 202 203 204
  form.task_id = utils.genDateTimeStr();
  console.log(form.task_id)
  // 按标点拆分成分镜
  const sentences = utils.splitText(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(),
      "场景关键词": "",
周成波's avatar
周成波 committed
205
      "场景关键词英文": "",
周成波's avatar
周成波 committed
206 207
      "角色": "",
      "角色关键词": "",
周成波's avatar
周成波 committed
208
      "角色关键词英文": "",
周成波's avatar
周成波 committed
209
      "画面描述词": "",
周成波's avatar
周成波 committed
210
      "本镜配图": "src/assets/waiting.png",
周成波's avatar
周成波 committed
211 212 213 214
      "local_image_path": "",
    });
  }
  console.log(form.adapt_result_json)
周成波's avatar
周成波 committed
215 216
}

217

周成波's avatar
周成波 committed
218 219 220 221 222 223 224 225 226
const onAdaptScene = async () => {
  if (!form.adapt_result_json || form.adapt_result_json.length == 0) {
    ElMessage({
      message: "分镜不能为空",
      type: "error",
    });
    return;
  }
  loading.value = true;
227 228
  async function processScenes() {
    for (const item of form.adapt_result_json) {
周成波's avatar
周成波 committed
229
      await onAdaptOneScene(item);
230 231
    }
  }
周成波's avatar
周成波 committed
232
  try {
233
    await processScenes();
周成波's avatar
周成波 committed
234
    ElMessage({
235 236
      message: "all scene ok",
      type: "success"
周成波's avatar
周成波 committed
237
    });
周成波's avatar
周成波 committed
238
    console.log(form.adapt_result_json);
周成波's avatar
周成波 committed
239
  } catch (error) {
周成波's avatar
周成波 committed
240
    ElMessage({
周成波's avatar
周成波 committed
241
      message: String(error),
242
      type: "error"
周成波's avatar
周成波 committed
243
    });
周成波's avatar
周成波 committed
244
  } finally {
245
    loading.value = false; // 最终关闭loading(无论成功或失败)
周成波's avatar
周成波 committed
246
  }
周成波's avatar
周成波 committed
247
};
周成波's avatar
周成波 committed
248

周成波's avatar
周成波 committed
249 250

const onAdaptOneScene = async (item: any) => {
周成波's avatar
周成波 committed
251 252
  if (!item.场景描述) {
    ElMessage({
周成波's avatar
周成波 committed
253
      message: `分镜 ${item.编号} 场景描述不能为空`,
周成波's avatar
周成波 committed
254 255 256 257
      type: "error",
    });
    return;
  }
周成波's avatar
周成波 committed
258
  // 推理场景
周成波's avatar
周成波 committed
259
  try {
周成波's avatar
周成波 committed
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
    const adapt_restrict = `故事:\n${form.chatgpt_answer}\n
    指令:
    请理解这个故事,给出这个场景“${item.场景描述}”的关键词(年代(可以发挥想象进行补充,但一定要有),空间(可以发挥想象进行补充,但一定要有),
    时间段(可以发挥想象进行补充,但一定要有),地理环境(可以发挥想象进行补充,但一定要有),天气(可以发挥想象进行补充,但一定要有),
    物品(可以发挥想象进行补充,但一定要有),人物(可以发挥想象进行补充,但一定要有),镜头角度(可以发挥想象进行补充,但一定要有))。
    要求:
    关键词以逗号分隔。
    只要返回关键词,不需要其他的说明文字。`;
    const keywords = await text2videoService.submitLLM(adapt_restrict, tuili_llm.api);
    console.log(keywords)
    item.场景关键词 = keywords;

    // const adapt_restrict_en = `你现在扮演专业的英语翻译的角色。请将这段文字“${item.场景描述}”翻译为英语。\n要求:只返回英语即可,不要返回其他内容。`;
    // const keywords_en = await text2videoService.submitLLM(adapt_restrict_en, tuili_llm.api);
    let keywords_en = await text2videoService.submitTranslateToEn(keywords);
275
    console.log(keywords_en)
周成波's avatar
周成波 committed
276
    item.场景关键词英文 = utils.filterChineseAndPunctuation(keywords_en);
周成波's avatar
周成波 committed
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
  } catch (error) {
    ElMessage({
      message: String(error),
      type: "error",
    });
  }
};


const onAdaptSceneRoles = async () => {
  if (!form.adapt_result_json || form.adapt_result_json.length == 0) {
    ElMessage({
      message: "分镜不能为空",
      type: "error",
    });
    return;
  }
周成波's avatar
周成波 committed
294 295
  if (!form.all_roles) {
    ElMessage({
周成波's avatar
周成波 committed
296
      message: `总角色不能为空`,
周成波's avatar
周成波 committed
297 298 299 300
      type: "error",
    });
    return;
  }
周成波's avatar
周成波 committed
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
  loading.value = true;
  async function processScenes() {
    for (const item of form.adapt_result_json) {
      await onAdaptOneSceneRoles(item);
    }
  }
  try {
    await processScenes();
    console.log(form.adapt_result_json);
  } catch (error) {
    ElMessage({
      message: String(error),
      type: "error"
    });
  } finally {
    loading.value = false; // 最终关闭loading(无论成功或失败)
  }
};


const onAdaptOneSceneRoles = async (item: any) => {
  if (!item.场景描述) {
    ElMessage({
      message: `分镜 ${item.编号} 场景描述不能为空`,
      type: "error",
    });
    return;
  }
周成波's avatar
周成波 committed
329 330
  if (!form.all_roles) {
    ElMessage({
周成波's avatar
周成波 committed
331
      message: `总角色不能为空`,
周成波's avatar
周成波 committed
332 333 334 335
      type: "error",
    });
    return;
  }
周成波's avatar
周成波 committed
336 337
  // 推理角色
  try {
周成波's avatar
周成波 committed
338 339 340 341
    if (form.chatgpt_answer_roles.length === 0) {
      // 总角色为空
      item.角色 = '';
      item.角色关键词 = '';
342
    } else {
周成波's avatar
周成波 committed
343
      // 总角色不为空
周成波's avatar
周成波 committed
344 345 346 347 348 349
      // const adapt_role_restrict = `请理解这个故事:“${form.chatgpt_answer}”,针对其中的这个场景:“${item.场景描述}”,从所有角色:“${form.all_roles}”中选择本场景的角色,多个角色以逗号分隔。`;
      const adapt_role_restrict = `整个故事(“${form.chatgpt_answer}),\n\n本章节(${item.场景描述}),\n\n角色列表(${form.all_roles}),\n\n你是程序员,请返回给本章节出现的角色,注意,不要发挥想象,必须从角色列表中选出本章节出现过的角色,如果多个用逗号隔开。`;
      const item_roles = await text2videoService.submitLLM(adapt_role_restrict, tuili_keyword_llm.api);
      // console.log(adapt_role_restrict)
      // console.log(item_roles)
      item.角色 = item_roles.trim();
周成波's avatar
周成波 committed
350
      let role_kws = ""
周成波's avatar
周成波 committed
351
      let role_kws_en = ""
352
      const item_roles_arr = item_roles.split(/[,,、]/);
周成波's avatar
周成波 committed
353
      item_roles_arr.forEach( one_item_role => {
354
        let temp_role_kws = ""
周成波's avatar
周成波 committed
355
        let temp_role_kws_en = ""
356 357 358
        // 人工匹配角色关键词,先找想同的
        for (const i of form.chatgpt_answer_roles) {
          if (i["角色"].trim() == one_item_role.trim()) {
周成波's avatar
周成波 committed
359 360
            temp_role_kws = `[${i["角色关键词"]}]`;
            temp_role_kws_en = `[${i["角色关键词英文"]}]`;
361 362
            // 找到就ok
            break;
周成波's avatar
周成波 committed
363
          }
364 365 366 367 368
        }
        // 如果找不到相同的,则模糊匹配
        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())) {
周成波's avatar
周成波 committed
369 370
              temp_role_kws = `[${i["角色关键词"]}]`;
              temp_role_kws_en = `[${i["角色关键词英文"]}]`;
371 372 373 374 375 376
              // 匹配到一个就ok
              break;
            }
          }
        }
        role_kws = `${role_kws}${temp_role_kws}`;
周成波's avatar
周成波 committed
377
        role_kws_en = `${role_kws_en}${temp_role_kws_en}`;
周成波's avatar
周成波 committed
378 379
      })
      item.角色关键词 = role_kws;
周成波's avatar
周成波 committed
380
      item.角色关键词英文 = role_kws_en;
381
    }
周成波's avatar
周成波 committed
382 383 384 385
  } catch (error) {
    ElMessage({
      message: String(error),
      type: "error",
周成波's avatar
周成波 committed
386
    });
周成波's avatar
周成波 committed
387
  }
周成波's avatar
周成波 committed
388 389
};

周成波's avatar
周成波 committed
390 391 392 393 394 395 396 397 398

const onDraw = async () => {
  if (!form.adapt_result_json || form.adapt_result_json.length == 0) {
    ElMessage({
      message: "分镜不能为空",
      type: "error",
    });
    return;
  }
周成波's avatar
周成波 committed
399
  let is_all_ok = true;
周成波's avatar
周成波 committed
400
  for (const item of form.adapt_result_json) {
周成波's avatar
周成波 committed
401
    if (!item.场景关键词 && !item.角色关键词) {
周成波's avatar
周成波 committed
402
      ElMessage({
周成波's avatar
周成波 committed
403
        message: `分镜 ${item.编号} 关键词为空,请重新推理本镜`,
周成波's avatar
周成波 committed
404 405
        type: "error",
      });
周成波's avatar
周成波 committed
406 407 408 409 410 411 412
      is_all_ok = false;
      break;
    }
  };
  if (is_all_ok) {
    for (const item of form.adapt_result_json) {
      onDrawOne(item);
周成波's avatar
周成波 committed
413
    }
周成波's avatar
周成波 committed
414 415 416 417
  }
};


周成波's avatar
周成波 committed
418
const onDrawOne = async (item: any) => {
周成波's avatar
周成波 committed
419
  if (!item.场景关键词 && !item.角色关键词) {
周成波's avatar
周成波 committed
420
    ElMessage({
周成波's avatar
周成波 committed
421
      message: "本镜关键词为空,请重新推理本镜",
周成波's avatar
周成波 committed
422 423 424 425 426
      type: "error",
    });
    return;
  }
  // 翻译+画图
周成波's avatar
周成波 committed
427 428 429
  if (!form.task_id) {
    form.task_id = utils.genDateTimeStr();
    console.log(form.task_id)
周成波's avatar
周成波 committed
430 431
  }
  try {
周成波's avatar
周成波 committed
432
    item.本镜配图 = "src/assets/loading.gif";
周成波's avatar
周成波 committed
433 434 435 436 437 438 439 440 441 442 443
    // let temp_prompt = ""
    // if (item.场景描述) {temp_prompt = temp_prompt + `场景描述为:${item.场景描述}\n`};
    // if (item.场景关键词) {temp_prompt = temp_prompt + `场景关键词为:${item.场景关键词}\n`};
    // if (item.角色) {temp_prompt = temp_prompt + `场景中的角色有:${item.角色}\n`};
    // if (item.角色关键词) {temp_prompt = temp_prompt + `角色关键词为:${item.角色关键词}\n`};
    // const sd_describe = await text2videoService.submitLLM(
    //   `${temp_prompt}
    //   指令:
    //   请理解以上内容,并返回一段英文的描述。`, fanyi_llm.api
    // );
    // item.画面描述词 = sd_describe;
周成波's avatar
周成波 committed
444
    item.画面描述词 = item.场景关键词英文 + "," + item.角色关键词英文;
周成波's avatar
周成波 committed
445

周成波's avatar
周成波 committed
446
    const sd_prompt = item.画面描述词 + "," + sd_prompt_prefix;
周成波's avatar
周成波 committed
447 448 449 450 451 452
    let width = "960";
    let height = "540";
    if (form.screen == "竖屏") {
      width = "540";
      height = "960";
    }
453 454
    // console.log(sd_prompt);
    // console.log(sd_negative_prompt_prefix);
455 456 457 458 459
    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);
周成波's avatar
周成波 committed
460 461 462 463 464 465 466
    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",
    });
周成波's avatar
周成波 committed
467
    item.本镜配图 = ""
周成波's avatar
周成波 committed
468 469 470
  }
};

周成波's avatar
周成波 committed
471

周成波's avatar
周成波 committed
472
const onGenVideo = () => {
周成波's avatar
周成波 committed
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
  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;
周成波's avatar
周成波 committed
491
  console.log(form.adapt_result_json);
周成波's avatar
周成波 committed
492
  const video_param_detail = form.adapt_result_json.map(item => {
周成波's avatar
周成波 committed
493 494 495
    return {
      idx: item.编号,
      text: item.场景描述,
周成波's avatar
周成波 committed
496
      img_path: item.local_image_path
周成波's avatar
周成波 committed
497 498
    };
  });
周成波's avatar
周成波 committed
499 500 501 502
  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}`}
周成波's avatar
周成波 committed
503
  const video_param = {
周成波's avatar
周成波 committed
504
    task_id: form.task_id,
周成波's avatar
周成波 committed
505
    if_need_subtitle: form.if_need_subtitle,
周成波's avatar
周成波 committed
506
    lang: "zh",
周成波's avatar
周成波 committed
507
    task_info: video_param_detail,
周成波's avatar
周成波 committed
508 509 510 511
    rate: para_rate,
    volume: para_volume,
    voice: voice.value,
    bgm: bgm.value,
512
    bgm_volume: bgm_volume.value,
周成波's avatar
周成波 committed
513 514 515
    sub_font_size: String(sub_font_size.value),
    sub_font_color: sub_font_color.value,
    sub_position: String(1 - sub_position.value),
周成波's avatar
周成波 committed
516
  }
周成波's avatar
周成波 committed
517 518 519
  text2videoService
    .submitGenVideo(video_param)
    .then((result: string) => {
周成波's avatar
周成波 committed
520
      console.log(result);
周成波's avatar
周成波 committed
521 522
      form.final_video = "";
      form.final_video = result+"?v="+utils.genDateTimeStr();
朱国瑞's avatar
朱国瑞 committed
523
    })
周成波's avatar
周成波 committed
524 525 526 527 528 529 530 531
    .catch((error: any) => {
      // console.error(error);
      ElMessage({
        message: error,
        type: "error",
      });
    });
};
周成波's avatar
周成波 committed
532 533 534 535

const clean_demo = () => {
  form.chatgpt_prompt = "";
  form.chatgpt_answer = "";
536
  form.chatgpt_answer_roles = <Wm.RolesItem[]>[];
周成波's avatar
周成波 committed
537 538 539 540
  form.adapt_result_json = <Wm.ScriptsItem[]>[];
  form.task_id = "";
  form.final_video = "";
}
周成波's avatar
周成波 committed
541

542 543 544
const clean_roles = () => {
  form.chatgpt_answer_roles = <Wm.RolesItem[]>[];
}
周成波's avatar
周成波 committed
545 546 547
const clean_scenes = () => {
  form.adapt_result_json = <Wm.ScriptsItem[]>[];
}
548

周成波's avatar
周成波 committed
549 550 551 552 553 554
const onChangeScreen = (val: string) => {
  if (debug.value == true) {
    if (val == "横屏") {
      form.task_id = default_data.horizontal_data.task_id;
      form.chatgpt_prompt = default_data.horizontal_data.chatgpt_prompt;
      form.chatgpt_answer = default_data.horizontal_data.chatgpt_answer;
555
      form.chatgpt_answer_roles = default_data.horizontal_data.chatgpt_answer_roles;
周成波's avatar
周成波 committed
556 557 558 559 560 561
      form.adapt_result_json = default_data.horizontal_data.adapt_result_json;
      form.final_video = default_data.horizontal_data.final_video;
    } else {
      form.task_id = default_data.vertical_data.task_id;
      form.chatgpt_prompt = default_data.vertical_data.chatgpt_prompt;
      form.chatgpt_answer = default_data.vertical_data.chatgpt_answer;
562
      form.chatgpt_answer_roles = default_data.vertical_data.chatgpt_answer_roles;
周成波's avatar
周成波 committed
563 564 565 566 567
      form.adapt_result_json = default_data.vertical_data.adapt_result_json;
      form.final_video = default_data.vertical_data.final_video;
    }
  }
}
568

569
const showsdprompt = (item: any) => {
周成波's avatar
周成波 committed
570 571 572 573 574 575 576
  if (!item.画面描述词) {
    ElMessage({
      message: "还未绘图,请绘图后查看",
      type: "error",
    });
    return;
  }
577
  // alert(item.画面描述词)
周成波's avatar
周成波 committed
578
  dialogData.value = `${item.画面描述词},${sd_prompt_prefix}===== 反向提示词 =====${sd_negative_prompt_prefix}`;
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
  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();
周成波's avatar
周成波 committed
595
    form.adapt_result_json[id].local_image_path = val.data[0].path;
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
    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()
614
}
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636

const onPwdCheckDialog = () => {
  text2videoService
    .submitPwdCheck(pwdCheckValue.value)
    .then((result: string) => {
      if (result == "success") {
        pwdCheckDialogVisible.value = false;
      } else {
        ElMessage({
          message: result,
          type: "error",
        });
      }
    })
    .catch((error: any) => {
      ElMessage({
        message: error,
        type: "error",
      });
    });

}
周成波's avatar
周成波 committed
637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653

const onDeleteOne = (item: any) => {
  try {
    let delete_no = item.编号;
    // 删除记录
    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()};
    });
  } catch (error) {
    ElMessage({
      message: String(error),
      type: "error",
    });
  }
};
Administrator's avatar
Administrator committed
654 655 656 657
</script>

<template>
  <main class="home-container">
周成波's avatar
周成波 committed
658
    <!-- 标题 -->
Administrator's avatar
Administrator committed
659
    <el-divider content-position="left">text2video</el-divider>
周成波's avatar
周成波 committed
660
    <el-form :model="form" label-width="114px" v-loading="loading">
周成波's avatar
周成波 committed
661 662 663 664 665 666 667 668
      <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>
周成波's avatar
周成波 committed
669
      <el-form-item>
670
        <el-button type="success" @click="clean_demo">清除所有数据</el-button>
周成波's avatar
周成波 committed
671
      </el-form-item>
周成波's avatar
周成波 committed
672
      <!-- Prompt到文案 -->
673
      <el-form-item label="Prompt">
周成波's avatar
周成波 committed
674
        <el-input v-model="form.chatgpt_prompt" :autosize="true" type="textarea" />
Administrator's avatar
Administrator committed
675
      </el-form-item>
周成波's avatar
周成波 committed
676
      <el-form-item>
周成波's avatar
周成波 committed
677
        <el-button type="primary" @click="onSubmitGpt">生成文案({{wen_an_llm.name}}</el-button>
周成波's avatar
周成波 committed
678
      </el-form-item>
周成波's avatar
周成波 committed
679
      <el-form-item label="文案">
朱国瑞's avatar
朱国瑞 committed
680
        <el-input v-model="form.chatgpt_answer" :autosize="true" type="textarea" />
周成波's avatar
周成波 committed
681
      </el-form-item>
682 683
      <!-- 角色 -->
      <el-form-item>
周成波's avatar
周成波 committed
684
        <el-button type="primary" @click="onAdaptRoles">推理角色({{role_llm.name}}</el-button>
周成波's avatar
周成波 committed
685
        <el-button type="primary" @click="onAdaptRolesKeywords">推理角色关键词({{role_keywords_llm.name}}</el-button>
686
        <el-button plain @click="clean_roles">清空总角色列表</el-button>
687 688 689
      </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)">
周成波's avatar
周成波 committed
690
          <el-table-column prop="角色" label="角色" width="300">
691 692 693 694
            <template v-slot="scope">
              <el-input v-model="scope.row.角色" :autosize="true" type="textarea"></el-input>
            </template>
          </el-table-column>
周成波's avatar
周成波 committed
695 696 697 698 699 700 701 702 703 704 705 706
          <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-select>
            </template>
          </el-table-column>
707 708 709 710 711
          <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>
周成波's avatar
周成波 committed
712
          <el-table-column prop="角色关键词英文" label="角色关键词英文">
周成波's avatar
周成波 committed
713
            <template v-slot="scope">
周成波's avatar
周成波 committed
714
              <el-input v-model="scope.row.角色关键词英文" :autosize="true" type="textarea"></el-input>
周成波's avatar
周成波 committed
715 716
            </template>
          </el-table-column>
717 718
        </el-table>
      </el-form-item>
周成波's avatar
周成波 committed
719
      <!-- 分镜 -->
Administrator's avatar
Administrator committed
720
      <el-form-item>
周成波's avatar
周成波 committed
721 722
        <el-button type="primary" @click="onAdapt">分镜</el-button>
        <el-button type="primary" @click="onAdaptScene">推理场景({{tuili_llm.name}})</el-button>
周成波's avatar
周成波 committed
723
        <el-button type="primary" @click="onAdaptSceneRoles">推理场景中的角色({{tuili_keyword_llm.name}})</el-button>
周成波's avatar
周成波 committed
724 725
        <el-button type="primary" @click="onDraw">绘图</el-button>
        <el-button plain @click="clean_scenes">清空分镜列表</el-button>
周成波's avatar
周成波 committed
726
      </el-form-item>
周成波's avatar
周成波 committed
727 728
      <el-form-item label="分镜">
        <el-table :data="form.adapt_result_json" border style="width: 100%; z-index: calc(var(--el-table-index) -1)">
周成波's avatar
周成波 committed
729
          <el-table-column prop="编号" label="编号" width="55" />
周成波's avatar
周成波 committed
730 731
          <el-table-column prop="场景描述" label="场景描述">
            <template v-slot="scope">
朱国瑞's avatar
朱国瑞 committed
732
              <el-input v-model="scope.row.场景描述" :autosize="true" type="textarea"></el-input>
周成波's avatar
周成波 committed
733 734
            </template>
          </el-table-column>
周成波's avatar
周成波 committed
735
          <el-table-column prop="场景关键词" label="场景关键词">
周成波's avatar
周成波 committed
736
            <template v-slot="scope">
周成波's avatar
周成波 committed
737
              <el-text class="mx-1" size="small">{{ scope.row.场景关键词 }}</el-text>
周成波's avatar
周成波 committed
738
              <hr style="border: none; border-top: 1px dashed #999; margin: 5px 0;">
周成波's avatar
周成波 committed
739
              <el-text class="mx-1" size="small">{{ scope.row.场景关键词英文 }}</el-text>
周成波's avatar
周成波 committed
740 741
            </template>
          </el-table-column>
周成波's avatar
周成波 committed
742
          <el-table-column prop="角色" label="角色" width="150" >
周成波's avatar
周成波 committed
743
            <template v-slot="scope">
周成波's avatar
周成波 committed
744
              <el-text class="mx-1" size="small">{{ scope.row.角色 }}</el-text>
周成波's avatar
周成波 committed
745 746 747 748
            </template>
          </el-table-column>
          <el-table-column prop="角色关键词" label="角色关键词">
            <template v-slot="scope">
周成波's avatar
周成波 committed
749
              <el-text class="mx-1" size="small">{{ scope.row.角色关键词 }}</el-text>
周成波's avatar
周成波 committed
750
              <hr style="border: none; border-top: 1px dashed #999; margin: 5px 0;">
周成波's avatar
周成波 committed
751
              <el-text class="mx-1" size="small">{{ scope.row.角色关键词英文 }}</el-text>
周成波's avatar
周成波 committed
752 753
            </template>
          </el-table-column>
周成波's avatar
周成波 committed
754
          <el-table-column prop="本镜配图" label="本镜配图" width="300">
周成波's avatar
周成波 committed
755 756
            <template v-slot="scope">
              <div>
周成波's avatar
周成波 committed
757
                <el-image :src="scope.row.本镜配图" :zoom-rate="1.2" :max-scale="1.5" :min-scale="0.5"
周成波's avatar
周成波 committed
758 759
                  :preview-src-list="[scope.row.本镜配图]" fit="cover" :hide-on-click-modal="true"
                />
周成波's avatar
周成波 committed
760 761 762
              </div>
            </template>
          </el-table-column>
周成波's avatar
周成波 committed
763 764 765 766 767 768
          <el-table-column width="120" label="操作" align="center">
            <!-- 
            <template v-slot:header>
              <el-button type="danger" size="default" @click="">批量绘制所有图片</el-button>
            </template> 
            -->
周成波's avatar
周成波 committed
769
            <template v-slot="scope">
周成波's avatar
周成波 committed
770 771 772
              <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>
773 774 775 776 777 778 779 780 781 782 783
              <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.编号}"
              >
周成波's avatar
周成波 committed
784
                <el-button type="primary" size="small">上传图片</el-button>
785
              </el-upload>
周成波's avatar
周成波 committed
786
              <div style="margin: 5px 0"><el-button plain size="small" @click="showsdprompt(scope.row)">debug</el-button></div>
787 788 789 790 791 792 793 794 795 796 797
              <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>
周成波's avatar
周成波 committed
798
              <!-- <div style="margin: 10px 0"><el-button type="danger" size="small" @click="onDeleteOne(scope.row)">删除本镜</el-button></div> -->
周成波's avatar
周成波 committed
799 800 801 802
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
周成波's avatar
周成波 committed
803
      <!-- 生成视频 -->
周成波's avatar
周成波 committed
804
      <el-form-item label="设置">
805
        <span style="margin: 0 20px">TTS语速:</span>
周成波's avatar
周成波 committed
806 807 808
        <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>
809
        <span style="margin: 0 20px">TTS音量:</span>
周成波's avatar
周成波 committed
810 811 812
        <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>
813
        <span style="margin: 20px 20px 0 20px">TTS语音:</span>
周成波's avatar
周成波 committed
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
        <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"
          >
            <span style="float: left">{{ item.value }}</span>
            <span
              style="
                float: right;
                color: var(--el-text-color-secondary);
                font-size: 13px;
              "
              >{{ 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>
      </el-form-item>
      <el-form-item>
834
        <span style="margin: 0 20px">背景音乐:</span>
周成波's avatar
周成波 committed
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853
        <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"
          >
            <span style="float: left">{{ item.label }}</span>
            <span
              style="
                float: right;
                color: var(--el-text-color-secondary);
                font-size: 13px;
              "
              >{{ 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>
854
      <el-form-item>
855
        <span style="margin: 0 20px">背景音量:</span>
周成波's avatar
周成波 committed
856
        <el-slider v-model="bgm_volume" show-input :step="0.1" :min="0" :max="2" :marks="default_data.bgm_volume_marks" style="width: 600px" />
857 858
      </el-form-item>
      <el-form-item>
周成波's avatar
周成波 committed
859
        <span style="margin: 20px 20px">字幕合成:</span>
860
        <el-switch v-model="form.if_need_subtitle" active-value="true" inactive-value="false"/>
周成波's avatar
周成波 committed
861 862 863 864 865 866
        <div v-if="JSON.parse(form.if_need_subtitle.toLowerCase())">
          <span style="margin-left:30px;">字体颜色:</span>
          <el-color-picker v-model="sub_font_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>
周成波's avatar
周成波 committed
867
          <el-slider v-model="sub_position" :step="0.1" :min="0" :max="1" show-input vertical height="100px" />
周成波's avatar
周成波 committed
868
        </div>
869
      </el-form-item>
周成波's avatar
周成波 committed
870
      <el-form-item>
周成波's avatar
周成波 committed
871
        <el-button type="primary" @click="onGenVideo">生成视频</el-button>
周成波's avatar
周成波 committed
872
      </el-form-item>
周成波's avatar
周成波 committed
873 874 875
      <el-form-item>
        <video :src="form.final_video" controls></video>
      </el-form-item>
Administrator's avatar
Administrator committed
876
    </el-form>
877
    <!-- 授权密码框 -->
周成波's avatar
周成波 committed
878
    <el-dialog 
879 880 881 882 883 884 885 886 887
      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="密码">
周成波's avatar
周成波 committed
888
          <el-input v-model="pwdCheckValue" autocomplete="off" type="password" show-password @keyup.enter="onPwdCheckDialog()" />
889 890 891 892 893 894 895 896
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="onPwdCheckDialog()">ok</el-button>
        </div>
      </template>
    </el-dialog>
Administrator's avatar
Administrator committed
897 898
  </main>
</template>
Administrator's avatar
Administrator committed
899

Administrator's avatar
Administrator committed
900
<style lang="scss" scoped>
朱国瑞's avatar
朱国瑞 committed
901 902 903 904 905 906 907 908 909
.home-container {
  width: 100%;
}
</style>

<style lang="scss">
.home-container {
  .el-table .el-table__cell {
    z-index: calc(var(--el-table-index) -1);
周成波's avatar
周成波 committed
910
  }
朱国瑞's avatar
朱国瑞 committed
911
}
Administrator's avatar
Administrator committed
912
</style>