Download inference.py from Emma5099/music2dance: direct link, hf CLI and curl.
- Browser
- Download file 2.45 kB
-
https://huggingface.co/Emma5099/music2dance/resolve/main/inference.py
- Command line
-
hf download hf://Emma5099/music2dance/inference.py
-
curl -L -o inference.py https://huggingface.co/Emma5099/music2dance/resolve/main/inference.py
2.45 kB
| """Load checkpoint and run autoregressive pose generation.""" | |
| from __future__ import annotations | |
| import os | |
| from typing import Tuple | |
| import numpy as np | |
| import torch | |
| from audio_features import CONTEXT_LEN | |
| from model import Music2PoseTransformer | |
| DEFAULT_CHECKPOINT = "pytorch_model.pt" | |
| def load_checkpoint( | |
| ckpt_path: str = DEFAULT_CHECKPOINT, | |
| device: torch.device | None = None, | |
| ) -> Tuple[Music2PoseTransformer, dict]: | |
| """Load model weights and normalisation stats from a checkpoint file.""" | |
| if device is None: | |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| ckpt = torch.load(ckpt_path, map_location=device, weights_only=False) | |
| model = Music2PoseTransformer( | |
| audio_dim=ckpt["audio_dim"], | |
| pose_dim=ckpt["pose_dim"], | |
| **ckpt["config"], | |
| ).to(device) | |
| model.load_state_dict(ckpt["model_state"]) | |
| model.eval() | |
| return model, ckpt | |
| def generate_poses( | |
| model: Music2PoseTransformer, | |
| audio_feat: np.ndarray, | |
| x_mean: np.ndarray, | |
| x_std: np.ndarray, | |
| y_mean: np.ndarray, | |
| y_std: np.ndarray, | |
| device: torch.device, | |
| ) -> np.ndarray: | |
| """ | |
| Autoregressive inference. | |
| Returns | |
| ------- | |
| poses_xyz : (T, 33, 3) normalised MediaPipe-style joint positions. | |
| """ | |
| T = audio_feat.shape[0] | |
| af_norm = (audio_feat - x_mean) / x_std | |
| af_t = torch.tensor(af_norm, dtype=torch.float32, device=device) | |
| pose_dim = model.pose_dim | |
| audio_ctx = torch.zeros(1, CONTEXT_LEN, af_t.shape[-1], device=device) | |
| pose_ctx = torch.zeros(1, CONTEXT_LEN, pose_dim, device=device) | |
| preds = [] | |
| with torch.no_grad(): | |
| for t in range(T): | |
| audio_ctx = torch.roll(audio_ctx, -1, dims=1) | |
| audio_ctx[0, -1] = af_t[t] | |
| next_pose = model.step(audio_ctx, pose_ctx)[0] | |
| preds.append(next_pose.cpu().numpy()) | |
| pose_ctx = torch.roll(pose_ctx, -1, dims=1) | |
| pose_ctx[0, -1] = next_pose | |
| pred_norm = np.stack(preds) | |
| pred_raw = pred_norm * y_std + y_mean | |
| return pred_raw.reshape(T, 33, 9)[:, :, :3] | |
| def resolve_checkpoint(path: str | None = None) -> str: | |
| """Return checkpoint path, defaulting to the bundled weights.""" | |
| if path: | |
| return path | |
| if os.path.exists(DEFAULT_CHECKPOINT): | |
| return DEFAULT_CHECKPOINT | |
| raise FileNotFoundError( | |
| f"No checkpoint found. Download weights or pass --checkpoint explicitly." | |
| ) | |