Metadata-Version: 2.4
Name: abstract_identity
Version: 0.1.2
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
Project-URL: Homepage, https://github.com/AbstractEndeavors/abstract-identity
Project-URL: Repository, https://github.com/AbstractEndeavors/abstract-identity
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 abstract_identity.char360.cli`). |
| `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.

Optional render dependencies can be installed with:

```sh
python -m pip install 'abstract_identity[render]'
```

Model weights and GPU/native runtimes need their own compatible installation.
The optional extra alone does not establish renderer readiness. See the
third-party notices in `LICENSE` and the package's installer scripts before
redistributing model assets or native components.

## 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.

## Import paths and commands

Use `abstract_identity.char360` and `abstract_identity.render` directly:

```python
from abstract_identity.char360.pipeline import run_char360
from abstract_identity.render.jobstate import STAGE_DONE
```

```bash
python -m abstract_identity.char360.cli <video> -o <outdir>
python -m abstract_identity.render.service
```

The `char360` and `identity-render` console scripts remain available.
Service log records flow through the `"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).

## Source organization

`abstract_identity/imports` owns the shared boundary, following hugpy-discovery:

- `init_imports.py` declares standard-library, external, and internal package imports.
  Symbols resolve on request; optional GPU imports stay inside the jobs that use them.
- `constants.py` owns fixed pipeline/service constants and environment defaults.
- `functions/` owns general file utilities and service configuration reading.

Section modules import dependencies through that boundary. Geometry/scoring,
character extraction stages, rendering, and job state remain in their respective
sections. Queues, locks, backend instances, and active job state remain with their
owning service modules. Service settings are read at boot rather than when the
boundary is imported.

Blender executes its scripts by file path in a separate Python environment. Their
small `sys`/`pathlib` bootstrap exposes the source package before resolving all
remaining imports through the boundary.
