ffy2000 commited on
Commit
35616fd
·
1 Parent(s): e304023

Vendor RIFE into repo

Browse files
Files changed (2) hide show
  1. SPACE_DEPLOYMENT.md +1 -1
  2. app.py +103 -5
SPACE_DEPLOYMENT.md CHANGED
@@ -38,7 +38,7 @@ Useful environment variables:
38
  - `LANCE_GPUS`: comma-separated GPU IDs, for example `0` or `0,1`
39
  - `LANCE_QUEUE_SIZE`: Gradio queue size
40
  - `LANCE_GRADIO_TMP_ROOT`: output and temporary file directory
41
- - `LANCE_ZEROGPU_MAX_DURATION_SECONDS`: fixed `@spaces.GPU` duration request in seconds for all tasks (default: 300)
42
  - `LANCE_INSTALL_FLASH_ATTN_ON_STARTUP`: set to `1` to install the pinned flash-attn wheel during Space startup instead of inside the GPU reservation (the wheel matches Python 3.10.13 and torch 2.8.0)
43
  - `LANCE_PREFETCH_MODEL_ASSETS`: set to `0` to skip CPU-side model prefetch at startup
44
  - `LANCE_PREFETCH_MODEL_VARIANTS`: comma-separated model variants to prefetch, for example `video,image`
 
38
  - `LANCE_GPUS`: comma-separated GPU IDs, for example `0` or `0,1`
39
  - `LANCE_QUEUE_SIZE`: Gradio queue size
40
  - `LANCE_GRADIO_TMP_ROOT`: output and temporary file directory
41
+ - `LANCE_ZEROGPU_MAX_DURATION_SECONDS`: upper bound for the task-aware `@spaces.GPU` duration request in seconds (default cap: 300)
42
  - `LANCE_INSTALL_FLASH_ATTN_ON_STARTUP`: set to `1` to install the pinned flash-attn wheel during Space startup instead of inside the GPU reservation (the wheel matches Python 3.10.13 and torch 2.8.0)
43
  - `LANCE_PREFETCH_MODEL_ASSETS`: set to `0` to skip CPU-side model prefetch at startup
44
  - `LANCE_PREFETCH_MODEL_VARIANTS`: comma-separated model variants to prefetch, for example `video,image`
app.py CHANGED
@@ -5,6 +5,7 @@ import base64
5
  import concurrent.futures
6
  import gc
7
  import html
 
8
  import json
9
  import os
10
  import random
@@ -3214,8 +3215,89 @@ def is_pipeline_pool_ready_for_task(task: str) -> bool:
3214
 
3215
 
3216
  def finalize_zerogpu_duration(estimated_seconds: float, task: str) -> int:
3217
- """Retained for compatibility with earlier duration logic."""
3218
- return clamp_zerogpu_duration(ZERO_GPU_RUN_TASK_DURATION_SECONDS)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3219
 
3220
 
