File size: 2,882 Bytes
6d5047c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
"""Parse and normalize prompt text/duration data from meta dicts."""

import os
from typing import Any, Optional

from kimodo.tools import load_json

from .sanitize import sanitize_text, sanitize_texts


def load_prompts_from_meta(meta_path: str, **kwargs):
    """Load prompts from a meta dict or file. If fps is provided, the durations are converted to
    frames.

    Args:
        meta_path: Path to the meta file.
        **kwargs: Additional arguments to pass to parse_prompts_from_meta.

    Returns:
        texts: List of texts.
        durations: List of durations in seconds or frames.
    """
    if not os.path.exists(meta_path):
        raise FileNotFoundError(f"meta.json not found in input folder: {meta_path}")

    meta = load_json(meta_path)
    return parse_prompts_from_meta(meta, **kwargs)


def parse_prompts_from_meta(
    meta: dict[str, Any],
    fps: Optional[float] = None,
    sanitize: bool = False,
) -> tuple[list[str], list[float]]:
    """Parse prompt texts and durations from a meta dict into normalized lists. If fps is provided,
    the durations are converted to frames.

    Accepts either:
    - Single prompt: "text" (str) and "duration" (float) in seconds.
    - Multiple prompts: "texts" (list of str) and "durations" (list of float) in seconds.

    Returns:
        (texts, durations): texts as list of str, durations as list of float (seconds or frames).
        Lengths of both lists are equal.

    Raises:
        ValueError: If meta does not contain a recognized format.
    """
    # Single prompt
    if "text" in meta and "duration" in meta:
        text = meta["text"]
        duration = float(meta["duration"])
        if fps is not None:
            duration = int(duration * fps)
        if isinstance(text, list):
            raise ValueError("meta has 'text' but it is a list; use 'texts' for multiple prompts")

        if sanitize:
            text = sanitize_text(text)
        return ([text], [duration])

    # Multiple prompts
    if "texts" in meta and "durations" in meta:
        texts = meta["texts"]
        durations = meta["durations"]
        if not isinstance(texts, list) or not isinstance(durations, list):
            raise ValueError("meta 'texts' and 'durations' must be lists")
        if len(texts) != len(durations):
            raise ValueError(f"meta 'texts' and 'durations' length mismatch: {len(texts)} vs {len(durations)}")
        durations = [float(d) for d in durations]
        if fps is not None:
            durations = [int(d * fps) for d in durations]

        if sanitize:
            texts = sanitize_texts(texts)
        return texts, durations

    raise ValueError("meta must contain either 'text' and 'duration', or 'texts' and 'durations'.")