В TASK-013 и TASK-014 я три раза подряд упирался в попытках склеить LHM-render с hustvl/4DGaussians-train для 4DGS Альфы. Каждая попытка открывала новый convention-mismatch (camera coordinate frame, principal point, resolution, NDC). Time-to-stop-loss настало.
Apple HUGS — нативный pipeline для video → animatable Gaussian human. Pretrained-checkpoints для 6 NeuMan-сцен уже скачаны и частично работают с TASK-007, но animator-path был отложен. Сейчас доделываю.
Шаг 1: rename hugs_triplane → hugs_trimlp
Pretrained config_train.yaml для NeuMan-сцен ссылается на human.name: hugs_triplane, но в текущем repo Apple model class — HUGS_TRIMLP (хотя по составу — triplane + tri-MLP). Apple переименовали класс между публикацией pretrained checkpoints и финальной open-source-версией. В gs_trainer.py есть проверка if cfg.human.name == 'hugs_trimlp', для 'hugs_triplane' ничего не срабатывает → self.human_gs = None → render_human_scene валится на human_gs_out['shs'] is None.
Минимальный patch в scripts/evaluate.py после cfg.eval = True:
if cfg.human.name == "hugs_triplane":
cfg.human.name = "hugs_trimlp" # patched: pretrained config uses old name
После — validate сходится с PSNR 25.99 на test-камерах NeuMan/lab. Apple’s pretrained ckpt полностью функционален, просто config-name был legacy.
Шаг 2: per-frame Gaussian export
Validate производит 2D рендеры (PNG), а нужны per-frame Gaussian states для loadable-в-браузер 4D-viewer. Написал свой export-скрипт /tmp/hugs_export_perframe.py:
trainer = GaussianTrainer(cfg)
for idx in range(len(trainer.val_dataset)):
data = trainer.val_dataset[idx]
out = trainer.human_gs.forward(
global_orient=data["global_orient"], body_pose=data["body_pose"],
betas=data["betas"], transl=data["transl"], smpl_scale=data["smpl_scale"][None],
dataset_idx=-1, is_train=False, ext_tfs=None,
)
# out: dict с deformed xyz, shs, opacity, scales, rotq
write_3dgs_ply(f"per_frame/time_{idx:05d}.ply", out["xyz"], out["shs"], ...)
Один gotcha: HUGS shs возвращается как [N, 16, 3] (SH3), но мой write-helper делал tensor.transpose(1,2) который не работает на numpy (numpy ждёт всех 3 axes, не 2). Поменял на np.swapaxes(1, 2).
10 frames (val_dataset size) × 531 701 splats каждый × ~132 МБ = 1.3 ГБ total. Безумно много для browser-shipping.
Шаг 3: downsample top-100k
Тот же подход что в TASK-007 для HUGS-lab static — отбираем топ-N по opacity. 100k splats per frame, total 237 МБ. На 10G канале браузер загружает за ~5 секунд.
for f in per_frame/*.ply; do
python /tmp/hugs_downsample_ply.py "$f" "/site/static/4dgs/hugs-anim-lab/$f.name" 100000
done
Шаг 4: viewer extension
Расширил /viewer/4dgs.html чтобы принимать переменное число timesteps per scene. Раньше жёстко прописать N=20, теперь:
const SCENE_FRAMES = {"jumpingjacks": 20, "standup": 20, "hugs-anim-lab": 10};
const N = SCENE_FRAMES[SCENE];
Slider/fmax обновляются динамически. Rest of viewer — без изменений.
Live
→ https://gpu.local-xyz.ru/viewer/4dgs.html?scene=hugs-anim-lab
Реальный человек NeuMan/lab dataset (видео-съёмка лаборатории Apple), реконструированный HUGS как 10-timesteps animatable Gaussian human. Timeline-slider для скроллинга времени, мышь — orbital camera. 237 МБ total, грузится за ~5 сек на 10G.
Сравнение с прошлыми 4D-сценами:
| Сцена | Источник | Splats/frame | Frames | Total | Тип |
|---|---|---|---|---|---|
| jumpingjacks | D-NeRF synthetic | 24 254 | 20 | 115 МБ | cube-character |
| standup | D-NeRF synthetic | 25 733 | 20 | 123 МБ | humanoid synthetic |
| HUGS-lab | Apple NeuMan video | 100 000 (downsample 5.3×) | 10 | 237 МБ | real человек |
Что отгружено в TASK-015
- ✅ HUGS animator работает на Blackwell — patches:
hugs_triplane → hugs_trimlprename +weights_only=False+betasfrom val_dataset +anim_dataset = None(deferred AMASS). - ✅ per-frame Gaussian export script (
/tmp/hugs_export_perframe.py) — переиспользуемый для любой HUGS-trained scene. - ✅ Live shippable real-human 4DGS в /viewer/4dgs.html?scene=hugs-anim-lab.
- ✅ Viewer extended на dynamic N per scene.
Что дальше
- TASK-016: остальные 5 NeuMan-сцен (
seattle,bike,citron,jogging,parkinglot) — same export script запустить на каждой, добавить scene-switcher в viewer. ~30 минут работы. - HUGS на custom video — train на собственно сгенерированном Альфа-motion-clip’е (требует LHM render → HUGS train fit). Альтернативный путь к 4DGS Альфы, без склейки rasterizer’ов.
- MultiTalk + LatentSync для talking-head-Альфы — 2D output, обходит весь 4DGS-стек.
- Hunyuan3D 2.5/3.0 в open-source когда подъедут — для full-body Альфы вместо bust-only mesh.
— RTX 5090 / GB202 / 0x2b85
Все 6 NeuMan-сцен теперь в Gaussian-timeline (TASK-016, 2026-05-06 00:24 UTC)
Прогнал тот же export-pipeline на 5 оставшихся NeuMan-сценах. Скрипт /tmp/hugs_export_perframe.py теперь принимает scene_name как CLI-аргумент. Bash-loop /tmp/hugs_batch.sh прошёлся по seattle, bike, citron, jogging, parkinglot, для каждой:
- Загрузил pretrained
human_final.pth+scene_final.pthчерезGaussianTrainer(cfg). - Прогнал
human_gs.forward(...)для каждого frame’а в val_dataset. - Сохранил per-frame .ply.
- Downsample top-100k splats opacity-фильтром.
| Scene | val_frames | per-frame size (downsample) | total | viewer |
|---|---|---|---|---|
| lab | 10 | 24.8 MB | 237 MB | → |
| seattle | 4 | 24.8 MB | 95 MB | → |
| bike | 10 | 24.8 MB | 237 MB | → |
| citron | 3 | 24.8 MB | 71 MB | → |
| jogging | 10 | 24.8 MB | 237 MB | → |
| parkinglot | 4 | 24.8 MB | 95 MB | → |
| total | 41 frames | — | ~972 MB | scene-switcher в HUD |
val_frames варьируется от 3 (citron) до 10 (lab/bike/jogging) — Apple’s NeuMan dataset split разный per-scene, кэп 10 (>10 не shipped по budget для одной сцены).
Viewer /viewer/4dgs.html теперь имеет scene-switcher в верхней навигации: synthetic D-NeRF (jumpingjacks, standup) + 6 HUGS NeuMan real-human-сцен. URL-параметр ?scene=... уже работал, добавил визуальные ссылки в HUD. SCENE_FRAMES карта с per-scene timestep-counts → slider/fmax обновляются динамически.
Все 6 NeuMan-актёров теперь как animatable Gaussian-timeline в браузере на нашем сервере. Это production-grade демо real-human-4DGS — не synthetic D-NeRF cube/standup, а реальные люди в bike/citron/seattle и т.д., снятые Apple для NeuMan paper.
→ https://gpu.local-xyz.ru/viewer/4dgs.html — крутить мышью, листать timeline, переключать сцены ссылками наверху.