3221
  def get_run_task_gpu_duration(
@@ -3234,8 +3316,23 @@ def get_run_task_gpu_duration(
3234
  cfg_text_scale: float,
3235
  enable_frame_interpolation: bool,
3236
  ) -> int:
3237
- """Return a fixed ZeroGPU reservation duration for compatibility."""
3238
- return ZERO_GPU_RUN_TASK_DURATION_SECONDS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3239
 
3240
 
3241
  def get_pipeline_pool(task: str) -> PipelinePool:
@@ -3265,7 +3362,7 @@ def get_pipeline_pool(task: str) -> PipelinePool:
3265
  return ACTIVE_PIPELINE_POOL
3266
 
3267
 
3268
- @spaces.GPU(size="large", duration=ZERO_GPU_RUN_TASK_DURATION_SECONDS)
3269
  def run_task(
3270
  task: str,
3271
  prompt: str,
@@ -3548,6 +3645,7 @@ def build_demo() -> gr.Blocks:
3548
  show_label=False,
3549
  choices=VIDEO_RESOLUTION_DISPLAY_CHOICES,
3550
  value=DEFAULT_RESOLUTION,
 
3551
  elem_classes=["generation-control"],
3552
  )
3553
  height = gr.Number(value=DEFAULT_HEIGHT, precision=0, visible=False)
 
5
  import concurrent.futures
6
  import gc
7
  import html
8
+ import math
9
  import json
10
  import os
11
  import random
 
3215
 
3216
 
3217
  def finalize_zerogpu_duration(estimated_seconds: float, task: str) -> int:
3218
+ """Clamp a heuristic duration to the deployment cap with a small safety margin."""
3219
+ task_key = normalize_task(task)
3220
+ raw_seconds = float(estimated_seconds)
3221
+ if raw_seconds <= 0:
3222
+ raw_seconds = _estimate_zerogpu_duration_seconds(
3223
+ task_key,
3224
+ prompt="",
3225
+ system_prompt=None,
3226
+ input_video=None,
3227
+ input_image=None,
3228
+ height=0,
3229
+ width=0,
3230
+ num_frames=0,
3231
+ seed=0,
3232
+ resolution="",
3233
+ validation_num_timesteps=0,
3234
+ validation_timestep_shift=0.0,
3235
+ cfg_text_scale=0.0,
3236
+ enable_frame_interpolation=False,
3237
+ )
3238
+ return clamp_zerogpu_duration(math.ceil(raw_seconds * 1.15) + 5)
3239
+
3240
+
3241
+ def _estimate_zerogpu_duration_seconds(
3242
+ task: str,
3243
+ prompt: str,
3244
+ system_prompt: Optional[str],
3245
+ input_video: Optional[str],
3246
+ input_image: Optional[str],
3247
+ height: int,
3248
+ width: int,
3249
+ num_frames: int,
3250
+ seed: int,
3251
+ resolution: str,
3252
+ validation_num_timesteps: int,
3253
+ validation_timestep_shift: float,
3254
+ cfg_text_scale: float,
3255
+ enable_frame_interpolation: bool,
3256
+ ) -> int:
3257
+ internal_task = normalize_task(task)
3258
+ prompt_length = len((prompt or "").strip())
3259
+ has_video_input = bool((input_video or "").strip())
3260
+ has_image_input = bool((input_image or "").strip())
3261
+ is_video_task = internal_task in {TASK_T2V, TASK_VIDEO_EDIT, TASK_X2T_VIDEO}
3262
+ is_image_task = internal_task in {TASK_T2I, TASK_IMAGE_EDIT, TASK_X2T_IMAGE}
3263
+
3264
+ if internal_task == TASK_T2I:
3265
+ return 150
3266
+
3267
+ if internal_task == TASK_IMAGE_EDIT:
3268
+ return 150
3269
+
3270
+ if internal_task == TASK_X2T_IMAGE:
3271
+ return 150
3272
+
3273
+ if internal_task == TASK_X2T_VIDEO:
3274
+ return 200
3275
+
3276
+ if internal_task == TASK_VIDEO_EDIT:
3277
+ base = 300
3278
+ base += min(48, max(0, num_frames - 37) // 2)
3279
+ base += 32 if enable_frame_interpolation else 0
3280
+ base += 20 if has_video_input else 0
3281
+ base += 16 if resolution == "video_480p" else 0
3282
+ return base
3283
+
3284
+ if internal_task == TASK_T2V:
3285
+ base = 224 if resolution == "video_360p" else 264
3286
+ base += min(56, max(0, num_frames - 37) // 2)
3287
+ base += 28 if enable_frame_interpolation else 0
3288
+ base += min(20, prompt_length // 260)
3289
+ return base
3290
+
3291
+ if is_video_task:
3292
+ base = 240
3293
+ base += min(40, max(0, num_frames - 37) // 2)
3294
+ base += 24 if enable_frame_interpolation else 0
3295
+ return base
3296
+
3297
+ if is_image_task:
3298
+ return 120
3299
+
3300
+ return 160
3301
 
3302
 
3303
  def get_run_task_gpu_duration(
 
3316
  cfg_text_scale: float,
3317
  enable_frame_interpolation: bool,
3318
  ) -> int:
3319
+ estimated_seconds = _estimate_zerogpu_duration_seconds(
3320
+ task=task,
3321
+ prompt=prompt,
3322
+ system_prompt=system_prompt,
3323
+ input_video=input_video,
3324
+ input_image=input_image,
3325
+ height=height,
3326
+ width=width,
3327
+ num_frames=num_frames,
3328
+ seed=seed,
3329
+ resolution=resolution,
3330
+ validation_num_timesteps=validation_num_timesteps,
3331
+ validation_timestep_shift=validation_timestep_shift,
3332
+ cfg_text_scale=cfg_text_scale,
3333
+ enable_frame_interpolation=enable_frame_interpolation,
3334
+ )
3335
+ return finalize_zerogpu_duration(estimated_seconds, task)
3336
 
3337
 
3338
  def get_pipeline_pool(task: str) -> PipelinePool:
 
3362
  return ACTIVE_PIPELINE_POOL
3363
 
3364
 
3365
+ @spaces.GPU(size="large", duration=get_run_task_gpu_duration)
3366
  def run_task(
3367
  task: str,
3368
  prompt: str,
 
3645
  show_label=False,
3646
  choices=VIDEO_RESOLUTION_DISPLAY_CHOICES,
3647
  value=DEFAULT_RESOLUTION,
3648
+ allow_custom_value=True,
3649
  elem_classes=["generation-control"],
3650
  )
3651
  height = gr.Number(value=DEFAULT_HEIGHT, precision=0, visible=False)