let path = require("path"); let fspromises = require("fs").promises; import { Tools } from "../tools"; import { DEFINE_STRING } from "../../define/define_string"; import { PublicMethod } from "../Public/publicMethod"; import { define } from "../../define/define"; import { get, has } from "lodash"; import { ClipSetting } from "../../define/setting/clipSetting"; const { v4: uuidv4 } = require('uuid'); // 引入UUID库来生成唯一标识符 let tools = new Tools(); export class Writing { constructor(global) { this.global = global this.pm = new PublicMethod(global); } /** * 将文案信息写入到本地的文案文件中 * @param {*} value */ async SaveWordTxt(value) { try { let word_path = path.join(global.config.project_path, "文案.txt"); await tools.writeArrayToFile(value, word_path); return { code: 1, message: "保存成功" } } catch (error) { throw new Error(error); } } /** * 将分镜的时间信息添加道配置文件中 * @param {*} value 是一个数组,0 :写入的数据 1:写入的属性 2:是否需要解析 */ async SaveCopywritingInformation(value) { try { return await this.pm.SaveConfigJsonProperty(value); } catch (error) { return { code: 0, message: error.toString() } } } /** * 获取Config.json文件中指定的属性 * @param {Array} value 传入的值 0 : 需要获取的属性 1: 返回的默认值 * @returns */ async GetConfigJson(value) { try { return await this.pm.GetConfigJson(value, false); } catch (error) { return { code: 0, message: error.toString() } } } /** * 获取当前项目下面的文案 */ async GetProjectWord() { try { // 先判断当前的项目文件下面是不是又配置文件。没有才读取文案 let srt_config_path = path.join(global.config.project_path, "scripts/config.json"); let isExist = await tools.checkExists(srt_config_path); let data = null; let isImformation = false; if (isExist) { let config_1 = JSON.parse(await fspromises.readFile(srt_config_path)); isImformation = has(config_1, 'srt_time_information'); if (isImformation) { data = JSON.parse(await fspromises.readFile(srt_config_path)).srt_time_information; } } if (!isExist || !isImformation) { let word_path = path.join(global.config.project_path, "文案.txt"); let isExistWord = await tools.checkExists(word_path); if (!isExistWord) { return { code: 0, message: "没有文案文件" } } let data = await fspromises.readFile(word_path, { encoding: 'utf-8' }); let lines = data.split(/\r?\n/); // 打印或返回这个数组 // console.log(lines); // 判断是不是有洗稿后的文件 let new_srt_path = path.join(global.config.project_path, "new_word.txt"); let isExistAfterGPTWord = await tools.checkExists(new_srt_path); let after_data = null; if (isExistAfterGPTWord) { after_data = (await fspromises.readFile(new_srt_path, { encoding: 'utf-8' })).split(/\r?\n/); } // 判断抽帧文件是不是存在 // 返回图片信息 let old_image_path_list = await tools.getFilesWithExtensions(path.join(global.config.project_path, "tmp/input_crop"), '.png'); let res = []; let lastId = ''; // 处理数据 for (let i = 0; i < lines.length; i++) { const line = lines[i]; let id = uuidv4(); let after_gpt = null; if (after_data != null) { after_gpt = after_data[i]; } let img_path = null; if (old_image_path_list != null) { img_path = old_image_path_list[i]; } let obj = { no: i + 1, id: id, lastId: lastId, word: line, old_image: img_path, after_gpt: after_gpt, start_time: null, end_time: null, timeLimit: null, subValue: [] } res.push(obj); lastId = id; } return { code: 1, type: 0, data: res } } else { let data = JSON.parse(await fspromises.readFile(srt_config_path)).srt_time_information; return { code: 1, type: 1, data: data } } } catch (error) { throw new Error(error); } } /** * 搭导入srt。然后加载时间轴。完全匹配失败的将会还是会导入然后手动手动切换 * @param {文案洗稿界面信息} textData */ async ImportSrtAndGetTime(data) { let textData = data[0]; let init_num = textData.length; let srt_path = data[1]; let current_text = ""; try { if (!srt_path) { // 获取项目下面的所有的srt let srtfiles = await tools.getFilesWithExtensions(global.config.project_path, '.srt'); if (srtfiles.length <= 0) { throw new Error("没有SRT文件"); } srt_path = srtfiles[0]; } let srt_data = (await fspromises.readFile(srt_path, 'utf-8')).toString("utf-8"); const entries = srt_data.replace(/\r\n/g, '\n').split('\n\n'); let data = entries.map(entry => { const lines = entry.split('\n'); if (lines.length >= 3) { const times = lines[1]; const text = lines.slice(2).join(' '); const [start, end] = times.split(' --> ').map(time => { const [hours, minutes, seconds] = time.split(':'); const [sec, millis] = seconds.split(','); return ((parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseInt(sec)) * 1000 + parseInt(millis)); }); return { start, end, text, id: uuidv4() }; } }).filter(entry => entry); // 开始匹配(洗稿后的) let srt_list = []; let srt_obj = null let text_count = 0; let tmp_str = ""; for (let i = 0; i < data.length;) { let srt_value = data[i].text; current_text = `字幕: “${srt_value}” 和文案第${text_count + 1} 行数据 “${textData[text_count].after_gpt}” 数据不匹配(检查一下上下文)`; let start_time = data[i].start; let end_time = data[i].end; let obj = { start_time, end_time, srt_value, id: data[i].id }; // 判断当前字幕是不是在当前句 // 不能用简单的包含,而是将数据进行去除特殊符号拼接后判断是不是相同 tmp_str += srt_value; if (tools.removePunctuationIncludingEllipsis(textData[text_count].after_gpt).startsWith(tools.removePunctuationIncludingEllipsis(tmp_str))) { if (srt_obj == null) { srt_obj = {} srt_obj.id = uuidv4(); srt_obj.start_time = start_time; srt_obj.value = srt_value; srt_obj.subValue = [obj]; } else { srt_obj.value = srt_obj.value + srt_value; srt_obj.subValue = [...srt_obj.subValue, obj]; } textData[text_count].start_time = srt_obj.start_time; textData[text_count].subValue = srt_obj.subValue srt_list.push(obj); i++; } else { // 判断下一句文件是不是以当当前巨开头。是的话继续。不是的话。直接返回后面的所有信息 if (tools.removePunctuationIncludingEllipsis(textData[text_count + 1].after_gpt).startsWith(tools.removePunctuationIncludingEllipsis(srt_value))) { textData[text_count].end_time = srt_list[srt_list.length - 1].end_time; text_count++; srt_obj = null; tmp_str = "" } else { // 将下面的数据直接 添加到textData后面。 // 修改当前行数据的结束事件为 if (srt_list.length > 0) { textData[text_count].end_time = srt_list[srt_list.length - 1].end_time; text_count++; } // 将后面的数据直接添加 let lastId = textData[textData.length - 1].id; for (let j = i; j < data.length; j++) { // 直接修改原有数据 if (text_count < init_num) { textData[text_count].subValue = [{ start_time: data[j].start, end_time: data[j].end, id: data[j].id, srt_value: data[j].text }] textData[text_count].start_time = data[j].start; textData[text_count].end_time = data[j].end; text_count++; } else { let id = uuidv4(); // 添加 let obj = { no: j + 1, id: id, word: null, lastId: lastId, old_image: path.normalize(define.zhanwei_image), after_gpt: null, start_time: data[j].start, end_time: data[j].end, subValue: [{ start_time: data[j].start, end_time: data[j].end, id: data[j].id, srt_value: data[j].text }] } lastId = id; textData.push(obj); } } this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, { code: 0, message: current_text }) return { code: 1, data: textData } } } } // 最后对齐 textData[textData.length - 1].end_time = srt_list[srt_list.length - 1].end_time // 返回数据 return { code: 1, data: textData } } catch (error) { return { code: 0, message: error.toString() } } } }