2024-08-18 16:22:19 +08:00
|
|
|
|
import { isEmpty } from "lodash";
|
|
|
|
|
|
import { GetSubtitleType, SubtitleSavePositionType } from "../../../define/enum/waterMarkAndSubtitle"
|
|
|
|
|
|
import { errorMessage, successMessage } from "../../Public/generalTools"
|
|
|
|
|
|
import { SoftWareServiceBasic } from "../ServiceBasic/softwareServiceBasic"
|
|
|
|
|
|
import { ValidateJson } from "../../../define/Tools/validate";
|
|
|
|
|
|
import { GeneralResponse } from "../../../model/generalResponse";
|
|
|
|
|
|
import { SubtitleModel } from "../../../model/subtitle";
|
|
|
|
|
|
import { define } from '../../../define/define'
|
|
|
|
|
|
import path from 'path'
|
|
|
|
|
|
import fs from 'fs'
|
|
|
|
|
|
import { CheckFileOrDirExist } from "../../../define/Tools/file";
|
|
|
|
|
|
import { BookServiceBasic } from "../ServiceBasic/bookServiceBasic";
|
|
|
|
|
|
import { Subtitle } from "./subtitle";
|
2024-10-20 23:19:22 +08:00
|
|
|
|
import { LogScheduler } from "../task/logScheduler";
|
2024-09-12 14:13:09 +08:00
|
|
|
|
import { BookTaskStatus, BookType, OperateBookType } from "../../../define/enum/bookEnum";
|
2024-11-09 16:46:06 +08:00
|
|
|
|
import { Book } from "../../../model/book/book";
|
2024-08-21 11:47:05 +08:00
|
|
|
|
import { TimeStringToMilliseconds } from "../../../define/Tools/time";
|
2024-08-18 16:22:19 +08:00
|
|
|
|
|
|
|
|
|
|
export class SubtitleService {
|
|
|
|
|
|
softWareServiceBasic: SoftWareServiceBasic
|
|
|
|
|
|
bookServiceBasic: BookServiceBasic
|
|
|
|
|
|
subtitle: Subtitle
|
2024-10-20 23:19:22 +08:00
|
|
|
|
logScheduler: LogScheduler
|
2024-08-18 16:22:19 +08:00
|
|
|
|
constructor() {
|
|
|
|
|
|
this.softWareServiceBasic = new SoftWareServiceBasic();
|
|
|
|
|
|
this.bookServiceBasic = new BookServiceBasic();
|
|
|
|
|
|
this.subtitle = new Subtitle();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//#region 设置相关的方法
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 初始化字幕设置
|
|
|
|
|
|
*/
|
|
|
|
|
|
async InitSubtitleSetting(): Promise<SubtitleModel.subtitleSettingModel> {
|
|
|
|
|
|
let defauleSetting = {
|
|
|
|
|
|
selectModel: GetSubtitleType.LAI_WHISPER,
|
|
|
|
|
|
laiWhisper: {
|
|
|
|
|
|
url: 'https://api.laitool.cc/',
|
|
|
|
|
|
apiKey: '你的LAI API KEY',
|
|
|
|
|
|
syncGPTAPIKey: false,
|
|
|
|
|
|
prompt: undefined
|
|
|
|
|
|
}
|
|
|
|
|
|
} as SubtitleModel.subtitleSettingModel
|
|
|
|
|
|
await this.softWareServiceBasic.SaveSoftwarePropertyData("subtitleSetting", JSON.stringify(defauleSetting));
|
|
|
|
|
|
return defauleSetting
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取提起字幕的设置
|
|
|
|
|
|
*/
|
|
|
|
|
|
async GetSubtitleSetting(): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
let subtitleSetting = undefined as SubtitleModel.subtitleSettingModel
|
|
|
|
|
|
let subtitleSettingString = await this.softWareServiceBasic.GetSoftWarePropertyData('subtitleSetting');
|
|
|
|
|
|
if (isEmpty(subtitleSettingString)) {
|
|
|
|
|
|
// 初始化
|
|
|
|
|
|
subtitleSetting = await this.InitSubtitleSetting();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (ValidateJson(subtitleSettingString)) {
|
|
|
|
|
|
subtitleSetting = JSON.parse(subtitleSettingString)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error("提起字幕设置解析失败,请重置后重新配置")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return successMessage(subtitleSetting, '获取提取字幕设置成功', "SubtitleService_GetSubtitleSetting")
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("获取字幕设置失败,失败信息如下:" + error.message, "SubtitleService_GetSubtitleSetting")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 重置识别字幕设置
|
|
|
|
|
|
*/
|
|
|
|
|
|
async ResetSubtitleSetting(): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
let subtitleSetting = await this.InitSubtitleSetting();
|
|
|
|
|
|
return successMessage(subtitleSetting, "重置字幕设置成功", "SubtitleService_ResetSubtitleSetting")
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("重置字幕设置失败,失败信息如下:" + error.message, "SubtitleService_ResetSubtitleSetting")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 保存提取字幕设置,并作相应的一些简单的检查
|
|
|
|
|
|
* @param subtitleSetting 要保存的数据结构体
|
|
|
|
|
|
*/
|
|
|
|
|
|
async SaveSubtitleSetting(subtitleSetting: SubtitleModel.subtitleSettingModel): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 判断模式,通过不同的模式判断是不是又必要检查
|
|
|
|
|
|
if (subtitleSetting.selectModel == GetSubtitleType.LOCAL_OCR) {
|
|
|
|
|
|
let localOcrPath = path.join(define.scripts_path, 'LaiOcr/LaiOcr.exe');
|
|
|
|
|
|
let fileIsExists = await CheckFileOrDirExist(localOcrPath);
|
|
|
|
|
|
if (!fileIsExists) {
|
|
|
|
|
|
throw new Error("当前模式未本地OCR,但是没有检查到对应的执行文件,请查看教程,安装对应的拓展");
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (subtitleSetting.selectModel == GetSubtitleType.LOCAL_WHISPER) {
|
|
|
|
|
|
// let localWhisper = path.join(define.scripts_path,'')
|
|
|
|
|
|
// 这个好像没有什么可以检查的
|
|
|
|
|
|
} else if (subtitleSetting.selectModel == GetSubtitleType.LAI_WHISPER) {
|
|
|
|
|
|
// 判断是不是laitool的,不是的话报错
|
|
|
|
|
|
if (!subtitleSetting.laiWhisper.url.includes('laitool')) {
|
|
|
|
|
|
throw new Error('该模式只能试用LAI API的接口请求');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (isEmpty(subtitleSetting.laiWhisper.apiKey)) {
|
|
|
|
|
|
throw new Error("当前模式为LAI API的接口请求,请输入LAI API KEY")
|
|
|
|
|
|
}
|
|
|
|
|
|
if (isEmpty(subtitleSetting.laiWhisper.url)) {
|
|
|
|
|
|
throw new Error("当前模式为LAI API的接口请求,请输入LAI API URL")
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error("未知的识别字幕模式")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查做完,开始保存数据
|
|
|
|
|
|
await this.softWareServiceBasic.SaveSoftwarePropertyData('subtitleSetting', JSON.stringify(subtitleSetting))
|
|
|
|
|
|
return successMessage(null, "保存提取文案设置成功", "SubtitleService_SaveSubtitleSetting");
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("保存提取文案设置失败,失败信息如下:" + error.message, "SubtitleService_SaveSubtitleSetting")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//#region 语音转文案或者是字幕识别
|
|
|
|
|
|
/**
|
2024-08-20 10:37:38 +08:00
|
|
|
|
* 反推提取文案的入口方法
|
|
|
|
|
|
* @param bookId 小说ID
|
|
|
|
|
|
* @param bookTaskId 小说批次任务ID
|
|
|
|
|
|
* @param operateBookType 操作的小说类型
|
|
|
|
|
|
* @param coverData 是不是要覆盖旧的数据
|
2024-09-12 14:13:09 +08:00
|
|
|
|
* @returns
|
2024-08-18 16:22:19 +08:00
|
|
|
|
*/
|
2024-08-20 10:37:38 +08:00
|
|
|
|
async GetCopywriting(bookId: string, bookTaskId: string, operateBookType: OperateBookType, coverData: boolean): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
2024-08-18 16:22:19 +08:00
|
|
|
|
try {
|
|
|
|
|
|
let subtitleSettingRes = await this.GetSubtitleSetting();
|
|
|
|
|
|
if (subtitleSettingRes.code == 0) {
|
|
|
|
|
|
throw new Error(subtitleSettingRes.message)
|
|
|
|
|
|
}
|
|
|
|
|
|
let subtitleSetting = subtitleSettingRes.data as SubtitleModel.subtitleSettingModel;
|
|
|
|
|
|
let res = undefined as GeneralResponse.ErrorItem | GeneralResponse.SuccessItem
|
|
|
|
|
|
|
|
|
|
|
|
let bookTaskDetails = undefined as Book.SelectBookTaskDetail[]
|
|
|
|
|
|
|
|
|
|
|
|
let tempBookTaskId = bookTaskId
|
|
|
|
|
|
if (operateBookType == OperateBookType.BOOKTASK) {
|
|
|
|
|
|
bookTaskDetails = await this.bookServiceBasic.GetBookTaskDetailData({
|
|
|
|
|
|
bookId: bookId,
|
|
|
|
|
|
bookTaskId: bookTaskId
|
|
|
|
|
|
})
|
|
|
|
|
|
} else if (operateBookType == OperateBookType.BOOKTASKDETAIL) {
|
|
|
|
|
|
let tempBookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(bookTaskId)
|
|
|
|
|
|
tempBookTaskId = tempBookTaskDetail.bookTaskId
|
|
|
|
|
|
bookTaskDetails = [tempBookTaskDetail]
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error("未知的操作类型")
|
|
|
|
|
|
}
|
2024-08-20 10:37:38 +08:00
|
|
|
|
|
|
|
|
|
|
if (!coverData) { // 不覆盖数据,将已经有的数据过滤掉
|
|
|
|
|
|
bookTaskDetails = bookTaskDetails.filter(item => isEmpty(item.afterGpt) && isEmpty(item.word))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-08-18 16:22:19 +08:00
|
|
|
|
if (bookTaskDetails.length <= 0) {
|
2024-08-20 10:37:38 +08:00
|
|
|
|
throw new Error("分镜信息不存在 / 已经有文案,无需提取");
|
2024-08-18 16:22:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
let { book, bookTask } = await this.bookServiceBasic.GetBookAndTask(bookId, tempBookTaskId)
|
|
|
|
|
|
|
|
|
|
|
|
switch (subtitleSetting.selectModel) {
|
|
|
|
|
|
case GetSubtitleType.LOCAL_OCR:
|
|
|
|
|
|
res = await this.subtitle.GetCopywritingByLocalOcr(book, bookTask, bookTaskDetails)
|
|
|
|
|
|
break;
|
|
|
|
|
|
case GetSubtitleType.LOCAL_WHISPER:
|
|
|
|
|
|
throw new Error("本地Whisper暂时不支持")
|
|
|
|
|
|
break;
|
|
|
|
|
|
case GetSubtitleType.LAI_WHISPER:
|
|
|
|
|
|
res = await this.subtitle.GetCopywritingByLaiWhisper(book, bookTask, bookTaskDetails, subtitleSetting)
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
throw new Error("未知的识别字幕模式")
|
|
|
|
|
|
}
|
2024-11-02 18:18:55 +08:00
|
|
|
|
if (res.code == 0) {
|
|
|
|
|
|
throw new Error(res.message)
|
|
|
|
|
|
}
|
2024-08-18 16:22:19 +08:00
|
|
|
|
if (operateBookType == OperateBookType.BOOKTASKDETAIL) {
|
|
|
|
|
|
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(bookTaskId)
|
|
|
|
|
|
return successMessage(bookTaskDetail.afterGpt, "获取文案成功", "ReverseBook_GetCopywriting")
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return res
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("获取分镜数据失败,失败信息如下:" + error.message, 'ReverseBook_GetCopywriting')
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-09-04 19:49:20 +08:00
|
|
|
|
//#endregion
|
2024-08-18 16:22:19 +08:00
|
|
|
|
|
2024-09-04 19:49:20 +08:00
|
|
|
|
//#region 文案相关的操作
|
2024-08-18 16:22:19 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 导出指定导出指定小说的文案
|
|
|
|
|
|
* @param bookTaskId 小说批次任务ID
|
2024-09-12 14:13:09 +08:00
|
|
|
|
* @returns
|
2024-08-18 16:22:19 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async ExportCopywriting(bookTaskId: string): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
|
|
|
|
|
try {
|
2024-08-21 11:47:05 +08:00
|
|
|
|
let bookTask = await this.bookServiceBasic.GetBookTaskDataById(bookTaskId)
|
2024-08-18 16:22:19 +08:00
|
|
|
|
let book = await this.bookServiceBasic.GetBookDataById(bookTask.bookId)
|
|
|
|
|
|
let bookTaskDetails = await this.bookServiceBasic.GetBookTaskDetailData({
|
|
|
|
|
|
bookId: book.id,
|
|
|
|
|
|
bookTaskId: bookTaskId
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
let emptyList = []
|
|
|
|
|
|
let content = []
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是不是所有的里面都有文案
|
|
|
|
|
|
for (let i = 0; i < bookTaskDetails.length; i++) {
|
|
|
|
|
|
const element = bookTaskDetails[i];
|
|
|
|
|
|
if (isEmpty(element.afterGpt)) {
|
|
|
|
|
|
emptyList.push(element.name)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
content.push(element.afterGpt)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (emptyList.length > 0) {
|
|
|
|
|
|
throw new Error(`以下分镜没有文案:${emptyList.join("\n")}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 写出文案
|
|
|
|
|
|
let contentStr = content.join("。\n");
|
|
|
|
|
|
contentStr = contentStr + '。'
|
|
|
|
|
|
let wordPath = path.join(book.bookFolderPath, "文案.txt")
|
|
|
|
|
|
await fs.promises.writeFile(wordPath, contentStr, 'utf-8')
|
|
|
|
|
|
return successMessage(wordPath, "导出文案成功", "ReverseBook_ExportCopywriting")
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("导出文案失败,失败信息如下:" + error.message, 'ReverseBook_ExportCopywriting')
|
|
|
|
|
|
}
|
2024-08-21 11:47:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-04 19:49:20 +08:00
|
|
|
|
/**
|
2024-09-12 14:13:09 +08:00
|
|
|
|
* 导入修改过后的文案数据
|
|
|
|
|
|
* @param bookId
|
|
|
|
|
|
* @param bookTaskId
|
|
|
|
|
|
* @param txtPath
|
|
|
|
|
|
* @returns
|
2024-09-04 19:49:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async ImportCopywriting(bookId: string, bookTaskId: string, txtPath: string): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
let word = await fs.promises.readFile(txtPath, 'utf-8');
|
|
|
|
|
|
let wordLines = word.split('\n').map(line => line.trim()).filter(line => line.length > 0);
|
|
|
|
|
|
// 判断小说类型,是反推的话,文案和分镜数据要对应
|
|
|
|
|
|
let book = await this.bookServiceBasic.GetBookDataById(bookId)
|
|
|
|
|
|
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({
|
|
|
|
|
|
bookId: bookId,
|
|
|
|
|
|
bookTaskId: bookTaskId
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
if (book.type == BookType.MJ_REVERSE || book.type == BookType.SD_REVERSE) {
|
|
|
|
|
|
if (wordLines.length != bookTaskDetail.length) {
|
|
|
|
|
|
throw new Error("文案行数和分镜数据不对应,请检查")
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (book.type == BookType.ORIGINAL) {
|
|
|
|
|
|
// 原创这边也要做些判断,待定
|
|
|
|
|
|
throw new Error("原创小说暂时不支持导入文案");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error("未知的小说类型,请检查")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let result = []
|
|
|
|
|
|
// 这边开始导入文案,这边使用事务
|
|
|
|
|
|
this.bookServiceBasic.transaction((realm) => {
|
|
|
|
|
|
for (let i = 0; i < bookTaskDetail.length; i++) {
|
|
|
|
|
|
const element = bookTaskDetail[i];
|
|
|
|
|
|
let btd = realm.objectForPrimaryKey("BookTaskDetail", element.id);
|
|
|
|
|
|
let ag = wordLines[i] ? wordLines[i] : ''
|
|
|
|
|
|
|
|
|
|
|
|
btd.afterGpt = ag
|
|
|
|
|
|
result.push({
|
|
|
|
|
|
bookTaskDetailId: element.id,
|
|
|
|
|
|
afterGpt: ag
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
return successMessage(result, "导入文案成功", "ReverseBook_ImportCopywriting")
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("导入文案失败,失败信息如下:" + error.message, 'ReverseBook_ImportCopywriting')
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-08-21 11:47:05 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 清除导入的对齐后的文案
|
|
|
|
|
|
* @param bookTaskId 小说批次任务ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
async ClearImportWord(bookTaskId: string): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
let bookTaskDetails = await this.bookServiceBasic.GetBookTaskDetailData({
|
|
|
|
|
|
bookTaskId: bookTaskId
|
|
|
|
|
|
})
|
|
|
|
|
|
if (bookTaskDetails.length <= 0) {
|
|
|
|
|
|
throw new Error("没有找到对应小说批次任务的的分镜数据")
|
|
|
|
|
|
}
|
|
|
|
|
|
let book = await this.bookServiceBasic.GetBookDataById(bookTaskDetails[0].bookId)
|
|
|
|
|
|
let originalTimePath = path.join(book.bookFolderPath, `data/${book.id}.mp4.json`);
|
|
|
|
|
|
let originalTime = [] as any[];
|
|
|
|
|
|
if (await CheckFileOrDirExist(originalTimePath)) {
|
|
|
|
|
|
let originalTimeString = await fs.promises.readFile(originalTimePath, 'utf-8');
|
|
|
|
|
|
if (ValidateJson(originalTimeString)) {
|
|
|
|
|
|
originalTime = JSON.parse(originalTimeString)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-09-12 14:13:09 +08:00
|
|
|
|
// 判断分镜数据和批次数据是不是相同的 好好办办
|
2024-08-21 11:47:05 +08:00
|
|
|
|
if (originalTime.length != bookTaskDetails.length) {
|
|
|
|
|
|
originalTime = []
|
|
|
|
|
|
}
|
2024-08-18 16:22:19 +08:00
|
|
|
|
|
2024-08-21 11:47:05 +08:00
|
|
|
|
// 开始删除,需要做的操作,删除 bookTaskDetail 众的subValue 数据,将时间数据复原
|
|
|
|
|
|
for (let i = 0; i < bookTaskDetails.length; i++) {
|
|
|
|
|
|
const element = bookTaskDetails[i];
|
|
|
|
|
|
let updateObj = {
|
|
|
|
|
|
subValue: undefined
|
|
|
|
|
|
} as Book.SelectBookTaskDetail
|
|
|
|
|
|
|
|
|
|
|
|
// 开始重置时间
|
|
|
|
|
|
if (originalTime[i]) {
|
|
|
|
|
|
let startTime = TimeStringToMilliseconds(originalTime[i][0])
|
|
|
|
|
|
let endTime = TimeStringToMilliseconds(originalTime[i][1])
|
|
|
|
|
|
updateObj.startTime = startTime;
|
|
|
|
|
|
updateObj.endTime = endTime;
|
|
|
|
|
|
updateObj.timeLimit = undefined
|
|
|
|
|
|
}
|
|
|
|
|
|
await this.bookServiceBasic.UpdateBookTaskDetail(element.id, updateObj);
|
|
|
|
|
|
}
|
|
|
|
|
|
let returnBookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({
|
|
|
|
|
|
bookTaskId: bookTaskId
|
|
|
|
|
|
})
|
|
|
|
|
|
// 成功
|
|
|
|
|
|
return successMessage(returnBookTaskDetail, "重置导入文案对齐数据成功", "ReverseBook_ClearImportWord")
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("清除导入的文案失败,失败信息如下:" + error.message, 'ReverseBook_ClearImportWord')
|
|
|
|
|
|
}
|
2024-08-18 16:22:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-12 14:13:09 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 保存文案的对齐信息,这边会做一些判断
|
|
|
|
|
|
* @param bookTaskId 小说任务ID
|
|
|
|
|
|
* @param copywritingData 要保存的文案数据
|
|
|
|
|
|
* @param operateBookType 操作的小说类型
|
|
|
|
|
|
* @returns
|
|
|
|
|
|
*/
|
|
|
|
|
|
async SaveCopywriting(bookTaskId: string, copywritingData: SubtitleModel.SaveCopywritingData[], operateBookType: OperateBookType): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (operateBookType != OperateBookType.BOOKTASK) {
|
|
|
|
|
|
throw new Error('目前只支持对小说任务的文案保存')
|
|
|
|
|
|
}
|
|
|
|
|
|
let bookTask = await this.bookServiceBasic.GetBookTaskDataById(bookTaskId)
|
|
|
|
|
|
let bookTaskDetails = await this.bookServiceBasic.GetBookTaskDetailData({
|
|
|
|
|
|
bookTaskId: bookTaskId
|
|
|
|
|
|
}, true)
|
|
|
|
|
|
|
2024-10-15 19:33:37 +08:00
|
|
|
|
// 获取SD设置
|
|
|
|
|
|
let sdConifg = JSON.parse(await fs.promises.readFile(define.sd_setting, 'utf-8'));
|
|
|
|
|
|
let adetailer = false;
|
|
|
|
|
|
if (sdConifg && sdConifg?.webui?.adetailer) {
|
|
|
|
|
|
adetailer = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-09-12 14:13:09 +08:00
|
|
|
|
if (bookTaskDetails.length == 0) {
|
|
|
|
|
|
// 新增
|
|
|
|
|
|
for (let i = 0; i < copywritingData.length; i++) {
|
|
|
|
|
|
const element = copywritingData[i];
|
|
|
|
|
|
await this.bookServiceBasic.AddBookTaskDetail({
|
|
|
|
|
|
bookTaskId: bookTaskId,
|
|
|
|
|
|
bookId: bookTask.bookId,
|
|
|
|
|
|
startTime: element.start_time,
|
|
|
|
|
|
endTime: element.end_time,
|
|
|
|
|
|
status: BookTaskStatus.WAIT,
|
|
|
|
|
|
word: element.word,
|
|
|
|
|
|
afterGpt: element.after_gpt,
|
|
|
|
|
|
subValue: JSON.stringify(element.subValue),
|
2024-10-15 19:33:37 +08:00
|
|
|
|
timeLimit: element.timeLimit,
|
|
|
|
|
|
// 新增修脸跟随
|
|
|
|
|
|
adetailer: adetailer
|
2024-09-12 14:13:09 +08:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 修改,这边就要判断是不是数量一致了
|
|
|
|
|
|
if (bookTaskDetails.length != copywritingData.length) {
|
|
|
|
|
|
throw new Error("已有文案,再导入的时候,文案函数数量和分镜数据不一致,请检查")
|
|
|
|
|
|
}
|
|
|
|
|
|
// 开始修改。修改使用事务吧
|
|
|
|
|
|
this.bookServiceBasic.transaction((realm) => {
|
|
|
|
|
|
for (let i = 0; i < copywritingData.length; i++) {
|
|
|
|
|
|
const element = copywritingData[i];
|
|
|
|
|
|
let btd = realm.objectForPrimaryKey("BookTaskDetail", bookTaskDetails[i].id);
|
|
|
|
|
|
if (btd == null) {
|
|
|
|
|
|
throw new Error("未找到对应的分镜数据,请检查")
|
|
|
|
|
|
}
|
|
|
|
|
|
// 开始修改
|
|
|
|
|
|
btd.startTime = element.start_time;
|
|
|
|
|
|
btd.endTime = element.end_time;
|
|
|
|
|
|
btd.word = element.word;
|
|
|
|
|
|
btd.afterGpt = element.after_gpt;
|
|
|
|
|
|
btd.subValue = JSON.stringify(element.subValue);
|
|
|
|
|
|
btd.timeLimit = element.timeLimit
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("保存文案数据失败,失败信息如下:" + error.toString(), 'SubtitleService_SaveCopywriting')
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-08-18 16:22:19 +08:00
|
|
|
|
//#endregion
|
2024-09-12 14:13:09 +08:00
|
|
|
|
}
|