等待逻辑调整 高清接口(未完成)
This commit is contained in:
parent
00c0c14e03
commit
370e1e3b70
@ -11,4 +11,5 @@ export default {
|
||||
API_VIDEO_GENERATION_FAILED: [-2008, '视频生成失败'],
|
||||
API_IMAGE_GENERATION_INSUFFICIENT_POINTS: [-2009, '即梦积分不足'],
|
||||
API_IMAGE_URL: [-2010, '即梦积分不足'],
|
||||
API_HISTORY_EMPTY: [-2011, '生成结果为空'],
|
||||
}
|
||||
@ -18,7 +18,7 @@ const MODEL_MAP = {
|
||||
export function getModel(model: string) {
|
||||
return MODEL_MAP[model] || MODEL_MAP[DEFAULT_MODEL];
|
||||
}
|
||||
|
||||
//图片生成视频 首帧
|
||||
export async function generateVideo(
|
||||
_model: string,
|
||||
task_id: string,
|
||||
@ -168,10 +168,11 @@ export async function generateVideo(
|
||||
);
|
||||
const historyId = aigc_data.history_record_id;
|
||||
if (!historyId)
|
||||
throw new APIException(EX.API_IMAGE_GENERATION_FAILED, "记录ID不存在");
|
||||
throw new APIException(EX.API_VIDEO_GENERATION_FAILED, "记录ID不存在");
|
||||
let status = 20, failCode, item_list = [];
|
||||
//https://jimeng.jianying.com/mweb/v1/get_history_by_ids?
|
||||
//
|
||||
let emptyCount = 30;
|
||||
while (status === 20) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
const result = await request("post", "/mweb/v1/get_history_by_ids", refreshToken, {
|
||||
@ -182,8 +183,16 @@ export async function generateVideo(
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!result[historyId])
|
||||
throw new APIException(EX.API_IMAGE_GENERATION_FAILED, "记录不存在");
|
||||
if (!result[historyId]){
|
||||
logger.warn(`记录ID不存在: ${historyId} 重试次数: ${emptyCount}`);
|
||||
emptyCount--;
|
||||
if(emptyCount<=0){
|
||||
throw new APIException(EX.API_HISTORY_EMPTY, "记录不存在: " + JSON.stringify(result));
|
||||
}else{
|
||||
status = 20;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
status = result[historyId].status;
|
||||
failCode = result[historyId].fail_code;
|
||||
item_list = result[historyId].item_list;
|
||||
@ -192,7 +201,7 @@ export async function generateVideo(
|
||||
if (failCode === '2038')
|
||||
throw new APIException(EX.API_CONTENT_FILTERED);
|
||||
else
|
||||
throw new APIException(EX.API_IMAGE_GENERATION_FAILED);
|
||||
throw new APIException(EX.API_VIDEO_GENERATION_FAILED);
|
||||
}
|
||||
// Assuming success if status is not 30 (failed) and not 20 (pending)
|
||||
// and item_list is populated.
|
||||
@ -211,7 +220,675 @@ export async function generateVideo(
|
||||
// If no valid URLs but no explicit error thrown earlier, consider it a failure.
|
||||
// This could happen if item_list is empty or items don't have video_url.
|
||||
videoTaskCache.finishTask(task_id, -2); // Failure
|
||||
throw new APIException(EX.API_IMAGE_GENERATION_FAILED, "视频生成未返回有效链接");
|
||||
throw new APIException(EX.API_VIDEO_GENERATION_FAILED, "视频生成未返回有效链接");
|
||||
}
|
||||
return validVideoUrls;
|
||||
} catch (error) {
|
||||
videoTaskCache.finishTask(task_id, -2); // Failure due to exception
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
}
|
||||
//视频 提升分辨率
|
||||
export async function upgradeVideoResolution(
|
||||
task_id: string,
|
||||
{
|
||||
targetVideoId = "",
|
||||
targetHistoryId = "",
|
||||
targetSubmitId = "",
|
||||
originHistoryId = "",
|
||||
originComponentList = []
|
||||
}: {
|
||||
targetVideoId: string,
|
||||
targetHistoryId: string,
|
||||
targetSubmitId: string,
|
||||
originHistoryId: string,
|
||||
originComponentList: any[],
|
||||
},
|
||||
refreshToken: string
|
||||
) {
|
||||
const videoTaskCache = VideoTaskCache.getInstance();
|
||||
videoTaskCache.startTask(task_id);
|
||||
|
||||
try {
|
||||
|
||||
const { totalCredit } = await getCredit(refreshToken);
|
||||
if (totalCredit <= 0)
|
||||
await receiveCredit(refreshToken);
|
||||
|
||||
const componentId = util.uuid();
|
||||
const originSubmitId = util.uuid();
|
||||
//生成视频返回的 historyId item_list[0].video.video_id
|
||||
let video_id = targetVideoId;
|
||||
//生成视频返回的 historyId
|
||||
let pre_historyId = targetHistoryId;
|
||||
let origin_historyId = originHistoryId;
|
||||
//生成视频返回的 historyId submit_id
|
||||
let previewSubmitId = targetSubmitId;
|
||||
//生成视频返回的 historyId draft_content.component_list[0]
|
||||
|
||||
let origin_component_list_item:any = originComponentList.find((a)=>{
|
||||
return a.process_type == 1;
|
||||
});
|
||||
originComponentList.sort((a,b)=>{
|
||||
return b.process_type - a.process_type;
|
||||
})
|
||||
let pro_component_list_item:any = originComponentList[0];
|
||||
let origin_video_gen_inputs = origin_component_list_item.abilities.gen_video.text_to_video_params.video_gen_inputs[0];
|
||||
let prompt = origin_video_gen_inputs.prompt;
|
||||
let first_frame_image = origin_video_gen_inputs.first_frame_image;
|
||||
let width = first_frame_image.width;
|
||||
let height = first_frame_image.height;
|
||||
let duration = origin_video_gen_inputs.duration_ms;
|
||||
let metrics_extra = JSON.stringify({
|
||||
promptSource: "upscale",
|
||||
//生成视频返回的 historyId 19680709245698
|
||||
originId:origin_historyId,
|
||||
originSubmitId: originSubmitId,
|
||||
//返回的 task.first_frame_image 信息
|
||||
coverInfo: {
|
||||
width: first_frame_image.width,
|
||||
height: first_frame_image.height,
|
||||
format: "",
|
||||
imageUri: first_frame_image.image_uri,
|
||||
imageUrl:first_frame_image.uri,
|
||||
smartCropLoc: null,
|
||||
coverUrlMap: {},
|
||||
},
|
||||
generateTimes: 0,
|
||||
isDefaultSeed: 1,
|
||||
previewId: pre_historyId,
|
||||
//生成视频用的submit_id
|
||||
previewSubmitId: previewSubmitId,
|
||||
imageNameMapping: {},
|
||||
});
|
||||
const { aigc_data } = await request(
|
||||
"post",
|
||||
"/mweb/v1/aigc_draft/generate",
|
||||
refreshToken,
|
||||
{
|
||||
params: {
|
||||
babi_param: encodeURIComponent(
|
||||
JSON.stringify({
|
||||
scenario: "image_video_generation",
|
||||
feature_key: "text_to_video",
|
||||
feature_entrance: "to_video",
|
||||
feature_entrance_detail: "to_image-text_to_video",
|
||||
})
|
||||
),
|
||||
},
|
||||
data: {
|
||||
extend: {
|
||||
m_video_commerce_info: {
|
||||
resource_id: "generate_video",
|
||||
resource_id_type: "str",
|
||||
resource_sub_type: "aigc",
|
||||
benefit_type: "video_upscale"
|
||||
},
|
||||
root_model: pro_component_list_item.abilities.gen_video.text_to_video_params.model_req_key,
|
||||
template_id: "",
|
||||
history_option: {},
|
||||
},
|
||||
submit_id: util.uuid(),
|
||||
metrics_extra: metrics_extra,
|
||||
draft_content: JSON.stringify({
|
||||
type: "draft",
|
||||
id: util.uuid(),
|
||||
min_version: DRAFT_VERSION,
|
||||
min_features: [],
|
||||
is_from_tsn: true,
|
||||
version: "3.2.2",
|
||||
main_component_id: componentId,
|
||||
//上一步生成视频任务返回的 historyId 中 draft_content的内容作为第一项
|
||||
component_list: [
|
||||
...originComponentList,
|
||||
{
|
||||
type: "video_base_component",
|
||||
id: componentId,
|
||||
min_version: DRAFT_V_VERSION,
|
||||
//上一步生成视频任务返回的 historyId 中 draft_content的内容的id
|
||||
parent_id: pro_component_list_item.id,
|
||||
metadata: {
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
created_platform: 3,
|
||||
created_platform_version: "",
|
||||
created_time_in_ms: Date.now(),
|
||||
created_did: "",
|
||||
},
|
||||
generate_type: "gen_video",
|
||||
aigc_mode: "workbench",
|
||||
abilities: {
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
gen_video:{
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
text_to_video_params:{
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
video_gen_inputs:[
|
||||
{
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
min_version: DRAFT_V_VERSION,
|
||||
prompt: prompt,
|
||||
first_frame_image:{
|
||||
type: "image",
|
||||
id: util.uuid(),
|
||||
source_from: "upload",
|
||||
platform_type: 1,
|
||||
name: "",
|
||||
image_uri: first_frame_image.image_uri,
|
||||
width: first_frame_image.width,
|
||||
height: first_frame_image.height,
|
||||
format: "",
|
||||
uri: first_frame_image.image_uri,
|
||||
},
|
||||
lens_motion_type: "",
|
||||
video_mode:2,
|
||||
//上一步生成视频任务返回的 historyId 中 的video_id
|
||||
vid: video_id,
|
||||
fps:24,
|
||||
duration_ms:duration,
|
||||
v2v_opt: {
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
min_version: "3.1.0",
|
||||
super_resolution: {
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
enable: true,
|
||||
target_width: width*2,
|
||||
target_height: height*2,
|
||||
origin_width: width,
|
||||
origin_height: height,
|
||||
},
|
||||
},
|
||||
//上一步生成视频任务返回的 historyId
|
||||
origin_history_id: pre_historyId,
|
||||
}
|
||||
],
|
||||
video_aspect_ratio:pro_component_list_item.abilities.gen_video.text_to_video_params.video_aspect_ratio,
|
||||
model_req_key: pro_component_list_item.abilities.gen_video.text_to_video_params.model_req_key,
|
||||
},
|
||||
scene: "super_resolution",
|
||||
//上面生成的 metrics_extra
|
||||
video_task_extra:metrics_extra,
|
||||
video_ref_params: {
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
generate_type: 0,
|
||||
item_id: (7512653500000000000 + Date.now()),
|
||||
origin_history_id: pre_historyId,
|
||||
},
|
||||
},
|
||||
},
|
||||
process_type:pro_component_list_item.process_type+1,
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
}
|
||||
);
|
||||
const historyId = aigc_data.history_record_id;
|
||||
if (!historyId)
|
||||
throw new APIException(EX.API_VIDEO_GENERATION_FAILED, "高清 记录ID不存在");
|
||||
let status = 20, failCode, item_list = [];
|
||||
//https://jimeng.jianying.com/mweb/v1/get_history_by_ids?
|
||||
//
|
||||
let emptyCount = 30;
|
||||
while (status === 20) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
const result = await request("post", "/mweb/v1/get_history_by_ids", refreshToken, {
|
||||
data: {
|
||||
history_ids: [historyId],
|
||||
http_common_info: {
|
||||
aid: Number(DEFAULT_ASSISTANT_ID),
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!result[historyId]){
|
||||
logger.warn(`高清 记录ID不存在: ${historyId} 重试次数: ${emptyCount}`);
|
||||
emptyCount--;
|
||||
if(emptyCount<=0){
|
||||
throw new APIException(EX.API_HISTORY_EMPTY, "高清 记录不存在: " + JSON.stringify(result));
|
||||
}else{
|
||||
status = 20;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
status = result[historyId].status;
|
||||
failCode = result[historyId].fail_code;
|
||||
item_list = result[historyId].item_list;
|
||||
}
|
||||
if (status === 30) {
|
||||
if (failCode === '2038')
|
||||
throw new APIException(EX.API_CONTENT_FILTERED);
|
||||
else
|
||||
throw new APIException(EX.API_VIDEO_GENERATION_FAILED);
|
||||
}
|
||||
// Assuming success if status is not 30 (failed) and not 20 (pending)
|
||||
// and item_list is populated.
|
||||
// A more robust check might be needed depending on actual API behavior for success.
|
||||
const videoUrls = item_list.map((item) => {
|
||||
if(!item?.video?.transcoded_video?.origin?.video_url)
|
||||
return null;
|
||||
return item.video.transcoded_video.origin.video_url;
|
||||
});
|
||||
|
||||
// Filter out nulls and check if any valid URL was generated
|
||||
const validVideoUrls = videoUrls.filter(url => url !== null);
|
||||
if (validVideoUrls.length > 0) {
|
||||
videoTaskCache.finishTask(task_id, -1, validVideoUrls.join(",")); // Success
|
||||
} else {
|
||||
// If no valid URLs but no explicit error thrown earlier, consider it a failure.
|
||||
// This could happen if item_list is empty or items don't have video_url.
|
||||
videoTaskCache.finishTask(task_id, -2); // Failure
|
||||
throw new APIException(EX.API_VIDEO_GENERATION_FAILED, "高清 视频生成未返回有效链接");
|
||||
}
|
||||
return validVideoUrls;
|
||||
} catch (error) {
|
||||
videoTaskCache.finishTask(task_id, -2); // Failure due to exception
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
}
|
||||
|
||||
//视频 补帧 (未完成)
|
||||
export async function upgradeVideoFrame(
|
||||
_model: string,
|
||||
task_id: string,
|
||||
prompt: string,
|
||||
{
|
||||
width = 512,
|
||||
height = 512,
|
||||
imgURL = "",
|
||||
duration = 5000,
|
||||
}: {
|
||||
width: number;
|
||||
height: number;
|
||||
imgURL: string;
|
||||
duration: number;
|
||||
},
|
||||
refreshToken: string
|
||||
) {
|
||||
const videoTaskCache = VideoTaskCache.getInstance();
|
||||
videoTaskCache.startTask(task_id);
|
||||
|
||||
try {
|
||||
if(!imgURL){
|
||||
throw new APIException(EX.API_REQUEST_PARAMS_INVALID);
|
||||
return;
|
||||
}
|
||||
const model = getModel(_model);
|
||||
logger.info(`使用模型: ${_model} : ${model} 参考图片尺寸: ${width}x${height} 图片地址 ${imgURL} 持续时间: ${duration} 提示词: ${prompt}`);
|
||||
|
||||
const { totalCredit } = await getCredit(refreshToken);
|
||||
if (totalCredit <= 0)
|
||||
await receiveCredit(refreshToken);
|
||||
|
||||
const componentId = util.uuid();
|
||||
const originSubmitId = util.uuid();
|
||||
const { aigc_data } = await request(
|
||||
"post",
|
||||
"/mweb/v1/aigc_draft/generate",
|
||||
refreshToken,
|
||||
{
|
||||
params: {
|
||||
babi_param: encodeURIComponent(
|
||||
JSON.stringify({
|
||||
scenario: "image_video_generation",
|
||||
feature_key: "text_to_video",
|
||||
feature_entrance: "to_video",
|
||||
feature_entrance_detail: "to_image-text_to_video",
|
||||
})
|
||||
),
|
||||
},
|
||||
data: {
|
||||
extend: {
|
||||
m_video_commerce_info: {
|
||||
resource_id: "generate_video",
|
||||
resource_id_type: "str",
|
||||
resource_sub_type: "aigc",
|
||||
benefit_type: "basic_video_operation_vgfm_v_three"
|
||||
},
|
||||
root_model: model,
|
||||
template_id: "",
|
||||
history_option: {},
|
||||
},
|
||||
submit_id: util.uuid(),
|
||||
metrics_extra: JSON.stringify({
|
||||
promptSource: "custom",
|
||||
originSubmitId: originSubmitId,
|
||||
isDefaultSeed: 1,
|
||||
originTemplateId: "",
|
||||
imageNameMapping: {},
|
||||
}),
|
||||
draft_content: JSON.stringify({
|
||||
type: "draft",
|
||||
id: util.uuid(),
|
||||
min_version: DRAFT_VERSION,
|
||||
min_features: [],
|
||||
is_from_tsn: true,
|
||||
version: "3.2.2",
|
||||
main_component_id: componentId,
|
||||
component_list: [
|
||||
{
|
||||
type: "video_base_component",
|
||||
id: componentId,
|
||||
min_version: DRAFT_V_VERSION,
|
||||
generate_type: "gen_video",
|
||||
aigc_mode: "workbench",
|
||||
metadata: {
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
created_platform: 3,
|
||||
created_platform_version: "",
|
||||
created_time_in_ms: Date.now(),
|
||||
created_did: "",
|
||||
},
|
||||
abilities: {
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
gen_video:{
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
text_to_video_params:{
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
video_gen_inputs:[
|
||||
{
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
min_version: DRAFT_V_VERSION,
|
||||
prompt: prompt,
|
||||
first_frame_image:{
|
||||
type: "image",
|
||||
id: util.uuid(),
|
||||
source_from: "upload",
|
||||
platform_type: 1,
|
||||
name: "",
|
||||
image_uri: imgURL,
|
||||
width: width,
|
||||
height: height,
|
||||
format: "",
|
||||
uri: imgURL,
|
||||
},
|
||||
video_mode:2,
|
||||
fps:24,
|
||||
duration_ms:duration,
|
||||
}
|
||||
],
|
||||
video_aspect_ratio:"9:16",
|
||||
seed: Math.floor(Math.random() * 100000000) + 2500000000,
|
||||
model_req_key: model,
|
||||
},
|
||||
video_task_extra:{
|
||||
promptSource: "custom",
|
||||
originSubmitId: originSubmitId,
|
||||
isDefaultSeed: 1,
|
||||
originTemplateId: "",
|
||||
imageNameMapping: {},
|
||||
}
|
||||
},
|
||||
},
|
||||
process_type:1,
|
||||
},
|
||||
],
|
||||
}),
|
||||
http_common_info: {
|
||||
aid: Number(DEFAULT_ASSISTANT_ID),
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
const historyId = aigc_data.history_record_id;
|
||||
if (!historyId)
|
||||
throw new APIException(EX.API_VIDEO_GENERATION_FAILED, "记录ID不存在");
|
||||
let status = 20, failCode, item_list = [];
|
||||
//https://jimeng.jianying.com/mweb/v1/get_history_by_ids?
|
||||
//
|
||||
while (status === 20) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
const result = await request("post", "/mweb/v1/get_history_by_ids", refreshToken, {
|
||||
data: {
|
||||
history_ids: [historyId],
|
||||
http_common_info: {
|
||||
aid: Number(DEFAULT_ASSISTANT_ID),
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!result[historyId])
|
||||
throw new APIException(EX.API_HISTORY_EMPTY, "记录不存在");
|
||||
status = result[historyId].status;
|
||||
failCode = result[historyId].fail_code;
|
||||
item_list = result[historyId].item_list;
|
||||
}
|
||||
if (status === 30) {
|
||||
if (failCode === '2038')
|
||||
throw new APIException(EX.API_CONTENT_FILTERED);
|
||||
else
|
||||
throw new APIException(EX.API_VIDEO_GENERATION_FAILED);
|
||||
}
|
||||
// Assuming success if status is not 30 (failed) and not 20 (pending)
|
||||
// and item_list is populated.
|
||||
// A more robust check might be needed depending on actual API behavior for success.
|
||||
const videoUrls = item_list.map((item) => {
|
||||
if(!item?.video?.transcoded_video?.origin?.video_url)
|
||||
return null;
|
||||
return item.video.transcoded_video.origin.video_url;
|
||||
});
|
||||
|
||||
// Filter out nulls and check if any valid URL was generated
|
||||
const validVideoUrls = videoUrls.filter(url => url !== null);
|
||||
if (validVideoUrls.length > 0) {
|
||||
videoTaskCache.finishTask(task_id, -1, validVideoUrls.join(",")); // Success
|
||||
} else {
|
||||
// If no valid URLs but no explicit error thrown earlier, consider it a failure.
|
||||
// This could happen if item_list is empty or items don't have video_url.
|
||||
videoTaskCache.finishTask(task_id, -2); // Failure
|
||||
throw new APIException(EX.API_VIDEO_GENERATION_FAILED, "视频生成未返回有效链接");
|
||||
}
|
||||
return validVideoUrls;
|
||||
} catch (error) {
|
||||
videoTaskCache.finishTask(task_id, -2); // Failure due to exception
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
}
|
||||
|
||||
//视频 生成音效 (未完成)
|
||||
export async function generateVideoSound(
|
||||
_model: string,
|
||||
task_id: string,
|
||||
prompt: string,
|
||||
{
|
||||
width = 512,
|
||||
height = 512,
|
||||
imgURL = "",
|
||||
duration = 5000,
|
||||
}: {
|
||||
width: number;
|
||||
height: number;
|
||||
imgURL: string;
|
||||
duration: number;
|
||||
},
|
||||
refreshToken: string
|
||||
) {
|
||||
const videoTaskCache = VideoTaskCache.getInstance();
|
||||
videoTaskCache.startTask(task_id);
|
||||
|
||||
try {
|
||||
if(!imgURL){
|
||||
throw new APIException(EX.API_REQUEST_PARAMS_INVALID);
|
||||
return;
|
||||
}
|
||||
const model = getModel(_model);
|
||||
logger.info(`使用模型: ${_model} : ${model} 参考图片尺寸: ${width}x${height} 图片地址 ${imgURL} 持续时间: ${duration} 提示词: ${prompt}`);
|
||||
|
||||
const { totalCredit } = await getCredit(refreshToken);
|
||||
if (totalCredit <= 0)
|
||||
await receiveCredit(refreshToken);
|
||||
|
||||
const componentId = util.uuid();
|
||||
const originSubmitId = util.uuid();
|
||||
const { aigc_data } = await request(
|
||||
"post",
|
||||
"/mweb/v1/aigc_draft/generate",
|
||||
refreshToken,
|
||||
{
|
||||
params: {
|
||||
babi_param: encodeURIComponent(
|
||||
JSON.stringify({
|
||||
scenario: "image_video_generation",
|
||||
feature_key: "text_to_video",
|
||||
feature_entrance: "to_video",
|
||||
feature_entrance_detail: "to_image-text_to_video",
|
||||
})
|
||||
),
|
||||
},
|
||||
data: {
|
||||
extend: {
|
||||
m_video_commerce_info: {
|
||||
resource_id: "generate_video",
|
||||
resource_id_type: "str",
|
||||
resource_sub_type: "aigc",
|
||||
benefit_type: "basic_video_operation_vgfm_v_three"
|
||||
},
|
||||
root_model: model,
|
||||
template_id: "",
|
||||
history_option: {},
|
||||
},
|
||||
submit_id: util.uuid(),
|
||||
metrics_extra: JSON.stringify({
|
||||
promptSource: "custom",
|
||||
originSubmitId: originSubmitId,
|
||||
isDefaultSeed: 1,
|
||||
originTemplateId: "",
|
||||
imageNameMapping: {},
|
||||
}),
|
||||
draft_content: JSON.stringify({
|
||||
type: "draft",
|
||||
id: util.uuid(),
|
||||
min_version: DRAFT_VERSION,
|
||||
min_features: [],
|
||||
is_from_tsn: true,
|
||||
version: "3.2.2",
|
||||
main_component_id: componentId,
|
||||
component_list: [
|
||||
{
|
||||
type: "video_base_component",
|
||||
id: componentId,
|
||||
min_version: DRAFT_V_VERSION,
|
||||
generate_type: "gen_video",
|
||||
aigc_mode: "workbench",
|
||||
metadata: {
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
created_platform: 3,
|
||||
created_platform_version: "",
|
||||
created_time_in_ms: Date.now(),
|
||||
created_did: "",
|
||||
},
|
||||
abilities: {
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
gen_video:{
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
text_to_video_params:{
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
video_gen_inputs:[
|
||||
{
|
||||
type: "",
|
||||
id: util.uuid(),
|
||||
min_version: DRAFT_V_VERSION,
|
||||
prompt: prompt,
|
||||
first_frame_image:{
|
||||
type: "image",
|
||||
id: util.uuid(),
|
||||
source_from: "upload",
|
||||
platform_type: 1,
|
||||
name: "",
|
||||
image_uri: imgURL,
|
||||
width: width,
|
||||
height: height,
|
||||
format: "",
|
||||
uri: imgURL,
|
||||
},
|
||||
video_mode:2,
|
||||
fps:24,
|
||||
duration_ms:duration,
|
||||
}
|
||||
],
|
||||
video_aspect_ratio:"9:16",
|
||||
seed: Math.floor(Math.random() * 100000000) + 2500000000,
|
||||
model_req_key: model,
|
||||
},
|
||||
video_task_extra:{
|
||||
promptSource: "custom",
|
||||
originSubmitId: originSubmitId,
|
||||
isDefaultSeed: 1,
|
||||
originTemplateId: "",
|
||||
imageNameMapping: {},
|
||||
}
|
||||
},
|
||||
},
|
||||
process_type:1,
|
||||
},
|
||||
],
|
||||
}),
|
||||
http_common_info: {
|
||||
aid: Number(DEFAULT_ASSISTANT_ID),
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
const historyId = aigc_data.history_record_id;
|
||||
if (!historyId)
|
||||
throw new APIException(EX.API_VIDEO_GENERATION_FAILED, "记录ID不存在");
|
||||
let status = 20, failCode, item_list = [];
|
||||
//https://jimeng.jianying.com/mweb/v1/get_history_by_ids?
|
||||
//
|
||||
while (status === 20) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
const result = await request("post", "/mweb/v1/get_history_by_ids", refreshToken, {
|
||||
data: {
|
||||
history_ids: [historyId],
|
||||
http_common_info: {
|
||||
aid: Number(DEFAULT_ASSISTANT_ID),
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!result[historyId])
|
||||
throw new APIException(EX.API_HISTORY_EMPTY, "记录不存在");
|
||||
status = result[historyId].status;
|
||||
failCode = result[historyId].fail_code;
|
||||
item_list = result[historyId].item_list;
|
||||
}
|
||||
if (status === 30) {
|
||||
if (failCode === '2038')
|
||||
throw new APIException(EX.API_CONTENT_FILTERED);
|
||||
else
|
||||
throw new APIException(EX.API_VIDEO_GENERATION_FAILED);
|
||||
}
|
||||
// Assuming success if status is not 30 (failed) and not 20 (pending)
|
||||
// and item_list is populated.
|
||||
// A more robust check might be needed depending on actual API behavior for success.
|
||||
const videoUrls = item_list.map((item) => {
|
||||
if(!item?.video?.transcoded_video?.origin?.video_url)
|
||||
return null;
|
||||
return item.video.transcoded_video.origin.video_url;
|
||||
});
|
||||
|
||||
// Filter out nulls and check if any valid URL was generated
|
||||
const validVideoUrls = videoUrls.filter(url => url !== null);
|
||||
if (validVideoUrls.length > 0) {
|
||||
videoTaskCache.finishTask(task_id, -1, validVideoUrls.join(",")); // Success
|
||||
} else {
|
||||
// If no valid URLs but no explicit error thrown earlier, consider it a failure.
|
||||
// This could happen if item_list is empty or items don't have video_url.
|
||||
videoTaskCache.finishTask(task_id, -2); // Failure
|
||||
throw new APIException(EX.API_VIDEO_GENERATION_FAILED, "视频生成未返回有效链接");
|
||||
}
|
||||
return validVideoUrls;
|
||||
} catch (error) {
|
||||
@ -222,4 +899,7 @@ export async function generateVideo(
|
||||
|
||||
export default {
|
||||
generateVideo,
|
||||
upgradeVideoResolution,
|
||||
// upgradeVideoFrame,
|
||||
// generateVideoSound,
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import _ from "lodash";
|
||||
|
||||
import Request from "@/lib/request/Request.ts";
|
||||
import { generateVideo } from "@/api/controllers/video.ts";
|
||||
import { generateVideo, upgradeVideoResolution } from "@/api/controllers/video.ts";
|
||||
import { tokenSplit } from "@/api/controllers/core.ts";
|
||||
import util from "@/lib/util.ts";
|
||||
import { VideoTaskCache } from '@/api/VideoTaskCache.ts';
|
||||
@ -73,5 +73,44 @@ export default {
|
||||
data:'success',
|
||||
};
|
||||
},
|
||||
"/upscale": async (request: Request) => {
|
||||
request
|
||||
.validate("body.task_id", _.isString)
|
||||
.validate("body.targetVideoId", _.isString)
|
||||
.validate("body.targetHistoryId", _.isString)
|
||||
.validate("body.targetSubmitId", _.isString)
|
||||
.validate("body.originHistoryId", _.isString)
|
||||
.validate("body.components", _.isString)
|
||||
.validate("headers.authorization", _.isString);
|
||||
// refresh_token切分 必须和generations使用同一个token
|
||||
const tokens = tokenSplit(request.headers.authorization);
|
||||
// 取第一个 必须和generations使用同一个token
|
||||
const token = tokens[0];
|
||||
const {
|
||||
task_id,
|
||||
targetVideoId,
|
||||
targetHistoryId,
|
||||
targetSubmitId,
|
||||
originHistoryId,
|
||||
components,
|
||||
} = request.body;
|
||||
const originComponentList = JSON.parse(components);
|
||||
//不等结果 直接返回
|
||||
upgradeVideoResolution(task_id, {
|
||||
targetVideoId,
|
||||
targetHistoryId,
|
||||
targetSubmitId,
|
||||
originHistoryId,
|
||||
originComponentList
|
||||
}, token);
|
||||
// let data = [];
|
||||
// data = imageUrls.map((url) => ({
|
||||
// url,
|
||||
// }));
|
||||
return {
|
||||
created: util.unixTimestamp(),
|
||||
data:'success',
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user