Skip to main content

terpsi

Dance corpora from single-dancer videos: body landmarks (no video kept), audio, subtitles, on-screen text, and movement-versus-music analysis. Named for Terpsichore, the muse of dance.

pip install "terpsi[all]"   # mediapipe + opencv, librosa, an OCR backend, yb (yt-dlp); ffmpeg on PATH
terpsi ingest https://youtu.be/q_TUyxUhoEw
terpsi clips

A clip goes in as a URL (YouTube, Wikimedia Commons, anything yt-dlp reads) or a local file, and comes out as a folder under ~/.local/share/terpsi/clips/<clip_id>/ holding what a dance model needs and nothing a video needs: 553 landmarks per frame (33 body + 2×21 hands + 478 face, with metric 3D world coordinates for body and hands, and 52 face blendshapes), the audio stream as the source carried it, the description and metadata, the subtitles, the text that was on screen with its timestamps, a beat grid, and a movement-versus-music report. The video is deleted once extracted.

Python

from terpsi import ingest, Corpus

clip_id = ingest("https://youtu.be/q_TUyxUhoEw")      # download, extract, delete the video
clip = Corpus()[clip_id]
lm = clip.landmarks            # LandmarkSeries: lm.pose (F,33,4), lm.pose_world (F,33,3), lm.hand_left, lm.face, ...
clip.beats["tempo"]            # 129.2
clip.screen_text[:2]           # [{'t_start': 3.0, 't_end': 6.0, 'text': 'Mise en place', ...}, ...]
clip.report["beat_alignment"]  # AIST++ Beat Alignment Score of the body's landings against the music beats

Each stage is a function with one seam, a keyword argument whose default works out of the box:

stage function seam default a replacement that exists
fetch terpsi.acquire.fetch downloader= yb over yt-dlp, with info.json, description, subtitles a local file (passes through)
landmarks terpsi.pose.extract_landmarks extractor= MediaPipe HolisticLandmarker kodokan.pose.estimate_poses (RTMPose, 2D)
on-screen text terpsi.screen_text.read_screen_text ocr= ocracy (ocrmac on macOS, Tesseract elsewhere) any ocracy backend id
beats terpsi.audio.track_beats tracker= librosa's beat tracker + onset envelope a madmom or su tracker with the same signature
storage terpsi.store.Corpus root= ~/.local/share/terpsi/clips any folder, a mounted or synced bucket included (a byte-store backend is the next seam, terpsi#1)

import terpsi needs only numpy, scipy and cw; the heavy dependencies are extras (pose, audio, ocr, acquire) imported on first use.

Choosing clips

terpsi search "house dance tutorial footwork" --n 15          # YouTube, Creative-Commons-filtered by default
terpsi screen https://youtu.be/XXXXXXXXXXX                      # single dancer? whole body? (a pose count on sampled frames)
terpsi ingest-many sources.txt                                  # one URL per line

screen reports the fraction of sampled frames with exactly one body, the fraction where that body is whole (nose and an ankle visible), and the licence yt-dlp found. The licence of record per clip is yt-dlp's license field, stored in the manifest.

The analysis

terpsi.analysis implements the literature's movement-versus-music measures over a LandmarkSeries and a beat grid: motion energy (summed joint speed), kinematic beats (its local minima, AIST++), the Beat Alignment Score in both directions, the phase concentration of the body's landings within the beat cycle (a resultant length), the motion tempo by autocorrelation and its ratio to the music tempo, and the audio-visual lag by onset cross-correlation. terpsi analyze <clip_id> recomputes a clip's report. When YouTube rate-limits the captions endpoint but still serves the video (a 429 on the subtitles alone, common in batches), the clip is ingested without subtitles and its manifest records subtitles_error; terpsi subtitles <clip_id> fetches them into the clip's folder later. The motion-tempo estimate is NaN when the motion has no periodicity (every autocorrelation peak negative). terpsi annotate <ids-or-sources-file> kind=performance,style=krump stores annotations in the manifest (Clip.annotations); when clips carry a kind (tutorial, performance), the report adds a by-kind comparison.

Data layout

~/.local/share/terpsi/clips/<clip_id>/
  manifest.json       id, title, source, licence, duration, fps, coverage, mirrored hint, files
  info.json           yt-dlp's metadata
  description.txt
  subtitles/*.vtt
  audio.m4a           the source audio stream (no re-encode)
  landmarks.npz/.json the LandmarkSeries (NaN where nothing was seen) and its meta
  screen_text.json    [{t_start, t_end, text, lines}]
  beats.json          tempo, beats, onset envelope
  report.json         the movement-vs-music report

$TERPSI_DATA_DIR moves the root. Models (.task files) are fetched once into <root>/models/.

thoremin (the live instrument whose body nodes and pulse follower this corpus is for), paces (step documents from tutorial video), kodokan (pose analysis of judo video), yb, ocracy. Research notes: docs/research/.

Metadata

Release files for terpsi 0.0.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for terpsi 0.0.7
File Size Uploaded Provenance Actions
terpsi-0.0.7.tar.gz 34.5 kB Without provenance Details for terpsi-0.0.7.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for terpsi 0.0.7
File Interpreter ABI Platform Actions
terpsi-0.0.7-py3-none-any.whl Python 3 none any Details for terpsi-0.0.7-py3-none-any.whl

Total release size: 73.6 kB

Release files / terpsi-0.0.7.tar.gz

Download URL terpsi-0.0.7.tar.gz
Size 34.5 kB
Tags Source
SHA-256 checksum
How to use checksums
78a3b4e46acf43f243cfa3680ae0d97e928912982d396e5e476a58bf9127a2b2
BLAKE2b-256 checksum
How to use checksums
c2dc446cd9ff55e5088cfadb48be398bfcb72fa047d1f2e43a324d811a1620e0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / terpsi-0.0.7-py3-none-any.whl

Download URL terpsi-0.0.7-py3-none-any.whl
Size 39.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f27563b383e2224baa2ca15cdda61a59286086b1f5768deb793fed5237265009
BLAKE2b-256 checksum
How to use checksums
85b0fbda7de530458d3795e758c10b824d3343bd08c27ee53402ea5822086009
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for terpsi 0.0.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page