230 lines
8.9 KiB
TypeScript
Raw Normal View History

import { TaskModal } from "@/model/task";
import { BookServiceBasic } from "../ServiceBasic/bookServiceBasic";
import { ValidateJson } from "@/define/Tools/validate";
import { BookTaskDetail } from "@/model/book/bookTaskDetail";
import { GetImageBase64 } from "@/define/Tools/image";
import { GetBaseUrl } from "@/define/Tools/common";
import axios from "axios";
import { cloneDeep, isEmpty } from "lodash";
import { VideoStatus } from "@/define/enum/video";
import { SendMessageToRenderer } from "../globalService";
import { ResponseMessageType } from "@/define/enum/softwareEnum";
import { Book } from "@/model/book/book";
import { BookBackTaskStatus, BookTaskStatus } from "@/define/enum/bookEnum";
export class LumaService {
bookServiceBasic: BookServiceBasic
constructor() {
this.bookServiceBasic = new BookServiceBasic();
}
async LumaImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string): Promise<void> {
try {
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(task.bookTaskDetailId);
let lumaOptionsString = bookTaskDetail.videoMessage.lumaOptions;
if (!ValidateJson(lumaOptionsString)) {
throw new Error("lumaOptions参数错误请检查");
}
let lumaOptions: BookTaskDetail.lumaOptions = JSON.parse(lumaOptionsString);
// console.log("lumaOptions", lumaOptions, "gptUrl", gptUrl, "gptApiKey", gptApiKey);
let data: BookTaskDetail.lumaOptions = {
user_prompt: lumaOptions.user_prompt,
aspect_ratio: lumaOptions.aspect_ratio,
loop: lumaOptions.loop,
}
// 是不是需要拓展提示词
if (lumaOptions.hasOwnProperty("expand_prompt")) {
data.expand_prompt = lumaOptions.expand_prompt;
}
// 图片地址(可以不传)
if (lumaOptions.hasOwnProperty("image_url")) {
if (!lumaOptions.image_url.startsWith("http")) {
let imageBase = await GetImageBase64(lumaOptions.image_url);
data.image_url = imageBase;
} else {
data.image_url = lumaOptions.image_url;
}
}
// 尾帧图片地址(可以不传)
if (lumaOptions.hasOwnProperty("image_end_url") && !isEmpty(lumaOptions.image_end_url)) {
if (!lumaOptions.image_end_url.startsWith("http")) {
let imageBase = await GetImageBase64(lumaOptions.image_end_url);
data.image_end_url = imageBase;
} else {
data.image_end_url = lumaOptions.image_end_url;
}
}
// 开始请求
let baseUrl = GetBaseUrl(gptUrl);
let url = baseUrl + "/luma/generations";
let res = await axios.post(url, data, {
headers: {
"Authorization": gptApiKey
}
});
// console.log("luma合成视频结果", res);
let returnData = res.data;
// console.log("luma合成视频结果", returnData);
let id = returnData.id;
// 修改数据
let videoMessage = cloneDeep(bookTaskDetail.videoMessage);
videoMessage.taskId = id;
videoMessage.status = VideoStatus.PROCESSING;
videoMessage.messageData = JSON.stringify(returnData);
delete videoMessage.id;
await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(task.bookTaskDetailId, videoMessage);
// 返回前端数据
SendMessageToRenderer({
code: 1,
id: task.bookTaskDetailId,
message: "runway合成任务提交成功正在合成中",
type: ResponseMessageType.LUMA_VIDEO,
data: JSON.stringify(returnData)
}, task.messageName);
await this.FetchLumaVideoResult(bookTaskDetail, task, id, baseUrl, gptApiKey);
} catch (error) {
throw new Error("Luma合成视频失败错误信息如下" + error.toString());
}
}
/**
*
* @param taskId ID
* @param baseUrl baseUrl
* @param gptApiKey Key
* @returns
*/
async GetVideoUri(taskId: string, baseUrl: string, gptApiKey: string): Promise<string> {
let url = baseUrl + "/luma/generations/" + taskId + "/download_video_url";
let res = await axios.get(url, {
headers: {
Authorization: gptApiKey
}
});
let resData = res.data;
// console.log("luma获取视频地址", resData);
return resData.url;
}
/**
*
* @param bookTaskDetail
* @param task
* @param taskId ID
* @param baseUrl
* @param gptApiKey APIKey
*/
async FetchLumaVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string) {
while (true) {
try {
let url = baseUrl + "/luma/generations/" + taskId;
let res = await axios.get(url, {
headers: {
Authorization: gptApiKey
}
});
// console.log("luma合成视频结果", res.data);
let resData = res.data;
if (resData.state == "completed") {
let video_url = resData.video.download_url;
if (isEmpty(video_url)) {
// 完成
let vr = await this.GetVideoUri(taskId, baseUrl, gptApiKey);
// console.log("luma合成视频结果", vr);
video_url = vr;
}
// 保存数据
let videoMessage = cloneDeep(bookTaskDetail.videoMessage);
delete videoMessage.id;
videoMessage.status = VideoStatus.SUCCESS;
videoMessage.taskId = taskId;
videoMessage.videoUrl = video_url;
videoMessage.messageData = JSON.stringify(resData);
await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(task.bookTaskDetailId, videoMessage);
await this.bookServiceBasic.UpdetedBookTaskData(task.bookTaskId, {
status: BookTaskStatus.IMAGE_TO_VIDEO_SUCCESS,
})
await this.bookServiceBasic.UpdateTaskStatus({
id: task.id,
status: BookBackTaskStatus.DONE,
})
SendMessageToRenderer({
code: 1,
id: bookTaskDetail.id,
message: "Luma合成视频完成",
type: ResponseMessageType.LUMA_VIDEO,
data: JSON.stringify(resData)
}, task.messageName);
break;
} else {
if (resData.state == "pending") {
// 任务再等待
let videoMessage = cloneDeep(bookTaskDetail.videoMessage);
delete videoMessage.id;
videoMessage.status = VideoStatus.WAIT;
videoMessage.taskId = taskId;
videoMessage.messageData = JSON.stringify(resData);
await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(task.bookTaskDetailId, videoMessage);
SendMessageToRenderer({
code: 1,
id: bookTaskDetail.id,
message: "Luma合成视频等待中",
type: ResponseMessageType.LUMA_VIDEO,
data: JSON.stringify(resData)
}, task.messageName);
} else if (resData.state == "processing") {
// 任务进行中
let videoMessage = cloneDeep(bookTaskDetail.videoMessage);
delete videoMessage.id;
videoMessage.status = VideoStatus.PROCESSING;
videoMessage.taskId = taskId;
videoMessage.messageData = JSON.stringify(resData);
await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(task.bookTaskDetailId, videoMessage);
SendMessageToRenderer({
code: 1,
id: bookTaskDetail.id,
message: "Luma合成视频进行中",
type: ResponseMessageType.LUMA_VIDEO,
data: JSON.stringify(resData)
}, task.messageName);
} else {
// 任务失败
let videoMessage = cloneDeep(bookTaskDetail.videoMessage);
delete videoMessage.id;
videoMessage.status = VideoStatus.FAIL;
videoMessage.taskId = taskId;
videoMessage.messageData = JSON.stringify(resData);
await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(task.bookTaskDetailId, videoMessage);
await this.bookServiceBasic.UpdetedBookTaskData(task.bookTaskId, {
status: BookTaskStatus.IMAGE_TO_VIDEO_ERROR,
})
await this.bookServiceBasic.UpdateTaskStatus({
id: task.id,
status: BookBackTaskStatus.FAIL,
})
SendMessageToRenderer({
code: 1,
id: bookTaskDetail.id,
message: "Luma合成视频失败",
type: ResponseMessageType.LUMA_VIDEO,
data: JSON.stringify(resData)
}, task.messageName);
throw new Error("Luma合成视频失败失败信息请查看API后台");
}
}
// 等待20秒后再次请求
await new Promise(resolve => setTimeout(resolve, 15000));
} catch (error) {
throw error;
}
}
}
}