paces 0.0.3__tar.gz → 0.0.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. paces-0.0.3/README.md → paces-0.0.5/PKG-INFO +46 -0
  2. paces-0.0.3/PKG-INFO → paces-0.0.5/README.md +12 -26
  3. {paces-0.0.3 → paces-0.0.5}/paces/__init__.py +22 -0
  4. paces-0.0.5/paces/derivation.py +957 -0
  5. paces-0.0.5/paces/measure.py +322 -0
  6. {paces-0.0.3 → paces-0.0.5}/paces/model.py +41 -3
  7. {paces-0.0.3 → paces-0.0.5}/paces/projection.py +2 -3
  8. {paces-0.0.3 → paces-0.0.5}/paces/render.py +42 -1
  9. {paces-0.0.3 → paces-0.0.5}/paces/segmenters.py +6 -0
  10. {paces-0.0.3 → paces-0.0.5}/paces/tools.py +155 -1
  11. {paces-0.0.3 → paces-0.0.5}/pyproject.toml +29 -1
  12. paces-0.0.5/tests/audio_synth.py +74 -0
  13. paces-0.0.5/tests/test_derivation.py +938 -0
  14. paces-0.0.5/tests/test_measure.py +259 -0
  15. paces-0.0.5/tests/test_render_media.py +132 -0
  16. paces-0.0.5/tests/video_synth.py +32 -0
  17. {paces-0.0.3 → paces-0.0.5}/.gitignore +0 -0
  18. {paces-0.0.3 → paces-0.0.5}/LICENSE +0 -0
  19. {paces-0.0.3 → paces-0.0.5}/docs/README.md +0 -0
  20. {paces-0.0.3 → paces-0.0.5}/docs/alignment/README.md +0 -0
  21. {paces-0.0.3 → paces-0.0.5}/docs/poc-reference/README.md +0 -0
  22. {paces-0.0.3 → paces-0.0.5}/docs/poc-reference/artifacts/clips.json +0 -0
  23. {paces-0.0.3 → paces-0.0.5}/paces/__main__.py +0 -0
  24. {paces-0.0.3 → paces-0.0.5}/paces/edits.py +0 -0
  25. {paces-0.0.3 → paces-0.0.5}/tests/data/routine.json +0 -0
  26. {paces-0.0.3 → paces-0.0.5}/tests/poc_fixture.py +0 -0
  27. {paces-0.0.3 → paces-0.0.5}/tests/test_chapters.py +0 -0
  28. {paces-0.0.3 → paces-0.0.5}/tests/test_edits.py +0 -0
  29. {paces-0.0.3 → paces-0.0.5}/tests/test_roundtrip_poc.py +0 -0
  30. {paces-0.0.3 → paces-0.0.5}/tests/test_segment.py +0 -0
  31. {paces-0.0.3 → paces-0.0.5}/tests/test_smoke.py +0 -0
@@ -1,3 +1,37 @@
1
+ Metadata-Version: 2.5
2
+ Name: paces
3
+ Version: 0.0.5
4
+ Summary: Turn instructional media into structured, interactive learning material
5
+ Project-URL: Homepage, https://github.com/thorwhalen/paces
6
+ Project-URL: Repository, https://github.com/thorwhalen/paces
7
+ Project-URL: Documentation, https://thorwhalen.github.io/paces
8
+ Author: Thor Whalen
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: dance,instructional-video,learning-material,practice,segmentation,steps,tutorial
12
+ Requires-Python: >=3.10
13
+ Requires-Dist: pydantic>=2.6
14
+ Provides-Extra: audio
15
+ Requires-Dist: audioop-lts; (python_version >= '3.13') and extra == 'audio'
16
+ Requires-Dist: mixing[audio,beats]>=0.0.36; extra == 'audio'
17
+ Requires-Dist: numba>=0.59; extra == 'audio'
18
+ Provides-Extra: cli
19
+ Requires-Dist: argcomplete>=3; extra == 'cli'
20
+ Requires-Dist: argh>=0.30; extra == 'cli'
21
+ Provides-Extra: dev
22
+ Requires-Dist: argh>=0.30; extra == 'dev'
23
+ Requires-Dist: mixing[audio,beats]>=0.0.39; extra == 'dev'
24
+ Requires-Dist: numba>=0.59; extra == 'dev'
25
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
26
+ Requires-Dist: pytest>=7.0; extra == 'dev'
27
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
28
+ Provides-Extra: docs
29
+ Requires-Dist: sphinx-rtd-theme>=1.0; extra == 'docs'
30
+ Requires-Dist: sphinx>=6.0; extra == 'docs'
31
+ Provides-Extra: media
32
+ Requires-Dist: mixing>=0.0.39; extra == 'media'
33
+ Description-Content-Type: text/markdown
34
+
1
35
  # paces
