Metadata-Version: 2.4
Name: auvux
Version: 0.1.0a2
Summary: Annotate faster. See deeper. Sound smarter.
Author-email: Auvux <peter@dreamteam.nl>
License: MIT
Project-URL: Homepage, https://inference.auvux.com
Project-URL: Repository, https://github.com/auvux/auvux-py
Project-URL: Issues, https://github.com/auvux/auvux-py/issues
Keywords: webrtc,jupyter,visualization,inference,audio
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Framework :: Jupyter
Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiortc>=1.9.0
Requires-Dist: websockets>=12.0
Requires-Dist: numpy>=1.24
Requires-Dist: soundfile>=0.12
Dynamic: license-file

<p align="center">
  <img src="https://raw.githubusercontent.com/auvux/auvux-py/main/assets/logo.png" alt="auvux" width="120" />
</p>

<h1 align="center">auvux</h1>

<p align="center"><em>Annotate faster. See deeper. Sound smarter.</em></p>

---

Push inference runs from a Python notebook to a browser viewer over WebRTC.

Bytes flow peer-to-peer over a DataChannel; identical bytes across runs
and viewers are deduplicated via per-viewer SHA-256 content addressing.
Auth is GitHub OAuth (`user:email` scope) verified by an HMAC-signed
JWT — your tokens never leave your machine.

## Install

```bash
pip install --pre auvux
```

(`--pre` while we're on the `0.1.0a1` alpha release.)

## Use

```bash
auvux login           # GitHub Device Flow, caches a JWT in ~/.auvux/
auvux whoami          # confirm
```

```python
import auvux
from auvux import lanes, markers

# Same as `auvux login`, but inline. Idempotent — no-op if already
# signed in.
auvux.login()

canvas = auvux.Canvas("Beat Detection")
canvas.add(
    lanes.Waveform.from_path("demo.wav", size=160, label="mix"),
    markers=[markers.vlines(beats, color="#FFFF00")],
)
canvas.add(lanes.Heatmap(spect, yaxis="mel", fmin=30, fmax=11000, size=256))
canvas.add(lanes.line(t, beat_logits, color="#4CAF50", label="beats", fill=True))
canvas.minimap(from_lane=0)
canvas.clicks(beats, freq=800)
canvas.show()                  # opens at https://inference.auvux.com
```

Open `https://inference.auvux.com` in your browser **before** running
`canvas.show()` — the publisher waits up to 60 seconds for at least
one viewer to be present.

`Waveform.from_path()` accepts both local paths and `http(s)://` URLs;
remote files are fetched once into memory and reused without a second
round-trip on emit.

## What gets sent

Each call to `canvas.show()` packages:

- A `manifest.json` describing the lanes and their layout
- Sidecar files: WAV / NPY / NPZ / CSV / JSON, per lane type
- Click-track time lists (if any)

The viewer pre-announces which file hashes it already has, so unchanged
audio across iterations is sent **once** — subsequent runs reuse the
cached blob.

## Auth flow

`auvux.login()` runs the GitHub Device Flow with scope `user:email`:

1. Asks GitHub for a short user code (`XXXX-XXXX`)
2. Opens the browser to the verification URL
3. Polls until you authorise
4. Swaps the GitHub access token for an auvux JWT at
   `https://inference.auvux.com/api/auth/cli-exchange`
5. Caches the JWT in `~/.auvux/credentials.json` (chmod 600)

Subsequent `auvux.login()` calls are no-ops if the cached token is
still valid; pass `force=True` to re-authenticate.

## Environment

| Var | Default | Purpose |
| --- | --- | --- |
| `AUVUX_SIGNALLING_URL` | from `~/.auvux/credentials.json`, otherwise `wss://signalling.auvux.com/signalling/me` | Override the signalling endpoint (escape hatch for local dev) |
| `AUVUX_API_BASE` | `https://inference.auvux.com` | Auvux API host used for `cli-exchange` |
| `AUVUX_GH_CLIENT_ID` | built-in | GitHub OAuth App client id |
| `AUVUX_PEER_WAIT` | `60` | Seconds to wait for a viewer before erroring |
| `AUVUX_ACK_WAIT` | `30` | Seconds to wait per-viewer for delivery ack |

## Development

```bash
git clone https://github.com/auvux/auvux-py
cd auvux-py
pip install -e .
```

Release a new version: bump `version` in `pyproject.toml`, then

```bash
git tag v0.1.0a2
git push --tags
```

The `release.yml` workflow builds the wheel + sdist and publishes to
PyPI via OIDC (Trusted Publisher) — no API token in the repo.

## License

MIT — see [LICENSE](LICENSE).
