fix: match candidate previews to video ratio
This commit is contained in:
@@ -224,6 +224,7 @@ el.videoForm.addEventListener("submit", async (event) => {
|
|||||||
createdAt: Date.now(),
|
createdAt: Date.now(),
|
||||||
lastCheckedAt: null,
|
lastCheckedAt: null,
|
||||||
progress: 5,
|
progress: 5,
|
||||||
|
ratio: shot.ratio,
|
||||||
};
|
};
|
||||||
shot.versions.push(version);
|
shot.versions.push(version);
|
||||||
state.activeGenerationShotId = shot.id;
|
state.activeGenerationShotId = shot.id;
|
||||||
@@ -692,10 +693,16 @@ function renderVersionList() {
|
|||||||
card.className = `version-card${shot.selectedVersionId === version.id ? " selected" : ""}`;
|
card.className = `version-card${shot.selectedVersionId === version.id ? " selected" : ""}`;
|
||||||
const preview = document.createElement("div");
|
const preview = document.createElement("div");
|
||||||
preview.className = "version-preview";
|
preview.className = "version-preview";
|
||||||
|
setVersionPreviewRatio(preview, version.ratio || shot.ratio);
|
||||||
if (version.videoUrl) {
|
if (version.videoUrl) {
|
||||||
const video = document.createElement("video");
|
const video = document.createElement("video");
|
||||||
video.src = version.videoUrl;
|
video.src = version.videoUrl;
|
||||||
video.controls = true;
|
video.controls = true;
|
||||||
|
video.playsInline = true;
|
||||||
|
video.preload = "metadata";
|
||||||
|
video.addEventListener("loadedmetadata", () => {
|
||||||
|
if (video.videoWidth && video.videoHeight) setVersionPreviewRatio(preview, `${video.videoWidth}:${video.videoHeight}`);
|
||||||
|
}, { once: true });
|
||||||
preview.appendChild(video);
|
preview.appendChild(video);
|
||||||
} else preview.textContent = version.status === "running" ? "生成中" : version.status === "failed" ? "生成失败" : "暂无预览";
|
} else preview.textContent = version.status === "running" ? "生成中" : version.status === "failed" ? "生成失败" : "暂无预览";
|
||||||
const details = document.createElement("div");
|
const details = document.createElement("div");
|
||||||
@@ -734,6 +741,15 @@ function renderVersionList() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setVersionPreviewRatio(preview, ratio) {
|
||||||
|
const [width, height] = String(ratio || "16:9").split(":").map(Number);
|
||||||
|
const safeWidth = width > 0 ? width : 16;
|
||||||
|
const safeHeight = height > 0 ? height : 9;
|
||||||
|
preview.style.setProperty("--preview-ratio", `${safeWidth} / ${safeHeight}`);
|
||||||
|
preview.classList.toggle("portrait", safeHeight > safeWidth);
|
||||||
|
preview.classList.toggle("square", safeHeight === safeWidth);
|
||||||
|
}
|
||||||
|
|
||||||
function videoProxyUrl(taskId) {
|
function videoProxyUrl(taskId) {
|
||||||
const base = API_BASE || location.origin;
|
const base = API_BASE || location.origin;
|
||||||
return `${base}/api/videos/${encodeURIComponent(taskId)}/video.mp4`;
|
return `${base}/api/videos/${encodeURIComponent(taskId)}/video.mp4`;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>营响力|AI 短剧数字人 Demo</title>
|
<title>营响力|AI 短剧数字人 Demo</title>
|
||||||
<link rel="stylesheet" href="./styles.css?v=23" />
|
<link rel="stylesheet" href="./styles.css?v=24" />
|
||||||
</head>
|
</head>
|
||||||
<body data-active-module="library">
|
<body data-active-module="library">
|
||||||
<header class="topbar">
|
<header class="topbar">
|
||||||
@@ -283,6 +283,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="toast hidden" id="toast"></div>
|
<div class="toast hidden" id="toast"></div>
|
||||||
<script src="./app.js?v=28"></script>
|
<script src="./app.js?v=29"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -239,9 +239,11 @@ hr { border: 0; border-top: 1px solid var(--line); margin: 26px 0 0; }
|
|||||||
.version-head h3 { margin: 5px 0 0; font-size: 16px; }
|
.version-head h3 { margin: 5px 0 0; font-size: 16px; }
|
||||||
.version-head > span { color: var(--muted); font-size: 11px; }
|
.version-head > span { color: var(--muted); font-size: 11px; }
|
||||||
.version-list, .assembly-list { display: grid; gap: 10px; margin-top: 12px; }
|
.version-list, .assembly-list { display: grid; gap: 10px; margin-top: 12px; }
|
||||||
.version-card { display: grid; grid-template-columns: 116px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 10px; border: 1px solid var(--line); border-radius: 12px; background: #fafbfe; }
|
.version-card { display: grid; grid-template-columns: max-content minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 10px; border: 1px solid var(--line); border-radius: 12px; background: #fafbfe; }
|
||||||
.version-card.selected { border-color: var(--green); background: var(--green-soft); }
|
.version-card.selected { border-color: var(--green); background: var(--green-soft); }
|
||||||
.version-preview { width: 116px; aspect-ratio: 16 / 9; border-radius: 8px; overflow: hidden; display: grid; place-items: center; background: #111827; color: #d6dceb; font-size: 10px; }
|
.version-preview { width: 150px; aspect-ratio: var(--preview-ratio, 16 / 9); border-radius: 8px; overflow: hidden; display: grid; place-items: center; background: #111827; color: #d6dceb; font-size: 10px; }
|
||||||
|
.version-preview.portrait { width: 84px; }
|
||||||
|
.version-preview.square { width: 108px; }
|
||||||
.version-preview video { width: 100%; height: 100%; object-fit: contain; background: #111827; }
|
.version-preview video { width: 100%; height: 100%; object-fit: contain; background: #111827; }
|
||||||
.version-copy { min-width: 0; display: grid; gap: 4px; }
|
.version-copy { min-width: 0; display: grid; gap: 4px; }
|
||||||
.version-copy strong { font-size: 13px; }
|
.version-copy strong { font-size: 13px; }
|
||||||
@@ -275,7 +277,7 @@ hr { border: 0; border-top: 1px solid var(--line); margin: 26px 0 0; }
|
|||||||
.shot-overview-head { align-items: flex-start; }
|
.shot-overview-head { align-items: flex-start; }
|
||||||
.shot-overview-head > div { align-items: flex-start; flex-direction: column; gap: 3px; }
|
.shot-overview-head > div { align-items: flex-start; flex-direction: column; gap: 3px; }
|
||||||
.shot-overview-list .shot-card { flex-basis: 190px; }
|
.shot-overview-list .shot-card { flex-basis: 190px; }
|
||||||
.version-card { grid-template-columns: 90px minmax(0, 1fr); }
|
.version-card { grid-template-columns: max-content minmax(0, 1fr); }
|
||||||
.version-actions { grid-column: 1 / -1; width: 100%; grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
.version-actions { grid-column: 1 / -1; width: 100%; grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||||
.form-grid { grid-template-columns: 1fr; }
|
.form-grid { grid-template-columns: 1fr; }
|
||||||
.view-grid { grid-template-columns: 1fr; }
|
.view-grid { grid-template-columns: 1fr; }
|
||||||
|
|||||||
Reference in New Issue
Block a user