Metadata-Version: 2.4
Name: abstract_identity
Version: 0.1.0
Summary: Identity pipeline for hugpy: char360 (video -> character face detection/clustering/360-view selection) + render (identity-render GPU service: Hunyuan3D-2mv mesh, Blender turntable, video_extract, video_characters_glb)
Author: putkoff
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: flask<4.0,>=3.0
Requires-Dist: pydantic<3.0,>=2.0
Provides-Extra: render
Requires-Dist: scenedetect[opencv]; extra == "render"
Requires-Dist: ultralytics; extra == "render"
Requires-Dist: insightface; extra == "render"
Requires-Dist: onnxruntime-gpu==1.18.1; extra == "render"
Requires-Dist: opencv-python; extra == "render"
Requires-Dist: numpy; extra == "render"
Requires-Dist: scikit-learn; extra == "render"
Dynamic: license-file

# abstract_identity

Identity pipeline for hugpy, merged from the former standalone `char360` and
`identity-render` dists into one src-layout package with two subpackages:

| Subpackage | What it is |
| --- | --- |
| `abstract_identity.char360` | Video → per-character 360° view sets: scenes → person detect+track (YOLO) → face embed+pose (insightface) → identity cluster (agglomerative) → yaw-bin (12×30°) → best-per-bin crops + `manifest.json`. Library + CLI (`char360` console script / `python -m char360`). |
| `abstract_identity.render` | The identity-render GPU service (`identity-render` console script): reference photos → Hunyuan3D-2mv mesh (+ headless-Blender turntable), plus the char360-powered `video_extract` and `video_characters_glb` job kinds, behind a tokened Flask job API on :9750. |

## Install

Base (any box — coordinator, dev VM, CI):

```bash
pip install abstract_identity
```

Base is deliberately thin and wheels-only: `flask` + `pydantic`, nothing else.
Every module still imports cleanly with no heavy deps present — heavy imports
are lazy, inside the stage/job that needs them — so the service can boot
anywhere and honestly report capabilities as not-ready.

ae render host (GPU box): run the installer instead of pip —

```bash
bash /srv/share/projects/hugpy/dev/py/abstract_identity/install/install_identity_render_ae.sh \
  --token <TOKEN>
```

It is idempotent (safe to re-run), refuses to run without `--token` or as
root, and sets up: CUDA torch, the Hunyuan3D-2 checkout + weights, rembg,
portable Blender 4.2, the char360 heavy deps, an editable install of this
package into the venv, and the `identity-render.service` systemd **user**
unit (`ExecStart=venv/bin/python -m abstract_identity.render.service`). See
the script header and its `PASS:`/`FAIL:`/`NOTE:` output for details. One-time
firewall opening on ae (verified 2026-07-14):

```bash
sudo ufw allow from 192.168.1.0/24 to any port 9750 proto tcp comment 'identity-render (hugpy central relay)'
```

## Why the heavy deps are an extra, not base

`pip install abstract_identity[render]` pulls the char360 detection stack:
`scenedetect[opencv]`, `ultralytics`, `insightface`, `onnxruntime-gpu==1.18.1`,
`opencv-python`, `numpy`, `scikit-learn`. They are not in base because they are

- **heavy/native/CUDA** — pointless on a coordinator box, and
- **restrictively licensed** — `ultralytics` is AGPL-3.0 (a deployed
  combination is an AGPL combined work) and the insightface pretrained packs
  (`buffalo_l`) are non-commercial research only. See the THIRD-PARTY
  OBLIGATIONS NOTICE in `LICENSE` before any commercial use or redistribution.

**Hunyuan3D-2 is never a pip dep** at all (restrictive Tencent community
license — excludes EU/UK/South Korea including outputs). It is installed
out-of-band, only on the render box, by
`install/install_identity_render_ae.sh` (git checkout + `pip install -e` +
weight pre-download); the code only reaches `hy3dgen` lazily inside a running
mesh job. Same for torch, trimesh, and Blender.

## Compat shims

The old import paths keep working — the wheel ships thin `char360` and
`identity_render` shim packages that re-export from their new homes:

```python
import char360                      # -> abstract_identity.char360
from char360.pipeline import run_char360
import identity_render              # -> abstract_identity.render
from identity_render.jobstate import STAGE_DONE
python -m char360.cli <video> -o <outdir>
python -m identity_render.service   # old systemd ExecStart still boots
```

New code should import `abstract_identity.char360` / `abstract_identity.render`
directly. The log-capture contract is unchanged: service log records still
flow through the literal `"identity_render"` logger name.

## Service API (summary)

Every request, `/health` included, requires `X-Identity-Render-Token: <TOKEN>`
(401 otherwise). Jobs run one at a time (single GPU, single worker thread).

| Method | Path | What |
|---|---|---|
| GET | `/health` | Service + honest capability report |
| POST | `/jobs` | Queue a job (`mesh_build`, `turntable`, `mesh_and_turntable`, `video_extract`, `video_characters_glb`); returns `202 {"job_id": ...}` |
| GET | `/jobs/<job_id>` | `{job_id, status, error?, files?}` |
| GET | `/jobs/<job_id>/files/<name>` | Fetch an artifact's bytes |
| DELETE | `/jobs/<job_id>` | Best-effort cleanup of a job's files |

Artifacts land under `$IDENTITY_RENDER_HOME/<job_id>/`; nothing is cleaned up
automatically. Env vars (`IDENTITY_RENDER_TOKEN/PORT/HOME`, `BLENDER_BIN`,
`FFMPEG_BIN`, `HUNYUAN3D_*`, `HF_HOME`, ...) are written to
`~/identity-render/env` by the installer. Background removal
(`mesh_params.remove_background`) is ON by default; originals are never
modified.

On ae: `systemctl --user status identity-render.service`,
`journalctl --user -u identity-render.service -f`. Code-only update: re-run
the installer (editable install — a restart alone picks up share changes),
then `systemctl --user restart identity-render.service`.

## char360 CLI

```bash
char360 <video> -o <outdir> [--stride 8] [--yolo yolov8m.pt] \
    [--min-h-frac 0.15] [--cluster-dist 0.55] [--min-faces 4]
```

Output: `<outdir>/manifest.json` + `char_NN/view_MM_yaw±DDD.png` crops (bin 0
frontal, 30° bins CCW; rear bins are `yaw_source=rear_inferred` via
track-level identity propagation). Missing heavy deps fail loud at stage-run
time with a `pip install` hint, never at import time.

## Tests

```bash
python -m pytest tests/ -q     # or: python -m unittest discover tests
```

The suite never imports cv2/torch/insightface/sklearn/scenedetect — heavy
stages are mocked — so it runs on a base install (plus numpy for the pipeline
test's fixtures).

## Publishing

```bash
cd py/abstract_identity
python -m build          # sdist + wheel
twine upload dist/*      # public PyPI
```

Order matters: publish `abstract_identity` **before** publishing
`abstract_hugpy_dev` 0.1.234, which now base-depends on
`abstract_identity>=0.1.0`. Version is single-sourced from
`src/abstract_identity/__init__.py:__version__` — bump it there.
