Metadata-Version: 2.4
Name: stapel-recordings
Version: 0.19.0
Summary: Recording lifecycle and transcription for the Stapel framework
License: MIT
Project-URL: Homepage, https://github.com/usestapel/stapel-recordings
Project-URL: Repository, https://github.com/usestapel/stapel-recordings
Project-URL: Documentation, https://github.com/usestapel/stapel-recordings#readme
Project-URL: Changelog, https://github.com/usestapel/stapel-recordings/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/usestapel/stapel-recordings/issues
Keywords: django,stapel,recordings
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: Django
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: stapel-core<1.0,>=0.26.0
Provides-Extra: s3
Requires-Dist: boto3>=1.34; extra == "s3"
Provides-Extra: vector
Requires-Dist: pgvector>=0.3; extra == "vector"
Provides-Extra: qa
Requires-Dist: stapel-recordings[vector]; extra == "qa"
Requires-Dist: stapel-agent>=0.12.0; extra == "qa"
Provides-Extra: all
Requires-Dist: stapel-recordings[qa,s3,vector]; extra == "all"
Dynamic: license-file

<!-- Generated by stapel-readme from docs/readme.md + docs/*.json. Do not edit this file; edit docs/readme.md and re-run `make readme`. -->

# stapel-recordings

[![CI](https://img.shields.io/github/actions/workflow/status/usestapel/stapel-recordings/ci.yml?branch=main&logo=github&label=CI)](https://github.com/usestapel/stapel-recordings/actions/workflows/ci.yml?query=branch%3Amain)
[![coverage](https://img.shields.io/codecov/c/github/usestapel/stapel-recordings?branch=main&logo=codecov&label=coverage)](https://app.codecov.io/gh/usestapel/stapel-recordings)
[![pypi](https://img.shields.io/pypi/v/stapel-recordings?logo=pypi&logoColor=white&label=pypi)](https://pypi.org/project/stapel-recordings/)
[![downloads](https://static.pepy.tech/badge/stapel-recordings/month)](https://pepy.tech/project/stapel-recordings)
[![python](https://img.shields.io/pypi/pyversions/stapel-recordings?logo=python&logoColor=white)](https://pypi.org/project/stapel-recordings/)
[![license](https://img.shields.io/github/license/usestapel/stapel-recordings)](https://github.com/usestapel/stapel-recordings/blob/main/LICENSE)
[![llms.txt](https://img.shields.io/badge/llms.txt-blue)](https://github.com/usestapel/stapel-recordings/blob/main/docs/llms.txt)

> Recording lifecycle: audio/video upload (presigned single-PUT and multipart), storage, a configurable processing pipeline (convert, transcribe, diarize, merge) producing a unified speaker-attributed transcript, optional automatic summaries, and a watchdog that recovers stuck or abandoned recordings.

Part of the [Stapel framework](https://github.com/usestapel) — composable Django apps that deploy as a monolith or as microservices without changing module code.

## Install

```bash
pip install stapel-recordings
```

## At a glance

| Fact | Value |
|---|---|
| Version | `0.19.0` |
| Python | `>=3.11` (3.11, 3.12, 3.13, 3.14) |
| HTTP operations | 10 |
| Config axes | 1 |
| Usage surface | 40 |
| Extension points | 7 |
| Error codes | 59 |
| Fleet dependencies | [`stapel-agent`](https://github.com/usestapel/stapel-agent) (optional) · [`stapel-auth`](https://github.com/usestapel/stapel-auth) (optional) · [`stapel-core`](https://github.com/usestapel/stapel-core) |

## Documentation

[OpenAPI](https://github.com/usestapel/stapel-recordings/blob/main/docs/schema.json) · [capabilities.json](https://github.com/usestapel/stapel-recordings/blob/main/docs/capabilities.json) · [llms.txt (for agents)](https://github.com/usestapel/stapel-recordings/blob/main/docs/llms.txt)

## What this is

Owns the lifecycle **capture/upload → storage → transcribe → summarize**:
`Recording` + `Speaker` + `Segment` (the unified transcript), presigned /
multipart upload sessions, and a data-driven, outbox-backed processing
pipeline with retry, DLQ and reconcile.

Speech-to-text and summarization are **delegated to
[stapel-agent](https://github.com/usestapel/stapel-agent)** via the
`llm.transcribe` / `llm.summarize` comm Functions — this module does not
implement STT or LLM calls. Object storage goes through a swappable seam.

## Quick start

The base install uses the Django-storage backend; add the `s3` extra for the
boto3 S3/MinIO backend:

```bash
pip install "stapel-recordings[s3]"
```

```python
INSTALLED_APPS = [
    # ...
    "stapel_core.django.outbox",   # transactional outbox (pipeline reliability)
    "stapel_recordings",
]

# urls.py
path("recordings/", include("stapel_recordings.urls"))
```

The `transcribe` / `merge` stages call stapel-agent by comm name — install
and configure stapel-agent (or provide `llm.transcribe` / `llm.summarize`
providers) for the pipeline to complete. The default `convert` stage needs
`ffmpeg`/`ffprobe` on PATH (or set `NORMALIZER` to `passthrough_normalize`).

## The pipeline is data you can edit

```python
STAPEL_RECORDINGS = {
    # Reorder / subset / insert stages — no fork:
    "PIPELINE": ["convert", "transcribe", "redact_pii", "merge"],
    # Replace or add stage handlers (merge-over-builtins; None removes):
    "STAGES": {"diarize": "myproject.stages.PyannoteDiarizer"},
    # Or source the list at runtime (DB / per-workspace / per-recording):
    "PIPELINE_RESOLVER": "myproject.pipelines.resolve",
    # Swap the object store:
    "STORAGE": "stapel_recordings.storage.S3Backend",
}
```

A generic driver runs the resolved stage list, advancing the status machine
and emitting the next stage through the outbox. See
[MODULE.md](https://github.com/usestapel/stapel-recordings/blob/main/MODULE.md)
for the stage contract and worked examples.

## Settings

All configuration lives in the `STAPEL_RECORDINGS` namespace (dict setting,
flat setting, or env var — resolved lazily). See the full table in
[MODULE.md](https://github.com/usestapel/stapel-recordings/blob/main/MODULE.md).
Highlights: `PIPELINE`, `STAGES`, `PIPELINE_RESOLVER`, `STORAGE`,
`NORMALIZER`, `SUMMARIZE_ENABLED`, `MAX_STAGE_RETRIES`.

## comm surface

| Kind | Name | Contract |
|---|---|---|
| Action (emit) | `recording.uploaded`, `recording.stage_completed`, `recording.completed`, `recording.failed` | pipeline lifecycle (public); the run events carry `run_id` + `attempt` — a reprocess is a new run, so meter on `recording_id` + `run_id` |
| Action (consume) | `recording.uploaded`, `recording.stage`, `user.deleted` | driver + GDPR erase |
| Function (call) | `llm.transcribe`, `llm.summarize` | provided by stapel-agent |

## Operations

```bash
python manage.py recordings_reconcile --once   # re-drive stuck recordings
```

## Development

```bash
pip install -e . && pip install pytest pytest-django ruff jsonschema djangorestframework
./setup-hooks.sh
pytest tests/
```

## License

MIT — see [LICENSE](https://github.com/usestapel/stapel-recordings/blob/main/LICENSE).

---

<sub>This page is assembled by `stapel-readme` from `docs/readme.md` plus the contract artifacts in `docs/`. Edit the prose in `docs/readme.md`; the badges, facts and links above and below it are generated — do not hand-edit `README.md`.</sub>
