fix(fal-video): sanitize credentials and urls for kling requests
This commit is contained in:
parent
5694fefca0
commit
825da7fd52
@ -22,14 +22,34 @@ const DEFAULT_RATIO = "16:9";
|
||||
const DEFAULT_SHOT_TYPE = "customize";
|
||||
const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
|
||||
|
||||
function normalizeFalTextInput(value: string) {
|
||||
return String(value || "")
|
||||
.replace(/\u00a0/g, " ")
|
||||
.trim()
|
||||
.normalize("NFKC");
|
||||
}
|
||||
|
||||
function normalizeFalCredentials(apiKey: string) {
|
||||
const normalized = apiKey.replace(/\u00a0/g, " ").trim();
|
||||
const normalized = normalizeFalTextInput(apiKey);
|
||||
const stripped = normalized.replace(/^bearer\s+/i, "").replace(/^key\s+/i, "");
|
||||
const kvMatch = stripped.match(/^(?:fal[_-]?key|api[_-]?key|token)\s*[::]\s*(.+)$/i);
|
||||
if (kvMatch?.[1]) {
|
||||
return kvMatch[1].trim();
|
||||
return kvMatch[1].trim().replace(/[^\x20-\x7E]/g, "");
|
||||
}
|
||||
return stripped.replace(/[^\x20-\x7E]/g, "");
|
||||
}
|
||||
|
||||
function normalizeFalModelId(modelId: string) {
|
||||
return normalizeFalTextInput(modelId);
|
||||
}
|
||||
|
||||
function normalizeFalImageUrl(url: string) {
|
||||
const normalized = normalizeFalTextInput(url);
|
||||
try {
|
||||
return new URL(normalized).toString();
|
||||
} catch {
|
||||
return normalized;
|
||||
}
|
||||
return stripped;
|
||||
}
|
||||
|
||||
function normalizeDuration(value?: number) {
|
||||
@ -60,7 +80,7 @@ function extractPromptAndImages(messages: Array<{ role: string; content: any }>)
|
||||
|
||||
const pushImageUrl = (url?: string) => {
|
||||
if (!url) return;
|
||||
const normalized = String(url).trim();
|
||||
const normalized = normalizeFalImageUrl(String(url));
|
||||
|
||||
if (normalized.startsWith("data:")) {
|
||||
throw new Error("FAL 视频模型不支持 Base64 图片,请先上传图片后再生成视频");
|
||||
@ -212,7 +232,7 @@ export function createFalVideo({ apiKey, baseURL }: FalVideoConfig) {
|
||||
overrideModelId?: string;
|
||||
}) => {
|
||||
try {
|
||||
const activeModelId = options.overrideModelId || modelId;
|
||||
const activeModelId = normalizeFalModelId(options.overrideModelId || modelId);
|
||||
const { prompt, imageUrls } = extractPromptAndImages(options.messages);
|
||||
const input = buildFalInput({
|
||||
prompt,
|
||||
@ -229,8 +249,12 @@ export function createFalVideo({ apiKey, baseURL }: FalVideoConfig) {
|
||||
});
|
||||
|
||||
const fal = await import("@fal-ai/serverless-client");
|
||||
const credentials = normalizeFalCredentials(apiKey);
|
||||
if (!credentials) {
|
||||
throw new Error("FAL API Key 未配置或格式无效");
|
||||
}
|
||||
fal.config({
|
||||
credentials: normalizeFalCredentials(apiKey),
|
||||
credentials,
|
||||
});
|
||||
|
||||
const result: any = await fal.subscribe(activeModelId, {
|
||||
@ -266,8 +290,12 @@ export function createFalVideo({ apiKey, baseURL }: FalVideoConfig) {
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("[Fal Video] Generation failed", error);
|
||||
const errorText =
|
||||
error instanceof Error ? `视频生成失败: ${error.message}` : "视频生成失败,请稍后重试";
|
||||
const rawErrorText = error instanceof Error ? error.message : "";
|
||||
const errorText = /ByteString/i.test(rawErrorText)
|
||||
? "视频生成失败: 检测到配置中包含非法字符(常见为中文冒号),请检查 FAL API Key 与模型ID"
|
||||
: error instanceof Error
|
||||
? `视频生成失败: ${error.message}`
|
||||
: "视频生成失败,请稍后重试";
|
||||
return {
|
||||
text: errorText,
|
||||
finishReason: "error" as const,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user