File size: 2,503 Bytes
e8b6587
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
from __future__ import annotations


CONDITION_PIPELINE_MODES = frozenset({"FLF2V", "KEYFRAME", "KEYFRAME_FLF2V"})
INVALID_CONDITION_MODE = "INVALID_CONDITION_WITHOUT_START"


def mode_from_condition_images(start_image_path, middle_image_path, end_image_path) -> str:
    """Resolve the product conditioning mode without touching media bytes."""
    if (middle_image_path or end_image_path) and not start_image_path:
        return INVALID_CONDITION_MODE
    if start_image_path and middle_image_path and end_image_path:
        return "KEYFRAME_FLF2V"
    if start_image_path and middle_image_path:
        return "KEYFRAME"
    if start_image_path and end_image_path:
        return "FLF2V"
    if start_image_path:
        return "I2V"
    return "T2V"


def conditioning_mode_status_markdown(start_image_path, middle_image_path, end_image_path) -> str:
    """Human-readable live summary of the mode inferred from conditioning inputs."""
    mode = mode_from_condition_images(start_image_path, middle_image_path, end_image_path)
    labels = {
        "T2V": "T2V · text only",
        "I2V": "I2V · Start frame",
        "FLF2V": "FLF2V · Start + End frames",
        "KEYFRAME": "Keyframe · Start + Middle frames",
        "KEYFRAME_FLF2V": "Keyframe + FLF2V · Start + Middle + End frames",
        INVALID_CONDITION_MODE: "Invalid · Middle/End requires a Start frame",
    }
    return f"**Detected mode:** {labels[mode]}"


def uses_condition_pipeline(mode: str) -> bool:
    return str(mode) in CONDITION_PIPELINE_MODES


def middle_keyframe_latent_index(num_frames: int, temporal_ratio: int = 8) -> int:
    """Nearest non-zero latent index to the pixel-space timeline midpoint."""
    frames = int(num_frames)
    ratio = int(temporal_ratio)
    if frames < 3 or ratio < 1:
        raise ValueError("middle keyframe requires a positive temporal grid")
    latent_num_frames = (frames - 1) // ratio + 1
    if latent_num_frames < 3:
        raise ValueError("video is too short to place a distinct middle keyframe")
    target_pixel_frame = (frames - 1) // 2
    # Non-first keyframe latent index i maps to pixel frame (i - 1) * ratio + 1.
    nearest = ((max(0, target_pixel_frame - 1) + ratio // 2) // ratio) + 1
    return max(1, min(latent_num_frames - 2, int(nearest)))


def keyframe_pixel_frame_index(latent_index: int, temporal_ratio: int = 8) -> int:
    idx = int(latent_index)
    ratio = int(temporal_ratio)
    if idx <= 0:
        return 0
    return (idx - 1) * ratio + 1