feat: expand video library into general asset library

This commit is contained in:
xuejianwu
2026-08-05 17:04:06 +08:00
parent ce5ae57abc
commit a054fc3b2c
6 changed files with 157 additions and 109 deletions

View File

@@ -131,6 +131,7 @@ async function handleApi(request, response, url) {
if (request.method === "POST" && ["/api/assets/review", "/api/assets/upload"].includes(url.pathname)) {
const body = await readJson(request);
const assetType = String(body.type || "image").toLowerCase();
const genericUpload = url.pathname === "/api/assets/upload" && body.category === "generic";
if (!["image", "video"].includes(assetType)) throw new ClientError("当前仅支持图片或视频素材");
const assetInputs = (assetType === "video"
? [{ url: body.url, view: "video" }]
@@ -138,10 +139,10 @@ async function handleApi(request, response, url) {
? body.images.map((item) => typeof item === "string" ? { url: item } : item)
: [{ url: body.url }])
.filter((item) => String(item?.url || "").trim());
if (assetType === "image" && (assetInputs.length < 1 || assetInputs.length > 3)) {
if (!genericUpload && assetType === "image" && (assetInputs.length < 1 || assetInputs.length > 3)) {
throw new ClientError("人物素材图片数量必须为 13 张");
}
if (assetType === "video" && assetInputs.length !== 1) throw new ClientError("请填写一条视频素材 URL");
if ((genericUpload || assetType === "video") && assetInputs.length !== 1) throw new ClientError("请填写一条素材 URL");
for (const item of assetInputs) validatePublicAssetUrl(item.url, assetType);
if (mockMode) {
@@ -150,11 +151,14 @@ async function handleApi(request, response, url) {
const items = assetInputs.map((input, index) => {
const id = `mat_demo_${Date.now()}_${index + 1}`;
const viewLabel = assetType === "video" ? (body.purpose || "视频素材") : labels[input.view] || `参考图${index + 1}`;
const purposeLabel = genericUpload
? (assetType === "image" ? `通用图片 · ${body.purpose || "图片素材"}` : body.purpose || "视频素材")
: `${body.name || "数字人形象"} · ${viewLabel}`;
const rejected = /reject|fail/i.test(input.url);
if (!rejected) {
mockAssets.unshift({
asset_id: id,
purpose: assetType === "video" ? viewLabel : `${body.name || "数字人形象"} · ${viewLabel}`,
purpose: purposeLabel,
type: assetType,
status: "ready",
original_url: input.url,
@@ -187,13 +191,16 @@ async function handleApi(request, response, url) {
const labels = { front: "正面", side: "侧面", back: "背面" };
const uploaded = await Promise.all(assetInputs.map(async (input, index) => {
const viewLabel = assetType === "video" ? (body.purpose || "视频素材") : labels[input.view] || `参考图${index + 1}`;
const purposeLabel = genericUpload
? (assetType === "image" ? `通用图片 · ${body.purpose || "图片素材"}` : body.purpose || "视频素材")
: `${body.name || "数字人形象"} · ${viewLabel}`;
const upstream = await callJson("https://ai-api.kkidc.com/v1/assets/upload", {
method: "POST",
headers: bearerHeaders(customerToken),
body: JSON.stringify({
url: input.url,
type: assetType,
purpose: assetType === "video" ? viewLabel : `${body.name || "数字人形象"} · ${viewLabel}`,
purpose: purposeLabel,
}),
});
if (upstream.status >= 400 || upstream.body?.success === false || !upstream.body?.data?.asset_id) {
@@ -559,8 +566,8 @@ function buildVideoPayload(body) {
if (imageReferences.length > 9) {
throw new ClientError(`人物图片与其他参考图片合计最多 9 张,当前为 ${imageReferences.length}`);
}
if (extraImageReferences.some((item) => !isPublicMediaUrl(item, "image"))) {
throw new ClientError("其他参考图片必须是公网可访问的 http/https 图片 URL");
if (extraImageReferences.some((item) => !isAssetReference(item) && !isPublicMediaUrl(item, "image"))) {
throw new ClientError("其他参考图片必须是 asset:// 素材引用或公网图片 URL");
}
if (videoReferences.length > 3 || videoReferences.some((item) => !isAssetReference(item) && !isPublicMediaUrl(item, "video"))) {
throw new ClientError("参考视频最多 3 条,且必须是 asset:// 素材引用或公网 MP4/MOV URL");