LaiTool/src/main/Service/Subtitle/subtitleService.ts

227 lines
9.3 KiB
TypeScript
Raw Normal View History

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";
import { LoggerStatus, ResponseMessageType } from "../../../define/enum/softwareEnum";
import { TaskScheduler } from "../taskScheduler";
import { OperationType } from "realm/dist/public-types/internal";
import { OperateBookType } from "../../../define/enum/bookEnum";
import { Book } from "../../../model/book";
export class SubtitleService {
softWareServiceBasic: SoftWareServiceBasic
bookServiceBasic: BookServiceBasic
subtitle: Subtitle
taskScheduler: TaskScheduler
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 语音转文案或者是字幕识别
/**
*
*/
async GetCopywriting(bookId: string, bookTaskId: string, operateBookType: OperateBookType): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
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("未知的操作类型")
}
if (bookTaskDetails.length <= 0) {
throw new Error("分镜信息不存在");
}
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("未知的识别字幕模式")
}
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')
}
}
/**
*
* @param bookTaskId ID
* @returns
*/
async ExportCopywriting(bookTaskId: string): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
try {
let bookTask = await this.bookServiceBasic.GetBookTaskDataId(bookTaskId)
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')
}
}
//#endregion
}