1ripon1's picture
Upload folder using huggingface_hub
7344bef verified
Raw
History Blame Contribute Delete
3.57 kB
from __future__ import annotations
import math
import re
import gradio as gr
TIMED_PROMPT_EXAMPLE = "00:00\nA calm cinematic opening shot.\n\n00:30\nThe mood becomes tense and dramatic."
TIMED_PROMPT_TIMESTAMP_RE = re.compile(r"^\d{1,2}:\d{2}(?::\d{2})?(?:\.\d+)?$")
def parse_time_input(value, *, label: str, allow_empty: bool) -> float | None:
if value is None:
return None if allow_empty else 0.0
if isinstance(value, (int, float)):
if not math.isfinite(float(value)):
raise gr.Error(f"{label} must be a finite time value.")
return max(0.0, float(value))
text = str(value).strip()
if len(text) == 0:
return None if allow_empty else 0.0
if ":" not in text:
try:
seconds = float(text)
if not math.isfinite(seconds):
raise ValueError
return max(0.0, seconds)
except ValueError as exc:
raise gr.Error(f"{label} must be a number of seconds, MM:SS(.xx), or HH:MM:SS(.xx).") from exc
parts = text.split(":")
if len(parts) not in (2, 3):
raise gr.Error(f"{label} must be a number of seconds, MM:SS(.xx), or HH:MM:SS(.xx).")
try:
if len(parts) == 2:
minutes = int(parts[0])
seconds = float(parts[1])
if not math.isfinite(seconds):
raise ValueError
return max(0.0, minutes * 60.0 + seconds)
hours = int(parts[0])
minutes = int(parts[1])
seconds = float(parts[2])
if not math.isfinite(seconds):
raise ValueError
return max(0.0, hours * 3600.0 + minutes * 60.0 + seconds)
except ValueError as exc:
raise gr.Error(f"{label} must be a number of seconds, MM:SS(.xx), or HH:MM:SS(.xx).") from exc
def parse_prompt_schedule(prompt_text: str) -> list[tuple[float, str]]:
text = str(prompt_text or "").replace("\r\n", "\n").replace("\r", "\n").strip()
if len(text) == 0:
return [(0.0, "")]
blocks = [block.strip() for block in re.split(r"\n\s*\n", text) if len(block.strip()) > 0]
first_line = text.split("\n", 1)[0].strip()
if len(blocks) <= 1 and not TIMED_PROMPT_TIMESTAMP_RE.fullmatch(first_line):
return [(0.0, text)]
schedule: list[tuple[float, str]] = []
for block in blocks:
lines = block.split("\n")
timestamp_line = lines[0].strip()
if not TIMED_PROMPT_TIMESTAMP_RE.fullmatch(timestamp_line):
raise gr.Error(
"Timed prompts must be separated by blank lines, and each block must start with a timestamp like MM:SS(.xx) or HH:MM:SS(.xx).\n\n"
f"Example:\n{TIMED_PROMPT_EXAMPLE}"
)
prompt_body = "\n".join(lines[1:]).strip()
if len(prompt_body) == 0:
raise gr.Error(
"Each timed prompt block must contain prompt text after its timestamp.\n\n"
f"Example:\n{TIMED_PROMPT_EXAMPLE}"
)
schedule.append((float(parse_time_input(timestamp_line, label="Timed prompt timestamp", allow_empty=False) or 0.0), prompt_body))
return sorted(schedule, key=lambda item: item[0])
def resolve_prompt_for_chunk(prompt_schedule: list[tuple[float, str]], chunk_start_seconds: float, default_prompt: str) -> str:
prompt_text = str(default_prompt or "")
for start_seconds, scheduled_prompt in prompt_schedule:
if float(start_seconds) <= float(chunk_start_seconds) + 1e-9:
prompt_text = scheduled_prompt
else:
break
return prompt_text