From e2d1152b29f9776143eedf29befde38e0b89cc87 Mon Sep 17 00:00:00 2001 From: yibo Date: Tue, 22 Sep 2026 16:10:41 +0800 Subject: [PATCH] Add 高清重绘 admin UI + 4 列房间网格;补 H3 cancel 端点文档 --- H3-CONSOLE.md | 11 +++++++++++ admin-dance-library.html | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- blacklist.json | 10 ++++++++++ dance-refs.json | 6 ++++-- dance-rooms.html | 12 ++++++++---- garments.json | 18 ++++++++++++------ generation-jobs.json | 6104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 7 files changed, 6260 insertions(+), 19 deletions(-) create mode 100644 blacklist.json diff --git a/H3-CONSOLE.md b/H3-CONSOLE.md index 8e13227..a9aeba9 100644 --- a/H3-CONSOLE.md +++ b/H3-CONSOLE.md @@ -136,6 +136,17 @@ Calling it on several jobs in a row puts the most-recently-prioritized one at position 1 and pushes the others back slightly — still clusters them all near the front, just not in a guaranteed relative order between themselves. +### `POST {base}/v1/videos/{id}/cancel` +Genuinely cancels a `queued`/`running` job — unlike `DELETE` (below), which +only hides it from listings but lets it keep consuming compute. Confirmed +live 2026-09-09: cancelling a queued job flips its `status` to `cancelled`, +sets `error` to `"用户手动取消"` and `finished_at`, and the cluster's +`queued` count in `GET /v1/backends` actually decrements. Use this (not +DELETE) to actually stop a duplicate/unwanted queued job. +```json +{ "id": "6361be157e48", "status": "cancelled", "error": "用户手动取消", ... } +``` + ### `GET {base}/v1/videos/{id}/file` Downloads the mp4. `Content-Type: video/mp4`, supports range requests (`Accept-Ranges: bytes`), `Content-Disposition: attachment`. Auth via diff --git a/admin-dance-library.html b/admin-dance-library.html index d5580d7..ad61afa 100644 --- a/admin-dance-library.html +++ b/admin-dance-library.html @@ -39,6 +39,12 @@ .pub-badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 12px; white-space: nowrap; } .pub-on { background: #eef7ee; color: #2e7d32; } .pub-off { background: #f0f0f0; color: var(--muted); } + /* 高清重绘: one cell per resolution tier — either a small preview (done), + a disabled "生成中…" state, or a "生成高清版" button (not generated yet). */ + td.hd-cell { min-width: 110px; } + td.hd-cell video { display: block; width: 100px; height: auto; max-height: 160px; object-fit: contain; background: #000; border-radius: 4px; margin-bottom: 4px; } + td.hd-cell .hd-status { font-size: 12px; color: var(--muted); } + td.hd-cell .hd-status.hd-failed { color: #c0392b; } @@ -87,6 +93,13 @@ + + ${hdCell(c, HD_RENDER_TIERS[0])} + ${hdCell(c, HD_RENDER_TIERS[1])} ${characterCell(c)} ${garmentCell(c)} ${danceRefCell(c)} @@ -333,6 +415,8 @@ function render() { ${escapeHtml((c.fullPrompt || "").slice(0, 80))}${(c.fullPrompt || "").length > 80 ? "…" : ""} ${videoHref(c)} + ${hdCell(c, HD_RENDER_TIERS[0])} + ${hdCell(c, HD_RENDER_TIERS[1])} ${characterCell(c)} ${garmentCell(c)} ${danceRefCell(c)} @@ -357,7 +441,7 @@ function render() { // Loading preload="metadata" for every row at once would hammer the // /lib/video proxy (each clip is a fresh H3 Console fetch); only pull a // row's first frame once it's actually scrolled into view. - tbody.querySelectorAll("td.preview video[data-src], td.ref-thumb video[data-src]").forEach((v) => previewObserver.observe(v)); + tbody.querySelectorAll("td.preview video[data-src], td.ref-thumb video[data-src], td.hd-cell video[data-src]").forEach((v) => previewObserver.observe(v)); tbody.querySelectorAll("[data-edit]").forEach((b) => b.addEventListener("click", () => { editingId = b.dataset.edit; render(); })); tbody.querySelectorAll("[data-cancel]").forEach((b) => b.addEventListener("click", () => { editingId = null; render(); })); @@ -396,6 +480,33 @@ function render() { else b.disabled = false; }) ); + tbody.querySelectorAll("[data-hd-gen]").forEach((b) => + b.addEventListener("click", async () => { + const id = b.dataset.hdGen; + const width = Number(b.dataset.width); + const height = Number(b.dataset.height); + b.disabled = true; + b.textContent = "提交中…"; + try { + const res = await fetch(`/api/admin/library/${id}/hd-render`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ width, height }), + }); + const data = await res.json().catch(() => ({})); + if (!res.ok) { + alert(data.error || "提交失败"); + b.disabled = false; + b.textContent = "生成高清版"; + return; + } + await loadLibrary(); // re-render shows "生成中…" (or the finished preview, if H3 happened to return cached:true) + } catch { + b.disabled = false; + b.textContent = "生成高清版"; + } + }) + ); tbody.querySelectorAll("[data-qc-check]").forEach((b) => b.addEventListener("click", async () => { const id = b.dataset.qcCheck; @@ -435,6 +546,7 @@ document.getElementById("garmentFilter").addEventListener("change", render); document.getElementById("danceRefFilter").addEventListener("change", render); document.getElementById("qcFilter").addEventListener("change", render); document.getElementById("publishFilter").addEventListener("change", render); +document.getElementById("hdFilter").addEventListener("change", render); document.getElementById("addBtn").addEventListener("click", async () => { const errorBox = document.getElementById("addError"); diff --git a/blacklist.json b/blacklist.json new file mode 100644 index 0000000..a3eca8c --- /dev/null +++ b/blacklist.json @@ -0,0 +1,10 @@ +[ + { + "id": "69a398b4-b36d-4756-85d5-6ba76f9efb9c", + "createdAt": 1789886140463, + "targetType": "character", + "targetId": "8b992ec5-c320-499d-b380-a5907c897474", + "reason": "跟 Moera 长得太像,用户反馈需要下架", + "createdBy": null + } +] \ No newline at end of file diff --git a/dance-refs.json b/dance-refs.json index 69b18cf..d5a9c91 100644 --- a/dance-refs.json +++ b/dance-refs.json @@ -104,7 +104,8 @@ "durationSec": null, "motionDescriptor": "双手举至脸颊两侧比划框脸手势,俏皮可爱,上身动作为主", "copyrightSource": "test_placeholder", - "isActive": true + "isActive": true, + "h3AssetUrl": "http://192.168.110.67:8080/assets/fba12b3d62e548ba__0638d68c-0aac-442e-b9ee-5a7f60f6cc65.mp4" }, { "id": "dee22838-4453-4386-9bed-4d69c78cd85f", @@ -547,7 +548,8 @@ "durationSec": null, "motionDescriptor": "单臂弯举靠近脸侧,头部微仰侧倾,慵懒俏皮的展示姿态", "copyrightSource": "test_placeholder", - "isActive": true + "isActive": true, + "h3AssetUrl": "http://192.168.110.67:8080/assets/3ec07a69bf86413f__96577e07-f4f9-49d8-9870-2591e561cf51.mp4" }, { "id": "40c054ee-3a52-4865-b965-8f695821be03", diff --git a/dance-rooms.html b/dance-rooms.html index 4aa311a..547e57a 100644 --- a/dance-rooms.html +++ b/dance-rooms.html @@ -9,11 +9,15 @@ \n\n\n

