import _ from "lodash"; import APIException from "@/lib/exceptions/APIException.ts"; import EX from "@/api/consts/exceptions.ts"; import util from "@/lib/util.ts"; import { getCredit, receiveCredit, request } from "./core.ts"; import logger from "@/lib/logger.ts"; const DEFAULT_ASSISTANT_ID = "513695"; export const DEFAULT_MODEL = "jimeng-v-3.0"; const DRAFT_VERSION = "3.0.5"; const DRAFT_V_VERSION = "1.0.0"; const MODEL_MAP = { "jimeng-v-3.0": "dreamina_ic_generate_video_model_vgfm_3.0", }; export function getModel(model: string) { return MODEL_MAP[model] || MODEL_MAP[DEFAULT_MODEL]; } export async function generateVideo( _model: string, prompt: string, { width = 512, height = 512, imgURL = "", duration = 5000, }: { width: number; height: number; imgURL: string; duration: number; }, refreshToken: string ) { 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_IMAGE_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_IMAGE_GENERATION_FAILED, "记录不存在"); 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_IMAGE_GENERATION_FAILED); } return item_list.map((item) => { if(!item?.video?.transcoded_video?.origin?.video_url) // return item?.common_attr?.cover_url || null; return null; return item.video.transcoded_video.origin.video_url; }); } export default { generateVideo, };