2024-07-13 15:44:13 +08:00
|
|
|
|
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, isEmpty } from 'lodash'
|
|
|
|
|
|
import { ClipSetting } from '../../define/setting/clipSetting'
|
2024-08-03 12:46:12 +08:00
|
|
|
|
import { errorMessage, successMessage } from '../Public/generalTools'
|
2024-07-13 15:44:13 +08:00
|
|
|
|
import { ServiceBase } from '../../define/db/service/serviceBase'
|
|
|
|
|
|
import {
|
|
|
|
|
|
GetDoubaoErrorResponse,
|
|
|
|
|
|
GetKimiErrorResponse,
|
|
|
|
|
|
GetOpenAISuccessResponse,
|
|
|
|
|
|
GetRixApiErrorResponse
|
2024-09-15 14:35:33 +08:00
|
|
|
|
} from '../../define/response/openAIResponse'
|
2024-07-13 15:44:13 +08:00
|
|
|
|
import axios from 'axios'
|
2024-09-15 14:35:33 +08:00
|
|
|
|
import { ValidateJson } from '../../define/Tools/validate'
|
|
|
|
|
|
import { RetryWithBackoff } from '../../define/Tools/common'
|
2024-07-13 15:44:13 +08:00
|
|
|
|
const { v4: uuidv4 } = require('uuid') // 引入UUID库来生成唯一标识符
|
|
|
|
|
|
let tools = new Tools()
|
|
|
|
|
|
|
|
|
|
|
|
export class Writing extends ServiceBase {
|
2024-09-15 14:35:33 +08:00
|
|
|
|
pm: PublicMethod
|
2024-07-13 15:44:13 +08:00
|
|
|
|
constructor(global) {
|
|
|
|
|
|
super()
|
|
|
|
|
|
this.pm = new PublicMethod(global)
|
|
|
|
|
|
axios.defaults.baseURL = define.serverUrl
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-15 14:35:33 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* AI 请求发送
|
|
|
|
|
|
* @param {*} setting
|
|
|
|
|
|
* @param {*} aiData
|
|
|
|
|
|
* @param {*} word
|
|
|
|
|
|
* @returns
|
|
|
|
|
|
*/
|
|
|
|
|
|
async AIRequest(setting, aiData, word): Promise<string> {
|
|
|
|
|
|
// 开始请求AI
|
|
|
|
|
|
let axiosRes = await axios.post('/api/Forward/ForwardWord', {
|
|
|
|
|
|
promptTypeId: setting.gptType,
|
|
|
|
|
|
promptId: setting.gptData,
|
|
|
|
|
|
gptUrl: aiData.gpt_url + '/v1/chat/completions',
|
|
|
|
|
|
model: aiData.model,
|
|
|
|
|
|
machineId: global.machineId,
|
|
|
|
|
|
apiKey: aiData.api_key,
|
|
|
|
|
|
word: word
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 判断返回的状态,如果是失败的话直接返回错误信息
|
|
|
|
|
|
if (axiosRes.status != 200) {
|
|
|
|
|
|
throw new Error('请求失败')
|
|
|
|
|
|
}
|
|
|
|
|
|
let dataRes = axiosRes.data
|
|
|
|
|
|
if (dataRes.code == 1) {
|
|
|
|
|
|
// 获取成功
|
|
|
|
|
|
// 解析返回的数据
|
|
|
|
|
|
return GetOpenAISuccessResponse(dataRes.data);
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 系统报错
|
|
|
|
|
|
if (dataRes.code == 5000) {
|
|
|
|
|
|
throw new Error('系统错误,错误信息如下:' + dataRes.message)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 处理不同类型的错误消息
|
|
|
|
|
|
if (setting.gptAI == 'laiapi') {
|
|
|
|
|
|
throw new Error(GetRixApiErrorResponse(dataRes.data))
|
|
|
|
|
|
} else if (setting.gptAI == 'kimi') {
|
|
|
|
|
|
throw new Error(GetKimiErrorResponse(dataRes.data))
|
|
|
|
|
|
} else if (setting.gptAI == 'doubao') {
|
|
|
|
|
|
throw new Error(GetDoubaoErrorResponse(dataRes.data))
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error(dataRes.data)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 流式请求接口
|
|
|
|
|
|
* @param setting
|
|
|
|
|
|
* @param aiData
|
|
|
|
|
|
* @param word
|
|
|
|
|
|
*/
|
|
|
|
|
|
async AIRequestStream(setting, aiData, word, oldData: string) {
|
|
|
|
|
|
let body = {
|
|
|
|
|
|
promptTypeId: setting.gptType,
|
|
|
|
|
|
promptId: setting.gptData,
|
|
|
|
|
|
gptUrl: aiData.gpt_url,
|
|
|
|
|
|
model: aiData.model,
|
|
|
|
|
|
machineId: global.machineId,
|
|
|
|
|
|
apiKey: aiData.api_key,
|
|
|
|
|
|
word: word
|
|
|
|
|
|
}
|
|
|
|
|
|
var myHeaders = new Headers();
|
|
|
|
|
|
myHeaders.append("User-Agent", "Apifox/1.0.0 (https://apifox.com)");
|
|
|
|
|
|
myHeaders.append("Content-Type", "application/json");
|
|
|
|
|
|
|
|
|
|
|
|
var requestOptions = {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: myHeaders,
|
|
|
|
|
|
body: JSON.stringify(body),
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let resData = oldData;
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
fetch(define.serverUrl + "/api/Forward/ForwardWordStream", requestOptions)
|
|
|
|
|
|
.then(response => {
|
|
|
|
|
|
if (!response.body) {
|
|
|
|
|
|
throw new Error('ReadableStream not yet supported in this browser.');
|
|
|
|
|
|
}
|
|
|
|
|
|
const reader = response.body.getReader();
|
|
|
|
|
|
return new ReadableStream({
|
|
|
|
|
|
start(controller) {
|
|
|
|
|
|
function push() {
|
|
|
|
|
|
reader.read().then(({
|
|
|
|
|
|
done,
|
|
|
|
|
|
value
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
if (done) {
|
|
|
|
|
|
controller.close();
|
|
|
|
|
|
resolve(resData)
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 假设服务器发送的是文本数据
|
|
|
|
|
|
const text = new TextDecoder().decode(value);
|
|
|
|
|
|
resData += text
|
|
|
|
|
|
// 将数据返回前端
|
|
|
|
|
|
global.newWindow[0].win.webContents.send(DEFINE_STRING.GPT.GPT_STREAM_RETURN, resData)
|
|
|
|
|
|
controller.enqueue(value); // 可选:将数据块放入流中
|
|
|
|
|
|
push();
|
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
|
controller.error(err);
|
|
|
|
|
|
reject(err)
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
push();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(error => {
|
|
|
|
|
|
reject(error)
|
|
|
|
|
|
});
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async SplitWord(word: string, wordCount: number) {
|
|
|
|
|
|
let word_list = word.split('\n')
|
|
|
|
|
|
let new_word = []
|
|
|
|
|
|
let tmp_str = ''
|
|
|
|
|
|
let result = []
|
|
|
|
|
|
for (let i = 0; i < word_list.length; i++) {
|
|
|
|
|
|
const element = word_list[i];
|
|
|
|
|
|
if (tmp_str.length + element.length > wordCount) {
|
|
|
|
|
|
result.push({
|
|
|
|
|
|
index: i,
|
|
|
|
|
|
word: new_word.join('\n')
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
new_word = []
|
|
|
|
|
|
tmp_str = ""
|
|
|
|
|
|
new_word.push(element);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
tmp_str += ',' + element
|
|
|
|
|
|
new_word.push(element);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
result.push({
|
|
|
|
|
|
index: word_list.length,
|
|
|
|
|
|
word: new_word.join('\n')
|
|
|
|
|
|
})
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-08-04 15:00:00 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 文案处理,GPT进行推理
|
|
|
|
|
|
* @param {*} setting
|
|
|
|
|
|
* @param {*} word
|
|
|
|
|
|
* @returns
|
|
|
|
|
|
*/
|
2024-07-13 15:44:13 +08:00
|
|
|
|
async ActionStart(setting, word) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await this.InitService()
|
|
|
|
|
|
console.log(setting, word)
|
|
|
|
|
|
if (isEmpty(setting.gptType)) {
|
|
|
|
|
|
throw new Error('请选择GPT类型')
|
|
|
|
|
|
}
|
|
|
|
|
|
if (isEmpty(setting.gptData)) {
|
|
|
|
|
|
throw new Error('请选择GPT预设')
|
|
|
|
|
|
}
|
|
|
|
|
|
if (isEmpty(setting.gptAI)) {
|
|
|
|
|
|
throw new Error('请选择使用的AI')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 判断对应的AI的设置是不是有
|
|
|
|
|
|
let aiSetting = this.softService.GetSoftWarePropertyData('aiSetting')
|
2024-08-03 12:46:12 +08:00
|
|
|
|
if (isEmpty(aiSetting)) {
|
2024-07-13 15:44:13 +08:00
|
|
|
|
throw new Error('请先设置AI设置')
|
|
|
|
|
|
}
|
2024-08-03 12:46:12 +08:00
|
|
|
|
let tryP = ValidateJson(aiSetting)
|
|
|
|
|
|
if (!tryP) {
|
|
|
|
|
|
throw new Error('AI设置的数据格式不正确')
|
|
|
|
|
|
}
|
|
|
|
|
|
aiSetting = JSON.parse(aiSetting)
|
2024-07-13 15:44:13 +08:00
|
|
|
|
// 判断是不是有对应的AI设置
|
|
|
|
|
|
let aiData = get(aiSetting, setting.gptAI)
|
|
|
|
|
|
for (const aid in aiData) {
|
|
|
|
|
|
if (isEmpty(aid)) {
|
|
|
|
|
|
throw new Error('请先设置AI设置')
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (isEmpty(word)) {
|
|
|
|
|
|
throw new Error('请先设置文案')
|
|
|
|
|
|
}
|
2024-09-15 14:35:33 +08:00
|
|
|
|
let result = ''
|
|
|
|
|
|
if (setting.isSplit) {
|
|
|
|
|
|
// 这边拆分文案
|
|
|
|
|
|
let spiltWord = await this.SplitWord(word, setting.splitNumber)
|
|
|
|
|
|
console.log(spiltWord)
|
|
|
|
|
|
for (let i = 0; i < spiltWord.length; i++) {
|
|
|
|
|
|
const element = spiltWord[i];
|
|
|
|
|
|
if (setting.isStream) {
|
|
|
|
|
|
result += await RetryWithBackoff(async () => {
|
|
|
|
|
|
return await this.AIRequestStream(setting, aiData, element.word, result)
|
|
|
|
|
|
}, 3, 1000) + '\n'
|
2024-09-12 14:13:09 +08:00
|
|
|
|
} else {
|
2024-09-15 14:35:33 +08:00
|
|
|
|
result = await RetryWithBackoff(async () => {
|
|
|
|
|
|
return await this.AIRequest(setting, aiData, word)
|
|
|
|
|
|
}, 3, 1000)
|
2024-09-12 14:13:09 +08:00
|
|
|
|
}
|
2024-07-13 15:44:13 +08:00
|
|
|
|
}
|
2024-09-15 14:35:33 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
if (setting.isStream) {
|
|
|
|
|
|
result += await RetryWithBackoff(async () => {
|
|
|
|
|
|
return await this.AIRequestStream(setting, aiData, word, '')
|
|
|
|
|
|
}, 3, 1000) + '\r\n\n'
|
|
|
|
|
|
} else {
|
|
|
|
|
|
result = await RetryWithBackoff(async () => {
|
|
|
|
|
|
return await this.AIRequest(setting, aiData, word)
|
|
|
|
|
|
}, 3, 1000)
|
|
|
|
|
|
}
|
2024-07-13 15:44:13 +08:00
|
|
|
|
}
|
2024-09-15 14:35:33 +08:00
|
|
|
|
// let tasks =
|
|
|
|
|
|
|
|
|
|
|
|
// ExecuteConcurrently
|
|
|
|
|
|
return successMessage(result, "执行文案相关任务成功", 'Writing_ActionStart');
|
2024-07-13 15:44:13 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage(
|
|
|
|
|
|
'执行文案相关任务失败,失败信息如下:' + error.toString(),
|
|
|
|
|
|
'Writing_ActionStart'
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//#region 下面是文案的处理相关
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将文案信息写入到本地的文案文件中
|
|
|
|
|
|
* @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 = ''
|
2024-08-03 12:46:12 +08:00
|
|
|
|
let iii = 0
|
|
|
|
|
|
let sss = ''
|
2024-07-13 15:44:13 +08:00
|
|
|
|
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 = ''
|
2024-08-03 12:46:12 +08:00
|
|
|
|
|
2024-09-15 14:35:33 +08:00
|
|
|
|
for (let i = 0; i < data.length;) {
|
2024-08-03 12:46:12 +08:00
|
|
|
|
iii = i
|
|
|
|
|
|
sss = data[i].after_gpt
|
2024-07-13 15:44:13 +08:00
|
|
|
|
let srt_value = data[i].text
|
2024-09-15 14:35:33 +08:00
|
|
|
|
current_text = `字幕: “${srt_value}” 和文案第${text_count + 1} 行数据 “${textData[text_count].after_gpt
|
|
|
|
|
|
}” 数据不匹配(检查一下上下文)`
|
2024-07-13 15:44:13 +08:00
|
|
|
|
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)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-09-15 14:35:33 +08:00
|
|
|
|
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
|
2024-07-13 15:44:13 +08:00
|
|
|
|
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) {
|
2024-08-03 12:46:12 +08:00
|
|
|
|
// console.log(iii)
|
|
|
|
|
|
// console.log(sss)
|
2024-07-13 15:44:13 +08:00
|
|
|
|
return {
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
message: error.toString()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//#endregion
|
|
|
|
|
|
}
|