| |
| """Run HY-WorldPlay-DEV-Predictor's generate_predictor_v4_train_case_eval.py at a |
| video length other than the 125-frame protocol (long-video rows of the comparison). |
| |
| HY_NUM_LATENTS (64 = 16 chunks = 253 frames, 128 = 32 chunks = 509 frames) replaces the |
| generator's hard-coded 32 latents / 125 frames: |
| * the four bidirectional camera actions are rescaled the way hycache does it |
| ("w-15,s-16" -> "w-31,s-32" for 64 latents: forward for floor((n-1)/2) latents, |
| back for the rest, so the video still turns around half-way); |
| * pose_to_input gets the new latent count and the pipeline call the matching |
| video_length. |
| The pipeline's own long-video mechanism (pose-retrieved memory frames, at most 20 |
| history latents per chunk) is left as is. DisCa's forward drops the ATC-only keywords |
| the rollout passes (same as hy_dev_gen_disca.py).""" |
| import inspect, os, sys |
| DEV = "/local/zoubin/cz/projects/HY-WorldPlay-DEV-Predictor" |
| sys.path.insert(0, DEV); os.chdir(DEV) |
| N = int(os.environ["HY_NUM_LATENTS"]) |
| assert N % 4 == 0 and N > 0, N |
| FRAMES = (N - 1) * 4 + 1 |
|
|
| import hyvideo.generate as G |
| import predictor_data.prefeature_schema as S |
| from hyvideo.pipelines.worldplay_video_pipeline import HunyuanVideo_1_5_Pipeline |
| import models |
|
|
|
|
| def rescale(pose): |
| (fwd, _), (back, _) = [p.strip().split("-") for p in pose.split(",")] |
| n = N - 1 |
| return f"{fwd}-{n // 2},{back}-{n - n // 2}" |
|
|
|
|
| S.DEFAULT_ACTIONS = tuple((name, rescale(pose)) for name, pose in S.DEFAULT_ACTIONS) |
| print(f"[hy_dev_gen_long] {N} latents = {FRAMES} frames; actions {S.DEFAULT_ACTIONS}", flush=True) |
|
|
| _pose_to_input = G.pose_to_input |
|
|
|
|
| def pose_to_input(pose_data, latent_num, tps=False): |
| return _pose_to_input(pose_data, N if latent_num == 32 else latent_num, tps) |
|
|
|
|
| G.pose_to_input = pose_to_input |
|
|
| _call = HunyuanVideo_1_5_Pipeline.__call__ |
|
|
|
|
| def __call__(self, *args, **kw): |
| if kw.get("video_length") == 125: |
| kw["video_length"] = FRAMES |
| return _call(self, *args, **kw) |
|
|
|
|
| HunyuanVideo_1_5_Pipeline.__call__ = __call__ |
|
|
| _orig = models.HYWorldPlayPredictorDisCa.forward |
| _accepted = set(inspect.signature(_orig).parameters) |
|
|
|
|
| def forward(self, *args, **kw): |
| return _orig(self, *args, **{k: v for k, v in kw.items() if k in _accepted}) |
|
|
|
|
| models.HYWorldPlayPredictorDisCa.forward = forward |
|
|
| |
| |
| import av |
| import tools.generate_predictor_v4_train_case_eval as gen |
|
|
|
|
| def video_is_complete(path): |
| if not path.is_file() or path.stat().st_size == 0: |
| return False |
| try: |
| with av.open(str(path)) as container: |
| stream = container.streams.video[0] |
| if stream.width != 832 or stream.height != 480: |
| return False |
| return sum(1 for _ in container.decode(stream)) == FRAMES |
| except Exception: |
| return False |
|
|
|
|
| gen.video_is_complete = video_is_complete |
| sys.argv[0] = gen.__file__ |
| gen.main() |
|
|