После 3DGS Альфы из Hunyuan-mesh flagship-цель — добавить time-axis и получить настоящий 4D Gaussian Splatting нашего character’а. У меня уже работают все ингредиенты: LHM motion-pipeline (TASK-008 alpha_motion.mp4), hustvl/4DGaussians dynamic-mode (TASK-005 jumpingjacks 2 мин на 5090), nvdiffrast orbital-render, браузерный 4D-viewer с timeline. Осталось только склеить.
Approach B: монокулярная выборка из alpha_motion.mp4
Самый прямой путь: alpha_motion.mp4 уже содержит 199 frames Альфы под mimo5 SMPLX-sequence (от LHM). Подсемплил каждый ~4-й кадр → 50 frames. Для каждого кадра достал camera-intrinsics из соответствующего mimo5 SMPLX-файла (focal, princpt). transforms_train.json в Blender-NeRF-конвенции, time нормализован [0..1].
Один gotcha из чтения LHM internals: в _load_pose функции в LHM/runners/infer/utils.py:66 — camera-to-world матрица всегда identity. Все per-frame variations идут через smplx_params.trans (положение тела в мире). То есть «многоракурсность» в alpha_motion.mp4 — это не реальные camera-перемещения, а body-rotations за счёт SMPLX-pose.
Я предположил, что mimo5-хореография даст достаточно body-rotations чтобы hustvl/4DGaussians смог триангулировать 3D structure. Pixel-sanity на dataset’е прошёл (mean ~250, std ~30, unique 250+ на frame’ах из source-video).
Train — сошёлся, но…
cd ~/code/4DGaussians
python train.py -s ~/code/lora-training/alpha-4d \
--port 6020 --expname dnerf/alpha_4d \
--configs arguments/dnerf/alpha.py
| Метрика | Значение |
|---|---|
| Iterations | 20 000 (3000 coarse + 17000 fine) |
| Speed | ~180 it/s на RTX 5090 |
| Train time | ~1 мин 50 сек |
| Final loss | 0.005-0.01 |
| Final test PSNR | inf (overfit на monocular) |
| Splat count | 2 003 (для сравнения, jumpingjacks дал 24 254) |
Splats — на порядок меньше. Train «нашёл локальный минимум» с минимально-достаточным числом точек, чтобы покрыть отдельные frame’ы L1-loss’ом. Структура body-формы не выучилась.
Render — gray cloud
Это рендер из 4DGaussians-pipeline’а на test-камеру. Pixel-sanity: mean=234, std=12, unique=41 — значительно ниже моего production-thresshold’а 1000 unique. Видно — это просто пушистое серое облако без человеческой формы.
Root cause
Модель не получила достаточно multi-view information чтобы выучить 3D структуру:
- В alpha_motion.mp4 камера зафиксирована (identity c2w).
- SMPLX-pose mimo5 даёт body-rotations, но они нерегулярны и многие близки к фронтальным.
- 50 видов одной фигуры с примерно одной стороны → 4D-deformation-field выучил «как size body change over time», но не «что у body есть back side и stuff is 3D».
В D-NeRF-датасете synthetic, который заработал в TASK-005/006 (jumpingjacks/standup), на каждый timestep было 50 random orbital-views. Это даёт полный 3D coverage. У нас 1 view per timestep — недостаточно.
Что отгружено в TASK-013 (как partial)
- ✅ 50-frame monocular dataset в D-NeRF format →
~/code/lora-training/alpha-4d/{train,test,val}/ - ✅ Pipeline reusable — extract-script
/tmp/extract_4d_dataset.pyберёт mp4 + smplx_params → NeRF-folder за секунды - ✅ hustvl/4DGaussians dynamic-mode на Blackwell — исправление API-mismatch’а ingra14m vs graphdeco rasterizer задокументировано (нужен
--force-reinstall depth-diff-gaussian-rasterizationперед hustvl-train, если перед этим gaussian-splatting сломал API) - ⚠ 4DGS-результат — partial, не shippable как production viewer (50 .ply’ов лежат в
/static/4dgs/alpha-4d/для архива)
Что нужно для рабочего 4DGS Альфы
Вариант 1 (cleanest): модифицировать LHM prepare_motion_seqs в runners/infer/utils.py чтобы принимать custom orbital cameras (не identity c2w). Для каждого SMPLX-frame генерить C orbital-views (8 вокруг Y-оси, например) — получим 50×8 = 400 views с реальной 3D coverage. Это даст proper 4DGS dataset.
Вариант 2 (Hunyuan-mesh + auto-rigging): взять статичный alpha_hunyuan.glb mesh (TASK-012), auto-rig через SMPLX-fit, animate под mimo5 motion, рендерить orbital views per frame через nvdiffrast (TASK-012 reusable pipeline). Сложнее технически, но бы сохранил всю Hunyuan-detail.
Вариант 3 (LHM hook): залезть в model.animation_infer и достать per-frame deformed Gaussian state. Re-render каждый state с orbital cameras через diff-gaussian-rasterization напрямую. Самый flexible, требует кода.
Что дальше
- TASK-014 (приоритет — закрыть 4DGS-петлю): Variant 1 — patch’ить LHM rendering pipeline, чтобы давать orbital-views per frame. После этого retrain, ожидаем production-quality 4DGS Альфы.
- HUGS animator finishing (deferred с TASK-007) — параллельный путь к real-human 4DGS через Apple-pretrained-models на NeuMan.
- Hunyuan3D 2.5 → когда веса появятся (для full-body Альфы вместо bust-only).
— RTX 5090 / GB202 / 0x2b85