dzmdd's picture
Upload folder using huggingface_hub
e488ce7 verified
Raw History Blame Contribute Delete
5.02 kB
"""plan.json -> a minted .api.json, from a shell. The T0 rung, usable alone.
python -m timeline.cli compile PLAN.json --graph OUT.api.json
python -m timeline.cli price PLAN.json [--port 8189]
python -m timeline.cli new CLIP.mp4 --frames 124 --ramp 73:2.0 \
--out PLAN.json
It never queues anything: launching is queue_scene.py's job (the project's
only sanctioned launcher, which guards prefix collisions and refuses
partial graphs). This prints the exact command instead.
Run it from the pack directory, or with the pack on PYTHONPATH.
"""
import argparse
import json
import os
import sys
if __package__ in (None, ""): # `python timeline/cli.py`
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from timeline import schema # noqa: E402
from timeline.h3.compile import H3Backend # noqa: E402
# Site config: set these for your install. H3_TIMELINE_QUEUE_CMD is the command
# that submits an API graph to ComfyUI (a launcher script of your own; the
# authoring box uses a private queue_scene.py); H3_TIMELINE_GRAPH_DIR is where
# compiled graphs live. Without them the CLI compiles but does not queue.
QUEUE = os.environ.get("H3_TIMELINE_QUEUE_CMD", "")
def _default_graph(plan_path):
base = os.path.basename(plan_path).replace(".plan.json", "").replace(
".json", "")
return os.path.join(os.environ.get("H3_TIMELINE_GRAPH_DIR",
os.path.join(os.getcwd(), "workflows")),
f"{base}.api.json")
def cmd_new(a):
plan = schema.new_plan(a.clip, frames=a.frames, fps=a.fps,
width=a.width, height=a.height,
proposed_by="timeline.cli",
settings={"prompt": a.prompt, "seed": a.seed,
"steps": a.steps,
"regen_strength": a.regen_strength,
"output_prefix": a.output_prefix})
env = [[0, 1.0]]
for spec in a.ramp:
f, r = spec.split(":")
env.append([int(f), float(r)])
if env[-1][0] != a.frames - 1:
env.append([a.frames - 1, env[-1][1]])
plan["lanes"].append(schema.generation_density_lane(
env, ceiling=a.ceiling, proposer="timeline.cli"))
schema.validate_or_raise(plan)
print("wrote", schema.save(plan, a.out))
print(json.dumps(plan["lanes"][0]["envelope"]))
def cmd_compile(a):
plan = schema.load(a.plan)
problems = schema.validate(plan)
if problems:
sys.exit("INVALID PLAN: " + "; ".join(problems))
graph = a.graph or _default_graph(a.plan)
res = H3Backend().compile(plan, {"graph_path": graph, "port": a.port,
"recorder_path": a.recorder})
schema.save(plan, a.plan)
print(res.report)
print("minted:", graph)
print("plan updated (compiled cache):", a.plan)
print("launch:", f"{QUEUE} {graph} --tag timeline --port {a.port}")
def cmd_price(a):
plan = schema.load(a.plan)
est = H3Backend().estimate(plan, {"port": a.port, "recorder_path": a.recorder})
print(est)
def main(argv=None):
ap = argparse.ArgumentParser(prog="timeline.cli")
sub = ap.add_subparsers(dest="cmd", required=True)
n = sub.add_parser("new", help="write a plan with one density ramp")
n.add_argument("clip")
n.add_argument("--frames", type=int, required=True)
n.add_argument("--fps", type=float, default=24.0)
n.add_argument("--width", type=int, default=1152)
n.add_argument("--height", type=int, default=640)
n.add_argument("--ramp", action="append", default=[],
metavar="FRAME:DENSITY",
help="density envelope control point (generated frames "
"per world frame; 1.0 = plain)")
n.add_argument("--ceiling", type=float, default=4.0)
n.add_argument("--prompt", default="")
n.add_argument("--seed", type=int, default=20260817)
n.add_argument("--steps", type=int, default=25)
n.add_argument("--regen-strength", dest="regen_strength", type=float,
default=0.45)
n.add_argument("--output-prefix", dest="output_prefix",
default="video/timeline")
n.add_argument("--out", required=True)
n.set_defaults(func=cmd_new)
c = sub.add_parser("compile", help="plan -> minted .api.json")
c.add_argument("plan")
c.add_argument("--graph", default=None)
c.add_argument("--port", type=int, default=8189)
c.add_argument("--recorder", default=None)
c.set_defaults(func=cmd_compile)
p = sub.add_parser("price", help="price a plan without minting")
p.add_argument("plan")
p.add_argument("--port", type=int, default=8189)
p.add_argument("--recorder", default=None)
p.set_defaults(func=cmd_price)
a = ap.parse_args(argv)
return a.func(a)
if __name__ == "__main__":
main()