From a4e82556f579e3f7e121bfaf2f2431b52966c138 Mon Sep 17 00:00:00 2001 From: yibo Date: Tue, 1 Sep 2026 16:59:38 +0800 Subject: [PATCH] h3-console/raylight: 支持竖屏视频生成(宽高互换,非独立参数) --- h3-console/static/index.html | 53 +++++++++++++++++++++++++++++++++++++++++++++++++---- raylight/scripts/server.py | 6 ++++++ 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/h3-console/static/index.html b/h3-console/static/index.html index d81dbfb..b4140e8 100644 --- a/h3-console/static/index.html +++ b/h3-console/static/index.html @@ -172,8 +172,10 @@ + +
@@ -210,12 +212,15 @@ +
+
+
@@ -368,11 +373,18 @@ function showCreate(pushUrl = true) { // 数字改动两边一起改。832×480/1024×576/1344×768 三个是真实CUDA OOM边界;448×256 技术上测到 // 3000帧都没OOM,1200帧(50秒)是画质边界(用户看过实际输出判定50秒往后不能看),不是显存边界。 // 1344×768(官方默认分辨率)排第一,作为新建任务的默认选项——2026-08-23 用户要求。 +// 2026-09-01:竖屏是宽高互换实现的,不是独立的横竖屏参数(生产已有 720×1280 提交案例,见 +// docs/todo/h3-showcase-cases.md)。maxFrames 沿用对应横屏档位的实测值——宽高互换总像素数不变, +// 显存/耗时特征预期一致,但没有单独针对竖屏重新跑过 OOM 边界测试,如果发现竖屏更早 OOM 要单独下调。 const RESOLUTIONS = [ - { value: '1344x768', width: 1344, height: 768, label: '1344×768(官方默认分辨率)', maxFrames: 412 }, - { value: '832x480', width: 832, height: 480, label: '832×480(标准档)', maxFrames: 1125 }, - { value: '448x256', width: 448, height: 256, label: '448×256(长时长档)', maxFrames: 1200 }, - { value: '1024x576', width: 1024, height: 576, label: '1024×576(高清档)', maxFrames: 743 }, + { value: '1344x768', width: 1344, height: 768, label: '1344×768(官方默认分辨率,横屏)', maxFrames: 412 }, + { value: '768x1344', width: 768, height: 1344, label: '768×1344(官方默认分辨率,竖屏)', maxFrames: 412 }, + { value: '832x480', width: 832, height: 480, label: '832×480(标准档,横屏)', maxFrames: 1125 }, + { value: '480x832', width: 480, height: 832, label: '480×832(标准档,竖屏)', maxFrames: 1125 }, + { value: '448x256', width: 448, height: 256, label: '448×256(长时长档,横屏)', maxFrames: 1200 }, + { value: '256x448', width: 256, height: 448, label: '256×448(长时长档,竖屏)', maxFrames: 1200 }, + { value: '1024x576', width: 1024, height: 576, label: '1024×576(高清档,横屏)', maxFrames: 743 }, + { value: '576x1024', width: 576, height: 1024, label: '576×1024(高清档,竖屏)', maxFrames: 743 }, ]; const DURATIONS = [ { value: '124', frames: 124, label: '5s' }, @@ -441,6 +453,34 @@ async function uploadFile(file) { return await r.json(); } +// 外部 URL 不经过 /v1/assets 转存,直接把地址原样交给后端——raylight 拿到 reference_image_urls +// 等字段里的 URL 就是 urllib.request.urlopen() 下载,本机 /v1/assets 生成的 URL 和外部 URL +// 对它没有区别。所以这里跳过上传,直接把用户粘贴的地址塞进 uploaded 状态。 +// ponytail: 不校验 URL 是否可达/是图片——排队执行时后端下载失败才会报错,不在提交阶段拦截。 +function addSingleUrl(key, inputId, renderFn, errBoxId) { + const input = document.getElementById(inputId); + const url = input.value.trim(); + if (!url) return; + uploaded[key] = url; + input.value = ''; + document.getElementById(errBoxId).textContent = ''; + renderFn(); +} + +function addArrayUrl(key, inputId, renderFn, errBoxId, cap) { + const input = document.getElementById(inputId); + const url = input.value.trim(); + if (!url) return; + if (cap && uploaded[key].length >= cap) { + document.getElementById(errBoxId).textContent = `最多${cap}个,已达上限`; + return; + } + uploaded[key].push(url); + input.value = ''; + document.getElementById(errBoxId).textContent = ''; + renderFn(); +} + // server.py 把原始文件名塞进了存盘文件名里(__<原名>.ext),这里直接从 URL 反解出来 // 显示——不用单独维护一份 filename 状态,旧任务(改动前上传的,URL 里没有 __ 分段)会 // 退化成显示 uuid 文件名,不算错误,只是没有原名可用。 @@ -629,12 +669,17 @@ function clearForm(kind) { uploaded['fl2va-first'] = null; uploaded['fl2va-last'] = null; document.getElementById('fl2va-first').value = ''; document.getElementById('fl2va-last').value = ''; + document.getElementById('fl2va-first-url').value = ''; + document.getElementById('fl2va-last-url').value = ''; renderFl2vaThumbs(); } else if (kind === 'ref2va') { uploaded['ref2va-refs'] = []; uploaded['ref2va-videos'] = []; uploaded['ref2va-audios'] = []; document.getElementById('ref2va-refs').value = ''; document.getElementById('ref2va-videos-input').value = ''; document.getElementById('ref2va-audios-input').value = ''; + document.getElementById('ref2va-refs-url').value = ''; + document.getElementById('ref2va-videos-url').value = ''; + document.getElementById('ref2va-audios-url').value = ''; renderRefThumbs(); renderTags('ref2va-video-tags', 'ref2va-videos'); renderTags('ref2va-audio-tags', 'ref2va-audios'); diff --git a/raylight/scripts/server.py b/raylight/scripts/server.py index f2a599e..d2469fd 100644 --- a/raylight/scripts/server.py +++ b/raylight/scripts/server.py @@ -96,11 +96,17 @@ RAY_INIT_CFG = { # 或画质边界(448×256,见notes.md——技术上测到3000帧都没OOM,是用户看过实际输出判定50秒往后 # 画质不能看,不是显存拦的)。跟 h3-console 前端 RESOLUTIONS 里的 maxFrames 保持一致—— # 两边算法对不上就会出现"前端放行、后端拒绝"或反过来,数字改动两边一起改。 +# 2026-09-01:竖屏(宽高互换)条目沿用对应横屏档位的实测上限——总像素数不变,显存/耗时特征预期 +# 一致,但没有专门为竖屏重跑过 OOM 边界测试,如果实测发现竖屏更早 OOM 要单独下调,不要假设两者永远相等。 RESOLUTION_CEILINGS = { (832, 480): 1125, + (480, 832): 1125, (448, 256): 1200, + (256, 448): 1200, (1024, 576): 743, + (576, 1024): 743, (1344, 768): 412, + (768, 1344): 412, } CLIP_NAME = "qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors" VAE_VIDEO = "minimax_h3_video_vae_fp16.safetensors" -- libgit2 0.21.4