All notable changes to MGT-python will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
-
Sound–movement analysis toolkit (#351, #352, #353) — a family of plain-numpy functions ported from the author's ro / stillstanding / Westney / cymbal research pipelines, all importable directly from
musicalgestures:_peaks.pick_peaks— the canonical adaptive peak-picker shared by every detector below._pulse—Cycle,group_strokes,segment_cycles,cycle_table,fit_accelerando,motion_onsets: onset grouping into rhythmic cycles and accelerando fitting._alignment—xcorr_lag,envelope_lag,per_cycle_motion_delta,anchor_and_match,offset_stats,sliding_correlation,envelope_agreement: cross-modal lead/lag and coupling._qom—band_limited_qom,accel_to_speed,group_qom,pose_qom,body_scale,normalized_qom,grid_qom,envelope,bin_series: quantity-of-motion cores, including body-scale (framing-invariant) normalization._audiofeatures—rms_envelope,spectral_flux,spectral_flux_onsets,energy_onsets,t60_backward_decay,attack_spectral_centroid: scipy-only audio features and onsets.motiongram_data()(_motionanalysis) gained anorientation='vertical'|'horizontal'option._posture— 12 posturography/sway-dynamics functions (cop_sway_metrics,stabilogram_diffusion,dfa,sample_entropy, ...)._physio—respiration_rate,spectral_band_fractions._mocap—read_qtm_tsv,compare_modality_envelopes(its owndominant_frequencyis intentionally not re-exported at top level to avoid shadowing_analysis.dominant_frequency)._posetools—extract_pose_landmarks(needs the new optional[pose]extra:pip install musicalgestures[pose]; supports both the legacy MediaPipe Solutions API and the newer Tasks API),midpoint,limb_speed_from_landmarks,impact_events.
See the README's "Sound–Movement Analysis Toolkit" section and the new user guide page for usage; API reference pages were regenerated for all nine new modules.
motiondescriptors()(#210) — higher-level scalar movement descriptors from the quantity-of-motion signal: motion energy (mean squared QoM), motion smoothness (SPARC — spectral arc length, a dimensionless validated smoothness metric), motion entropy (normalised 0–1 Shannon entropy of the QoM magnitude distribution), and spectral descriptors (dominant frequency + spectral centroid from the Hann-windowed QoM power spectrum). Returns anMgFigure(QoM time series + power spectrum) with the scalars and full spectrum in.data, and writes a_motiondescriptors.csv. Hann windowing is the documented default (withwindow='none'for rectangular), answering the windowing question raised in the issue; the dominant frequency and spectral centroid are searched within a movement band (fmin/fmax, default 0.2–10 Hz).
- Lightweight animated GIFs for the video-producing methods (motion, history, motion vectors,
Eulerian magnification, dense/sparse optical flow), a
motiondescriptorsfigure, and a new visual Gallery in the examples page;scripts/generate_example_media.pyregenerates them. README, the video-analysis user guide and the wiki updated formotiondescriptors().
- Accurate frame counts (#242, #239).
get_framecount(fast=True)— used to setMgVideo.length— read the container'snb_framesmetadata, which is unreliable (off by one on many AVIs, absent on WebM); this was the "extra frame after conversion" reported in #239. It now counts demuxed video packets (-count_packets), which matches the true decoded frame count across containers while still avoiding a full decode (it is in fact marginally faster than the old metadata query).fast=Falsestill does the exhaustive decode-and-count. Added a regression test that pinsfast == exactfor AVI/MP4/WebM.
- Faster import (#349):
import musicalgesturesdropped from ~0.65s to ~0.52s by deferringimport numba(it pulls in LLVM). The@jitkernels in_directograms,_impactsand_warpare now compiled lazily on first use. The nested directogram case (directogramcallsmatrix3D_norm) is handled by compiling the inner kernel and rebinding the module global before the outer kernel compiles — the issue that reverted the first attempt. Addstests/test_numba_kernels.pyto pin the deferral and nested-jit behaviour. - Also added the missing parameter type hints to
mg_warp_audiovisual_beats(a follow-on to #345).
- Parameter type hints across the public API (#345). Every public analysis method now
annotates its parameters (not just its return type): the motion methods, motiongrams/
motionvideo/motiondata/motionplots, optical flow (
Flow.dense/sparseand the velocity helpers), pose (pose,pose_waterfall/segments/center/distance), the space-time visualisations, directograms/impacts, SSM, cropping, heatmap, history, videograms, the audio methods and the audio–movement suite, plus the public_utilshelpers and theMgVideoinline methods. Modules now usefrom __future__ import annotationsso hints are lazy (no runtime/import-speed cost) and use modernstr | Nonesyntax. Combined with thepy.typedmarker shipped in 1.6.4, downstream IDEs and type checkers now see a fully-typed public API.
- Fixed the CI mypy step (#345), which was aborting on a third-party file (
tifffileships 3.12-only syntax, fatal on our 3.10 target) before it ever checked our code. Settings are now centralised in[tool.mypy](follow_imports=skip, exclude deprecated/3rdparty) and shared by CI andnox -s typecheck. The step stays non-blocking while the internal-typing backlog is worked through (#350).
- Cached average-frame decode for the space-time analyses (#347).
stroboscope,silhouette_waterfallandspacetime_volumeall reconstruct the same average background frame by decoding the whole video; this is now computed once and cached perMgVideo(keyed by filename, invalidated when it changes), so chained space-time calls reuse it instead of re-decoding. Joins the existing derived-signal caches (quantity-of-motion, audio envelope). Full raw-frame shared decoding is intentionally avoided — caching the decoded frame stack is too memory-heavy for typical videos (>1 GB), so only small derived signals are cached.
1.6.4 – 2026-06-28
- Type hints +
py.typed— theMgVideo/MgAudio/MgImage/MgFigureconstructors are typed and ~45 public methods now declare their return types (the audio suite, space-time visualisations, the audio–movement reports, motion/pose/flow/ssm/videograms, etc.). Apy.typedmarker is shipped (PEP 561) so the hints are consumed by downstream type checkers. (Parameter annotations and stricter CI mypy remain an ongoing follow-up — see #345.)
- Extended the
resolve_filename()output-path helper (1.6.3) to the remaining single-target methods: the space-time visualisations, the audio–movement reports,beat_statistics/tempo_similarity, bothvideogramspasses,history/history_cv2,pixelarray/pixelarray_cv2, andflow.dense/flow.sparse/the velocity plot (#344). ~38 sites total now use the shared helper, removing the copy-pastetarget_name/overwritebug class for all standard single-target outputs.
1.6.3 – 2026-06-27
- Faster import:
import musicalgesturesdropped from ~1.5s to ~0.7s by lazy-loading heavy dependencies (scipy.signal,scipy.stats,IPython.display) that are only needed by specific methods. - Pose model download now uses Python's
urllibinstead of a bundled Windowswget.exeand platform-specific shell scripts — removes the 3.8 MB binary from the wheel and is fully cross-platform.
- Added a
resolve_filename()helper that centralises thetarget_name/overwriteoutput-path logic (the pattern whose copy-paste variants caused the earliergrid()/blend()bugs); adopted it across the single-output video methods and allMgAudiomethods. - Added regression tests for the audio–movement suite,
resample(), the pose renderers, and the core-class conveniences (353 → 371 tests).
1.6.2 – 2026-06-27
pose()defaults to the MediaPipe backend (the optional[pose]extra). On installs without MediaPipe it now falls back to the OpenPosebody_25backend (with a clear message) instead of raising, sopose()works out of the box. (This also fixes the CI test jobs.)- Several result attributes shadowed their own methods on the instance, so a second call failed:
tempo_similarity,phase_synchrony,structure_comparison,body_audio_coupling,dynamics_coupling(now stored as*_figure) and the warp result (nowself.warp_video). blend()ignored itsfilenameargument (it always readself.filename).grid()ignored itstarget_nameargument (it always wrote<input>_grid.png).- Corrected stale
overwritedocstrings (now defaultTrue), documented the previously undocumentedconvertparameter ondirectograms/impacts/history_cv2, and fixed several quickstart errors (invalidscale=example;_motiondata.csv/_descriptors.csv/.avinames).
- Informative
reprforMgVideo(frames, fps, size, audio) andMgAudio. MgVideo.duration(seconds) andMgVideo.n_framesproperties, andMgAudio.duration— clearing up thelengthfootgun (frame count for video vs seconds for audio).MgImage.save(path)andMgFigure.save(path)to copy/save a result to a chosen location.- Documentation: an optional-dependency/extras matrix, core-class conveniences, a "Which method
should I use?" disambiguation table, and
pose_center()/pose_distance()with examples + images.
1.6.1 – 2026-06-27
pose_center()— centre the pose data on its global centroid (a 2D port of the MoCap Toolboxmccenter); plots the centred trajectories and saves a CSV of centred coordinates.pose_distance()— per-marker cumulative distance travelled plus the across-marker average (a 2D port ofmccumdist); plots cumulative curves + a ranked total-per-marker bar chart and saves a CSV.
- Consolidated the audio–movement material into a dedicated Audio-Video Processing & Analysis
documentation page; the docs module was renamed accordingly (the public
warp_audiovisual_beats()method is unchanged).
- Cache the movement quantity-of-motion and audio onset/RMS envelopes per
MgVideo, so running several audio–movement analyses in a row no longer re-decodes the same video/audio (~6× faster on subsequent calls). - Removed ~26 MB of generated test artifacts that had been committed under
musicalgestures/examples/(and added.gitignorerules to keep them out); de-duplicated the pose-keypoint cache fallback across thepose_*methods; surfaced CSV-save errors as warnings.
1.6.0 – 2026-06-27
- Audio–movement analysis suite for comparing a single performer's sound and motion:
tempo_similarity()— audio tempo vs movement tempo (ratio, nearest harmonic, cross-correlation peak/lag, zero-lag correlation), with a CSV.phase_synchrony()— phase-locking value (PLV) between the audio and movement rhythm, with a polar phase-difference histogram.structure_comparison()— audio self-similarity (MFCC) vs movement self-similarity (frame appearance) plus a difference map and structural-agreement score.body_audio_coupling()— correlates each pose marker's speed with the audio onset envelope; body map + ranked bar chart + CSV.dynamics_coupling()— audio loudness (RMS) vs quantity of motion, zero/best-lag correlation.
pose_segments()— circular (polar rose) motion plots and per-segment circular statistics (mean angle, resultant length R, circular std, range of motion, mean angular speed) + CSV.resample(fps=…, speed=…, skip=…)— retime an already-loaded video and return a new MgVideo: duration-preserving frame-rate change, playback-speed factor (audio kept in sync), and/or integer frame decimation.pose_waterfall(style=…)gained'markers','skeleton', and'both'styles (in addition to'trajectories'), plusaxes=False(clean render) andcrop=True(trim to the data).silhouette_waterfall()gainedaxes=Falseandcrop=True.
pose(background='white')now also makes the trajectories image white (the trajectory background follows the posebackground); usetrajectory_backgroundto override.
- Removed the white frame around the average-pose image (it now fills edge-to-edge).
pose_waterfall(crop=True)no longer leaves a large empty margin (the 3D axes fills the figure and the data cube is zoomed), including withaxes=False.
1.5.0 – 2026-06-27
- Motiongram/videogram output filenames now use direction-of-movement suffixes:
_mgh/_vgh(horizontal) and_mgv/_vgv(vertical), replacing the axis-based_mgy/_vgyand_mgx/_vgx. Applied tomotion(),motiongrams(),videograms(),motion_mp(), and thessm()intermediates. Theshow(key=...)keys ('horizontal'/'vertical',mgh/mgv/vgh/vgv, and the legacymgx/mgy/vgx/vgy) all still resolve correctly.
silhouette_waterfall()andpose_waterfall()acceptaxes=Falseto render without any axes, ticks, labels, panes, or title (a clean 3D image).
1.4.9 – 2026-06-27
pose_waterfall(style=...): new'markers','skeleton', and'both'styles that draw the pose atn_samplestime slices (colour-by-time by default), in addition to the existing'trajectories'style.pose(trajectory_background=...): choose the trajectories-image background —'black','white', or'transparent'(legacytransparent_trajectoriesstill honoured).- Orientation aliases for
show(key=...):mgh/vgh(horizontal) andmgv/vgv(vertical).
overwritenow defaults toTruefor all functions: outputs are overwritten in place instead of auto-incrementing the filename. Passoverwrite=Falsefor the old behaviour.MgVideo.beat_statistics()now defaults tosource='motion'(analyses the movement rhythm), so it differs fromvideo.audio.beat_statistics(). Usesource='audio'for the audio track.pose():convertdefaults toNone("auto") — MediaPipe reads the source directly (no intermediate AVI), OpenPose still converts for frame-accurate decoding. The result video is written in the original container (mp4 in → mp4 out; no avi→mp4 round-trip).- Pose images decluttered: removed the titles from the trajectories and waterfall images and
the average-pose image, and removed the average-pose colorbar. The trajectories image omits
marker-name labels by default (
trajectory_labels=Trueto re-enable).
- The
show(key=...)orientation keys for motiongrams/videograms were swapped:'horizontal'now selects the horizontal-movement gram and'vertical'the vertical one, with correct titles (in bothMgVideo.showandMgList.show).
1.4.8 – 2026-06-27
pose_waterfall(): a 3D spatio-temporal waterfall where each marker's trajectory flows through (x, time, y) space — a pose-based counterpart tosilhouette_waterfall(). Reuses cached pose keypoints when available;color_by='marker'/'time', marker subsets supported.pose(marker_history=N): draw a motion trail for each marker over the last N frames (works in the OpenPose, MediaPipe, and cached re-render paths).pose(trajectory_labels=True): re-enable per-marker name labels on the trajectories image.
pose()now defaults to the MediaPipe backend instead of OpenPosebody_25. MediaPipe is fast on plain CPU, needs no CUDA-enabled OpenCV build, and gives 33 landmarks with depth + visibility. The OpenPose models (body_25/coco/mpi) remain available for multi-person scenes and CUDA setups.pose(overlay=False, background='white')now draws a black skeleton and markers (a print-friendly inverted look) instead of the previous dark-blue/dark-red scheme.- The marker-trajectories image no longer shows per-marker name labels by default.
tempogram(): added a colorbar (matching the chromagram), shows the estimated tempo rounded to one decimal with "BPM" in the title, and removed the dotted estimated-tempo line.videograms()/motiongrams()display keys are now'horizontal'/'vertical'.
motionhistory():normalizenow defaults toFalseand is guarded so it no longer amplifies faint residual trails into a washed-out ("blown up") image when the final frames are static.- Documentation: refreshed the docs site, wiki, and READMEs for the MediaPipe default and the
new pose options; updated the stale
releases.mdpage (was pinned to an old version) to track the changelog.
1.4.7 – 2026-06-27
- GPU detection:
_utils.pynever importedcv2, soget_cuda_device_count()andcuda_build_available()always reported no CUDA — GPU was never used even with a CUDA-enabled OpenCV. Now fixed:pose(device='gpu')(OpenPose),flow.dense(use_gpu=True), andflow.sparse(use_gpu=True)use the GPU on a CUDA build. - GPU sparse optical flow: corrected point shapes (1×N CV_32FC2) and
calc()return handling so the CUDA path works (it was never exercised before the detection fix). MgList.show(key='mgx'/'vgx'/…)on motiongrams/videograms results no longer crashes — it selects the matching panel.- CI on macOS/Windows: skip
.oggconversion tests when the FFmpeg build lacks libtheora; force the Matplotlib Agg backend in tests (no more Windows_tkintercrash). - Audio cache: methods inherited by
MgVideo(e.g.video.spectrogram()) no longer fail on a missing_y_cacheattribute.
pose(use_cache=True): reuse cached keypoints to re-render a differentstyle/overlay/backgroundwithout re-running inference.pose(data_format='c3d'): export markers to a C3D motion-capture file (optionalc3ddep).tempogram(onset_strength=False): single-panel tempogram matching the chromagram size.beat_statistics(source='motion')onMgVideo: rhythmic-timing statistics from movement onsets.
- Average-pose image: labels show numbers only (normalised QoM 0–1 | dominant frequency Hz), with stronger de-overlap; QoM reported normalised instead of px/frame.
motiontempo(): QoM normalised to 0–1, panel renamed to "Motion spectrum", with average quantity-of-motion and average beat-frequency lines + numbers.
1.4.6 – 2026-06-27
- Space-time person visualisations (
musicalgestures/_spacetime.py):stroboscope()(chronophotography),silhouette_waterfall(),motionhistory()(Motion History Image), andspacetime_volume()(3D x,y,t silhouette point cloud). Silhouettes use MediaPipe selfie segmentation when available, falling back to background subtraction (method='auto'|'mediapipe'|'bgsub'). ssm(features='motiongrams', combine=True)— a single self-similarity matrix from the concatenated horizontal + vertical motiongram features (both axes of motion in one display).pose()stylenow also applies to the average-pose image (markers/skeleton/both).
pose(): the no-CUDA fallback now uses the MediaPipe CPU (XNNPACK) delegate (fast, reliable) rather than the fragile OpenGL-ES GPU delegate. Newquiet=Truesuppresses MediaPipe's native C++/GL console logs; explicitdevice='gpu'prints a one-line caveat.
- Orientation: portrait/phone videos that store a rotation flag are now normalised at load (the rotation is baked into the pixels and the flag removed), so cv2-based processes no longer come out rotated 90°. All processes keep the original orientation.
1.4.5 – 2026-06-26
pose()now also exports an average-pose image (each marker coloured/labelled by its average quantity of motion in px/frame and dominant movement frequency in Hz, with a per-marker stats CSV) and an all-trajectories image. Marker labels are laid out to avoid overlapping (with leader lines). Options:save_average_pose,save_trajectories,transparent_trajectories(transparent background, auto-enabled when trajectories are the only export, for overlaying on video).pose()rendering controls:style('both'/'markers'/'skeleton'),overlay(draw on the video or a plain background), andbackground('black'/'white', with contrast-adapted colours).convert=Falseflag onpose(),flow.dense()/flow.sparse(),directograms(),impacts(),motion_mp(), andhistory_cv2()to skip the AVI conversion and read the source (e.g. mp4) directly.
- Display model: analysis results (
MgImage/MgFigure) no longer auto-render as a notebook cell's last expression — display happens only viashow(). HTML is available viato_html().MgList.as_figure()andinfo('frame')updated accordingly (info('frame')returns anMgImage). blur_faces()writes MP4/libx264 (via the FFmpeg pipe) instead of MJPEG-AVI, keeping the source container by default.
MgAudiocaches the decoded audio, so multiple audio analyses decode the file once.ffprobe()results are cached per file (path+mtime+size), so the metadata helpers share a single subprocess call.
- Fixed all "invalid escape sequence"
SyntaxWarnings on import. - Documented that
MgVideo.lengthis a frame count (MgAudio.lengthis seconds). - Removed 30 unused imports.
1.4.4 – 2026-06-26
MgVideo.eulerian()— Eulerian Video Magnification (Wu et al., SIGGRAPH 2012) to reveal subtle changes.mode='color'amplifies subtle colour changes (pulse/breathing) via a Gaussian pyramid + ideal FFT band-pass (two-pass, low memory);mode='motion'amplifies subtle motion via a Laplacian pyramid + streaming IIR band-pass with spatial-wavelength attenuation. Reads/writes through the FFmpeg pipe so any format works, addressing the format/memory limitations of existing PyEVM ports (closes #212).MgVideo.sonomotiongram()— sonifies the motiongram by treating it as a magnitude spectrogram (spatial position → frequency, motion intensity → amplitude) and resynthesising audio via inverse STFT (Griffin–Lim). Returns an MgAudio (closes #171).MgVideo.motionvectors()— visualises the motion vectors carried by inter-frame codecs (MPEG/H.264/H.265) using FFmpeg's codecview filter (closes #254).
- EVM/sonomotiongram timing:
MgVideo.lengthis a frame count (not seconds), so audio duration is computed aslength/fpsand progress is tracked in frames.
1.4.3 – 2026-06-26
MgVideo.heatmap(): a motion heatmap showing which parts of the video change the most (accumulated frame differences, colour-mapped, optionally overlaid on the average frame).MgVideo.motiontempo(): estimates the dominant movement tempo from the quantity of motion via FFT, reported in Hz and BPM (addresses #158).descriptors(save_data=True, data_format=...): save the per-frame audio descriptor time series to csv/tsv/txt, mirroring motiondata (closes #124).pose()GPU via MediaPipe:MediaPipePoseEstimatorgains adeviceparameter and uses MediaPipe's GPU delegate (CPU fallback). Whendevice='gpu'is requested for an OpenPose model but OpenCV lacks CUDA,pose()auto-switches to the MediaPipe backend so the GPU is actually used.cuda_build_available()andcuda_unavailable_reason()helpers.
- Display model:
MgImage/MgFigureno longer auto-render as a notebook cell's last expression (the rich_repr_html_/_repr_mimebundle_hooks were removed; the HTML helper is kept asto_html()). Display now happens only viashow(), removing the duplicate (small + large) outputs for the audio figure methods and makingaverage()display only whenshow()is called. - Audio figure methods always close the pyplot figure after saving.
MgFigure.show()renders the saved image (inline in notebooks).- GPU-fallback messages in
pose(), optical flow, and CenterFace now explain the real cause (pip OpenCV is built without CUDA) instead of implying a missing GPU.
spectrogram()/descriptors(): pin the time axis to the actual spectrogram extent so a container duration longer than the decoded audio no longer leaves trailing whitespace or mislabels the timeline.
1.4.2 – 2026-06-26
- Critical: repaired a
thresholdoldcorruption (from a botchedthresh→thresholdreplace) that broke the FFmpegthresholdfilter, leavingmotion(),motiongrams()and related functions producing no frames and crashing. Motion analysis works again. skipwith large values no longer crashes:atempofilters are chained for ratios above FFmpeg's per-filter limit of 100, and colons are stripped from output filenames.- Restored consistent behaviour of the threshold/filtertype options in
motiongrams().
info(type='summary')now reports video codec/profile, pixel format, color space, and audio codec/sample-rate/bit-rate alongside resolution, frames, fps, and duration.audio.mfcc(),audio.tempo()(beat tracking with tempo, beat times, inter-beat intervals and beat regularity), andaudio.beat_statistics()(circular timing analysis).musicalgestures/_analysis.py: general signal/statistics utilities (smooth,bandpass,dominant_frequency,circular_stats,rayleigh_test,synchrony), exported at package level.
1.4.1 – 2026-06-26
average()now correctly ignores bothmethod=andnormalize=legacy kwargs (1.4.0 only filterednormalize=).- Rename
cols→columnsparameter inmg_grid. - Added
audio.chromagram()method.
1.4.0 – 2026-06-26
- Migrated project metadata and build configuration to
pyproject.toml(PEP 517/518/621).setup.pyandsetup.cfgare now stubs pointing to the new file. - Raised minimum Python version to 3.10; updated CI matrix to test 3.10, 3.11, and 3.12.
- Added a separate
lintCI job (ruff + mypy) to catch style and type issues early. - Added
noxfile.pyfor reproducible local development environments (nox -s tests,nox -s lint,nox -s coverage). - Added optional dependency extras:
musicalgestures[pose],[ml],[cli],[dev],[full]. - Added
musicalgestures/_enums.py:StrEnum-based enum types (FilterType,BlurType,CropMode,PoseModel,PoseDevice,DataFormat) with case-insensitive lookup. Fully backward-compatible with existing string parameters. - Added
musicalgestures/_exceptions.py: typed exception hierarchy (MgError→MgInputError,MgProcessingError,MgIOError,MgDependencyError). - Added
musicalgestures/_logging.py: module-levellogging.getLogger('musicalgestures')logger with aNullHandlerand aset_log_level()helper.
- Added
musicalgestures/_features.py:MgFeatures– a named time-series container for motion and audio descriptors. Supportsto_numpy(),to_dataframe(),to_json(),from_json(),from_dataframe(), NumPy array protocol, and a rich Jupyter_repr_html_display. - Added
musicalgestures/_stream.py:MgVideoReader– a context-manager-based streaming frame iterator (lazy, low-memory, FFmpeg-backed). - Added
_repr_html_()and_repr_mimebundle_()toMgImageandMgFigurefor rich inline display in Jupyter notebooks.
- Added
musicalgestures/_pose_estimator.py: abstractPoseEstimatorbase class,PoseEstimatorResultcontainer,MediaPipePoseEstimator(Google MediaPipe Pose, 33 landmarks, no model download required),OpenPosePoseEstimator(compatibility shim for the legacy OpenPose backend), andget_pose_estimator()factory function.
- Added
musicalgestures/_pipeline.py:MgPipeline– a scikit-learn–style pipeline that chains namedMgStepobjects. Supportstransform(),fit(),fit_transform(), and adescribe()method. - Added
musicalgestures/_dataset.py:MgDataset– labelled collection of media files withfrom_directory(),from_json(),train_test_split(),filter(),to_json(), and Jupyter_repr_html_. Also includesMgCorpus(directory-scanning convenience subclass) andMediaItem.
- Added
CHANGELOG.mdfollowing the Keep-a-Changelog format. - Added
CONTRIBUTING.mdwith a complete developer guide.
- Added
musicalgestures/cli.py: click-based command-line interface (musicalgestures info,motion,videograms,average,history,motiongrams,convert). - Updated
musicalgestures/__init__.pyto export all new public classes (MgFeatures,MgVideoReader,MgPipeline,MgStep,MgDataset,MgCorpus,MediaItem,PoseEstimator,MediaPipePoseEstimator,PoseEstimatorResult,get_pose_estimator, enums, exceptions,set_log_level).
tqdmadded as a core dependency (progress bars in downstream usage).- CI now installs the package from source (
pip install -e ".[dev]") and runspytest. thresholdparameter name is now consistent across all public APIs (previously some paths usedthresh).contrastandbrightnessparameters use integer range −100 to 100 (previously ambiguous).blurparameter only accepts'None'and'Average'(removed undocumented'Medium').
average()method restored as an alias forblend(component_mode='average')(was accidentally removed in a prior refactor).average()silently accepts legacy kwargsmethod=andnormalize=for backward compatibility.motiongrams()andmotion()silently acceptnormalize=kwarg for backward compatibility.- OGG video conversion now explicitly specifies
libtheora/libvorbiscodecs. from_numpy()path bug fixed whenpathattribute is set.- Motiondata fallback corrected for invalid data formats.
- Optical flow video export fixed (replaced broken cv2.VideoWriter with FFmpeg subprocess).
- History feature string-weights parsing fixed.
- Cropping window on Linux no longer stalls on repeated use.
- All examples in
docs/examples.mdupdated to match the current API.
- Python 3.7 and 3.8 are no longer supported. The minimum required version is Python 3.10.
1.3.3 – 2024-01-01
- Minor changes for v1.3.3.