2
36
 
3
37
  Turn instructional media into structured, interactive learning material.
@@ -47,9 +81,17 @@ Same thing from the shell:
47
81
  ```bash
48
82
  paces segment VIDEO_URL --steps steps.json --grid grid.json --output seg.json
49
83
  paces to-document seg.json --source VIDEO_URL --title "My routine" --output document.json
84
+ paces derive document.json --media routine.mp4 # real loop clips + gifs + posters
50
85
  paces render document.json --output page.html
51
86
  ```
52
87
 
88
+ `derive` (`pip install paces[media]`) cuts a loopable mp4, a palette-quality
89
+ gif and a poster for every excerpt-bearing span, writes them to `media/` next
90
+ to the document, and the practice page embeds them as looping clips. Crop
91
+ recipes persist in a hand-overridable `document.recipes.json` sidecar; the
92
+ `subject_locator=` seam (default: no crop) is where pose-based auto-crop
93
+ plugs in. Design record: `docs/adr/0005-media-derivation.md`.
94
+
53
95
  ## How it thinks
54
96
 
55
97
  **Analysis and rendering are separate phases** with a serialisable document
@@ -75,7 +117,11 @@ content (`OpenQuestion`), and human edits are protected from regeneration
75
117
  |---|---|
76
118
  | cut media into steps | `segment(media, steps=..., grid=...)` → `Segmentation` |
77
119
  | explicit/human boundaries | `segment(media, boundaries=[...], steps=[names])` |
120
+ | use the video's own chapters | `segment(media, metadata=<yt-dlp info.json>)` |
121
+ | measure the grid from the media | `segment(local_media, steps=[(name, counts), ...])` — no grid needed; tempo + structure measured, origin estimated and flagged (`pip install paces[audio]`) |
122
+ | protect edits from regeneration | `apply_edits(doc, patches, by="user:you")` + `merge_regenerated(committed, fresh)` |
78
123
  | the committed artifact | `to_document(seg, ...)` → `StepDocument` |
124
+ | real clips/gifs/posters for the page | `derive_document(doc, media=..., doc_path=...)` / `paces derive` (`pip install paces[media]`) |
79
125
  | a practice page | `render_html(doc)` |
80
126
  | wall-clock times from counts | `resolve(doc)` |
81
127
  | sanity checks | `validate_document(doc)` |
@@ -1,29 +1,3 @@
1
- Metadata-Version: 2.5
2
- Name: paces
3
- Version: 0.0.3
4
- Summary: Turn instructional media into structured, interactive learning material
5
- Project-URL: Homepage, https://github.com/thorwhalen/paces
6
- Project-URL: Repository, https://github.com/thorwhalen/paces
7
- Project-URL: Documentation, https://thorwhalen.github.io/paces
8
- Author: Thor Whalen
9
- License-Expression: MIT
10
- License-File: LICENSE
11
- Keywords: dance,instructional-video,learning-material,practice,segmentation,steps,tutorial
12
- Requires-Python: >=3.10
13
- Requires-Dist: pydantic>=2.6
14
- Provides-Extra: cli
15
- Requires-Dist: argcomplete>=3; extra == 'cli'
16
- Requires-Dist: argh>=0.30; extra == 'cli'
17
- Provides-Extra: dev
18
- Requires-Dist: argh>=0.30; extra == 'dev'
19
- Requires-Dist: pytest-cov>=4.0; extra == 'dev'
20
- Requires-Dist: pytest>=7.0; extra == 'dev'
21
- Requires-Dist: ruff>=0.1.0; extra == 'dev'
22
- Provides-Extra: docs
23
- Requires-Dist: sphinx-rtd-theme>=1.0; extra == 'docs'
24
- Requires-Dist: sphinx>=6.0; extra == 'docs'
25
- Description-Content-Type: text/markdown
26
-
27
1
  # paces