The page you requested was not found.

\n

Sorry, the page you are looking for is currently unavailable.
\nPlease try again later.

\n

The server is powered by frp.

\n

Faithfully yours, frp.

\n\n\n" + }, + { + "id": "9727af09-db7f-4c1d-bb89-f60a612634b2", + "createdAt": 1789943860908, + "kind": "hd_render", + "sourceClipId": "9331f7792dca", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "3da0ae2f-4baa-486b-9128-47379b8864f3", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "1140b062ef10", + "error": null, + "generatedVideoId": "1140b062ef10" + }, + { + "id": "a529227f-41a4-415d-ae54-ecd181734d04", + "createdAt": 1789946534133, + "kind": "hd_render", + "sourceClipId": "d34bcfb5eff6", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "34f2baac-5d14-4f5d-9e11-3baede1aaa65", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "be202ec5902b", + "error": null, + "generatedVideoId": "be202ec5902b" + }, + { + "id": "59d72383-6867-465d-9a6b-7a198a58e934", + "createdAt": 1789949207188, + "kind": "hd_render", + "sourceClipId": "dc0186259e10", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "97efeea4-6f90-4092-90dd-ba27540d5682", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "6246cff70f4a", + "error": null, + "generatedVideoId": "6246cff70f4a" + }, + { + "id": "12b2f664-120e-497f-8cdd-38e229f05712", + "createdAt": 1789951840102, + "kind": "hd_render", + "sourceClipId": "3600d90d0cfd", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "1645498f-ccc4-48c8-a195-15b7b18241db", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "04392c0995df", + "error": null, + "generatedVideoId": "04392c0995df" + }, + { + "id": "f3cbb576-19e4-4712-a41f-9483b934e79b", + "createdAt": 1789954472677, + "kind": "hd_render", + "sourceClipId": "5ac883f42315", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "c370a3fd-bef6-41b1-90c2-a0a56de8bb47", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "2e3f14163e1a", + "error": null, + "generatedVideoId": "2e3f14163e1a" + }, + { + "id": "f39dc334-a35f-4e71-82b5-d8228247a37e", + "createdAt": 1789957105542, + "kind": "hd_render", + "sourceClipId": "5542fa48c846", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "28ae0935-5a8c-45a3-89be-b39a53f91773", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "bd8b8c814b98", + "error": null, + "generatedVideoId": "bd8b8c814b98" + }, + { + "id": "c908e226-173b-4f69-addd-08eef2f21883", + "createdAt": 1789959778524, + "kind": "hd_render", + "sourceClipId": "415763622860", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "da733477-b2b9-4a7c-b042-a347e8e4b412", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "c42a4b7b0720", + "error": null, + "generatedVideoId": "c42a4b7b0720" + }, + { + "id": "f239ce27-bd8f-419f-93e6-cb6f453d7a40", + "createdAt": 1789962491554, + "kind": "hd_render", + "sourceClipId": "7765c19d1afe", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "6215327f-7c51-46ba-b344-75a9f575cb9e", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "43c330b1bc11", + "error": null, + "generatedVideoId": "43c330b1bc11" + }, + { + "id": "8b8f978a-f962-4f33-bdcc-2c9efb63d5a9", + "createdAt": 1789965506200, + "kind": "hd_render", + "sourceClipId": "d86bfe9114ee", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "3490157d-bbf7-469f-a291-6051d80af04c", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "a65254569ccf", + "error": null, + "generatedVideoId": "a65254569ccf" + }, + { + "id": "9d1937a1-e394-4ee3-a873-1b18332c8fe8", + "createdAt": 1789968219308, + "kind": "hd_render", + "sourceClipId": "ccaf964e04e4", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "73049ad1-13f9-4360-bf7e-46b89bcf9eef", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "e68a0e876c74", + "error": null, + "generatedVideoId": "e68a0e876c74" + }, + { + "id": "a4b2572f-b9d0-45c9-b606-eac15d1f5267", + "createdAt": 1789970912683, + "kind": "hd_render", + "sourceClipId": "ea82ada32190", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "c5b61a5c-98fe-4634-913c-7fdc4d7e653e", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "5b0641047b59", + "error": null, + "generatedVideoId": "5b0641047b59" + }, + { + "id": "6c410db1-d140-41a3-a033-9472767e6803", + "createdAt": 1789973927566, + "kind": "hd_render", + "sourceClipId": "4fc337764e2c", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "c1e9dcdc-41a3-4d48-afcf-65cf0e429820", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "0f0b36065adf", + "error": null, + "generatedVideoId": "0f0b36065adf" + }, + { + "id": "d7dc13c0-0fd8-4b68-bac6-5a2cfa971208", + "createdAt": 1789976711431, + "kind": "hd_render", + "sourceClipId": "7552751e4017", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "7d09a69b-2aa1-45af-b281-b10ff0db72ef", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "cec3f84055a6", + "error": null, + "generatedVideoId": "cec3f84055a6" + }, + { + "id": "48ab5ba0-a1ae-49d8-9dff-3bcc3b4c97c3", + "createdAt": 1789979628420, + "kind": "hd_render", + "sourceClipId": "ff818215fd3e", + "characterId": "35b3de40-82fb-4c4c-9f04-eef1a38972b2", + "garmentId": "7e4022ee-78d8-4b1d-b92a-eaf9022e4ac0", + "targetWidth": 768, + "targetHeight": 1344, + "status": "done", + "h3JobId": "8834f8b59b25", + "error": null, + "generatedVideoId": "8834f8b59b25" } ] \ No newline at end of file -- libgit2 0.21.4