增加即梦的生图和生视频功能
This commit is contained in:
1 parent
a9a4cdf125
commit
542246e4ce
20 files changed
+1008
-53
No files matched your search
@@ -139,12 +139,12 @@ export function materialContentForProvider(materials: PromptMaterial[], origin:
|
||||
return normalizeMaterials(materials).map((material) => {
|
||||
const url = toAbsoluteUrl(material.url, origin);
|
||||
if (material.type === "video") {
|
||||
return { type: "video_url", video_url: { url }, role: "reference_video", label: material.label };
|
||||
return { type: "video_url", video_url: { url }, role: "reference_video" };
|
||||
}
|
||||
if (material.type === "audio") {
|
||||
return { type: "audio_url", audio_url: { url }, role: "reference_audio", label: material.label };
|
||||
return { type: "audio_url", audio_url: { url }, role: "reference_audio" };
|
||||
}
|
||||
return { type: "image_url", image_url: { url }, role: "reference_image", label: material.label };
|
||||
return { type: "image_url", image_url: { url }, role: "reference_image" };
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ export type SeedanceCreateInput = {
|
||||
};
|
||||
|
||||
export type SeedanceQueryResult = {
|
||||
status: "queued" | "running" | "succeeded" | "failed" | "cancelled";
|
||||
status: "queued" | "running" | "succeeded" | "failed" | "cancelled" | "expired";
|
||||
resultUrl?: string;
|
||||
errorMessage?: string;
|
||||
usage?: SeedanceUsage;
|
||||
@@ -49,11 +49,15 @@ export function getSeedanceConfig() {
|
||||
export async function createSeedanceTask(input: SeedanceCreateInput) {
|
||||
const config = getSeedanceConfig();
|
||||
if (!config.apiKey) throw new Error("缺少 SEEDANCE_API_KEY。请在 .env.local 配置火山方舟 API Key。");
|
||||
const materialContent = materialContentForProvider(input.materials, input.origin);
|
||||
if (materialContent.length > 4) {
|
||||
throw new Error("Seedance 2.0 最多支持 4 个素材(加上文本后 content 最多 5 项)。");
|
||||
}
|
||||
const payload = {
|
||||
model: config.model,
|
||||
content: [
|
||||
{ type: "text", text: input.prompt },
|
||||
...materialContentForProvider(input.materials, input.origin)
|
||||
...materialContent
|
||||
],
|
||||
generate_audio: true,
|
||||
ratio: normalizeVideoRatio(input.settings.ratio, config.ratio),
|
||||
@@ -123,7 +127,8 @@ export function extractSeedanceUsage(value: unknown): SeedanceUsage | undefined
|
||||
function normalizeSeedanceStatus(status: unknown): SeedanceQueryResult["status"] {
|
||||
const value = String(status || "").toLowerCase();
|
||||
if (["succeeded", "success", "completed"].includes(value)) return "succeeded";
|
||||
if (["failed", "error", "expired", "timeout"].includes(value)) return "failed";
|
||||
if (["expired", "timeout"].includes(value)) return "expired";
|
||||
if (["failed", "error"].includes(value)) return "failed";
|
||||
if (["cancelled", "canceled"].includes(value)) return "cancelled";
|
||||
if (["running", "processing", "generating"].includes(value)) return "running";
|
||||
return "queued";
|
||||
|
||||
@@ -11,7 +11,7 @@ export const VIDEO_RATIO_DEFAULT = "9:16";
|
||||
export const VIDEO_RATIOS = ["9:16", "16:9", "1:1", "4:3", "3:4", "21:9", "adaptive"] as const;
|
||||
|
||||
export const VIDEO_RESOLUTION_DEFAULT = "720p";
|
||||
export const VIDEO_RESOLUTIONS = ["720p", "1080p", "480p", "4k"] as const;
|
||||
export const VIDEO_RESOLUTIONS = ["720p", "1080p", "480p"] as const;
|
||||
export const VIDEO_FAST_RESOLUTIONS = ["720p", "480p"] as const;
|
||||
|
||||
type VideoDurationOptions = {
|
||||
|
||||
@@ -27,7 +27,8 @@ export async function submitVisualTask(
|
||||
config = getVisualClientConfig()
|
||||
): Promise<VisualTaskSubmitResponse> {
|
||||
if (!config) throw new Error("Volcengine Visual credentials are not configured.");
|
||||
return callVisualApi<VisualTaskSubmitResponse>("CVSync2AsyncSubmitTask", payload, config);
|
||||
const protocol = visualProtocolForPayload(payload);
|
||||
return callVisualApi<VisualTaskSubmitResponse>(protocol.submitAction, protocol.version, payload, config);
|
||||
}
|
||||
|
||||
export async function queryVisualTask(
|
||||
@@ -35,11 +36,38 @@ export async function queryVisualTask(
|
||||
config = getVisualClientConfig()
|
||||
): Promise<VisualTaskQueryResponse> {
|
||||
if (!config) throw new Error("Volcengine Visual credentials are not configured.");
|
||||
return callVisualApi<VisualTaskQueryResponse>("CVSync2AsyncGetResult", payload, config);
|
||||
const protocol = visualProtocolForPayload(payload);
|
||||
return callVisualApi<VisualTaskQueryResponse>(protocol.queryAction, protocol.version, payload, config);
|
||||
}
|
||||
|
||||
type VisualAction =
|
||||
| "CVSync2AsyncSubmitTask"
|
||||
| "CVSync2AsyncGetResult"
|
||||
| "JimengSeedream46CVToBSubmitTask"
|
||||
| "JimengSeedream46CVToBGetResult";
|
||||
|
||||
function visualProtocolForPayload(payload: Record<string, unknown>): {
|
||||
submitAction: VisualAction;
|
||||
queryAction: VisualAction;
|
||||
version: string;
|
||||
} {
|
||||
if (String(payload.req_key || "").trim() === "jimeng_seedream46_cvtob") {
|
||||
return {
|
||||
submitAction: "JimengSeedream46CVToBSubmitTask",
|
||||
queryAction: "JimengSeedream46CVToBGetResult",
|
||||
version: "2024-06-06"
|
||||
};
|
||||
}
|
||||
return {
|
||||
submitAction: "CVSync2AsyncSubmitTask",
|
||||
queryAction: "CVSync2AsyncGetResult",
|
||||
version: "2022-08-31"
|
||||
};
|
||||
}
|
||||
|
||||
async function callVisualApi<T>(
|
||||
action: "CVSync2AsyncSubmitTask" | "CVSync2AsyncGetResult",
|
||||
action: VisualAction,
|
||||
version: string,
|
||||
payload: Record<string, unknown>,
|
||||
config: VisualClientConfig
|
||||
): Promise<T> {
|
||||
@@ -49,7 +77,7 @@ async function callVisualApi<T>(
|
||||
endpoint: config.endpoint,
|
||||
query: {
|
||||
Action: action,
|
||||
Version: "2022-08-31"
|
||||
Version: version
|
||||
},
|
||||
body,
|
||||
accessKeyId: config.accessKeyId,
|
||||
|
||||
Reference in new issue
Block a user