28
2
 
29
3
  Turn instructional media into structured, interactive learning material.
@@ -73,9 +47,17 @@ Same thing from the shell:
73
47
  ```bash
74
48
  paces segment VIDEO_URL --steps steps.json --grid grid.json --output seg.json
75
49
  paces to-document seg.json --source VIDEO_URL --title "My routine" --output document.json
50
+ paces derive document.json --media routine.mp4 # real loop clips + gifs + posters
76
51
  paces render document.json --output page.html
77
52
  ```
78
53
 
54
+ `derive` (`pip install paces[media]`) cuts a loopable mp4, a palette-quality
55
+ gif and a poster for every excerpt-bearing span, writes them to `media/` next
56
+ to the document, and the practice page embeds them as looping clips. Crop
57
+ recipes persist in a hand-overridable `document.recipes.json` sidecar; the
58
+ `subject_locator=` seam (default: no crop) is where pose-based auto-crop
59
+ plugs in. Design record: `docs/adr/0005-media-derivation.md`.
60
+
79
61
  ## How it thinks
80
62
 
81
63
  **Analysis and rendering are separate phases** with a serialisable document
@@ -101,7 +83,11 @@ content (`OpenQuestion`), and human edits are protected from regeneration
101
83
  |---|---|
102
84
  | cut media into steps | `segment(media, steps=..., grid=...)` → `Segmentation` |
103
85
  | explicit/human boundaries | `segment(media, boundaries=[...], steps=[names])` |
86
+ | use the video's own chapters | `segment(media, metadata=<yt-dlp info.json>)` |
87
+ | measure the grid from the media | `segment(local_media, steps=[(name, counts), ...])` — no grid needed; tempo + structure measured, origin estimated and flagged (`pip install paces[audio]`) |
88
+ | protect edits from regeneration | `apply_edits(doc, patches, by="user:you")` + `merge_regenerated(committed, fresh)` |
104
89
  | the committed artifact | `to_document(seg, ...)` → `StepDocument` |
90
+ | real clips/gifs/posters for the page | `derive_document(doc, media=..., doc_path=...)` / `paces derive` (`pip install paces[media]`) |
105
91
  | a practice page | `render_html(doc)` |
106
92
  | wall-clock times from counts | `resolve(doc)` |
107
93
  | sanity checks | `validate_document(doc)` |
@@ -48,7 +48,18 @@ from paces.model import (
48
48
  seconds_per_unit,
49
49
  validate_document,
50
50
  )
51
+ from paces.derivation import (
52
+ DeriveResult,
53
+ DirStore,
54
+ LocateQuery,
55
+ SubjectObservation,
56
+ check_media_requirements,
57
+ derive_document,
58
+ full_frame,
59
+ resolve_crop_box,
60
+ )
51
61
  from paces.edits import apply_edits, merge_regenerated
62
+ from paces.measure import GridMeasurement, measure_grid
52
63
  from paces.projection import to_document
53
64
  from paces.render import render_html
54
65
  from paces.segmenters import (
@@ -87,7 +98,18 @@ __all__ = [
87
98
  "Capability",
88
99
  "register",
89
100
  "capabilities",
101
+ "measure_grid",
102
+ "GridMeasurement",
90
103
  "to_document",
104
+ # media derivation (issue #1, ADR-0005)
105
+ "derive_document",
106
+ "DeriveResult",
107
+ "DirStore",
108
+ "LocateQuery",
109
+ "SubjectObservation",
110
+ "full_frame",
111
+ "resolve_crop_box",
112
+ "check_media_requirements",
91
113
  # editing & regeneration
92
114
  "apply_edits",
93
115
  "merge_regenerated",