danceflow-stemlab 1.2.0__tar.gz → 1.3.0__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 (162) hide show
  1. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/MANIFEST.in +5 -0
  2. {danceflow_stemlab-1.2.0/src/danceflow_stemlab.egg-info → danceflow_stemlab-1.3.0}/PKG-INFO +185 -5
  3. danceflow_stemlab-1.2.0/PKG-INFO → danceflow_stemlab-1.3.0/README.md +145 -89
  4. danceflow_stemlab-1.3.0/docs/cue-alignment.md +201 -0
  5. danceflow_stemlab-1.3.0/docs/evidence-models.md +109 -0
  6. danceflow_stemlab-1.3.0/docs/midi.md +353 -0
  7. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/mcp-registry/server.json +4 -4
  8. danceflow_stemlab-1.3.0/plugins/stemlab/.codex-plugin/plugin.json +24 -0
  9. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/plugins/stemlab/plugin.json +4 -4
  10. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/plugins/stemlab/skills/stemlab/SKILL.md +29 -0
  11. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/plugins/stemlab/skills/stemlab/references/tools.md +3 -1
  12. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/pyproject.toml +26 -5
  13. danceflow_stemlab-1.3.0/scripts/benchmark_evidence_corpus.py +46 -0
  14. danceflow_stemlab-1.3.0/scripts/smoke_midi.py +44 -0
  15. danceflow_stemlab-1.2.0/README.md → danceflow_stemlab-1.3.0/src/danceflow_stemlab.egg-info/PKG-INFO +269 -3
  16. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/danceflow_stemlab.egg-info/SOURCES.txt +36 -1
  17. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/danceflow_stemlab.egg-info/requires.txt +51 -0
  18. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/__init__.py +1 -1
  19. danceflow_stemlab-1.3.0/src/stemlab/analysis/evidence/__init__.py +4 -0
  20. danceflow_stemlab-1.3.0/src/stemlab/analysis/evidence/adapters.py +230 -0
  21. danceflow_stemlab-1.3.0/src/stemlab/analysis/evidence/registry.py +146 -0
  22. danceflow_stemlab-1.3.0/src/stemlab/analysis/evidence/runner.py +216 -0
  23. danceflow_stemlab-1.3.0/src/stemlab/analysis/evidence/worker.py +35 -0
  24. danceflow_stemlab-1.3.0/src/stemlab/analysis/midi/__init__.py +8 -0
  25. danceflow_stemlab-1.3.0/src/stemlab/analysis/midi/adapters.py +254 -0
  26. danceflow_stemlab-1.3.0/src/stemlab/analysis/midi/artifacts.py +109 -0
  27. danceflow_stemlab-1.3.0/src/stemlab/analysis/midi/registry.py +119 -0
  28. danceflow_stemlab-1.3.0/src/stemlab/analysis/midi/runner.py +238 -0
  29. danceflow_stemlab-1.3.0/src/stemlab/analysis/midi/worker.py +39 -0
  30. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/registry.py +25 -0
  31. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/runner.py +63 -1
  32. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/beats/beatnet.py +16 -3
  33. danceflow_stemlab-1.3.0/src/stemlab/beats/beatthis.py +41 -0
  34. danceflow_stemlab-1.3.0/src/stemlab/bootstrap.py +249 -0
  35. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/branding.py +4 -3
  36. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/canonical.py +5 -12
  37. danceflow_stemlab-1.3.0/src/stemlab/cli.py +452 -0
  38. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/codex/bridge.py +55 -1
  39. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/codex/jobs.py +1 -1
  40. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/codex/server.py +40 -0
  41. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/codex/tasks.py +125 -0
  42. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/codex/worker.py +5 -1
  43. danceflow_stemlab-1.3.0/src/stemlab/cue_cli.py +86 -0
  44. danceflow_stemlab-1.3.0/src/stemlab/cues.py +645 -0
  45. danceflow_stemlab-1.3.0/src/stemlab/lyric_lrc.py +105 -0
  46. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/pipeline.py +79 -2
  47. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/separators/bsroformer.py +27 -0
  48. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/spectrogram.py +57 -27
  49. danceflow_stemlab-1.3.0/src/stemlab/spectrogram_repair.py +86 -0
  50. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/types.py +24 -0
  51. danceflow_stemlab-1.3.0/src/stemlab/word_alignment.py +114 -0
  52. danceflow_stemlab-1.3.0/tests/test_beat_this_bootstrap.py +62 -0
  53. danceflow_stemlab-1.3.0/tests/test_beatnet_bootstrap.py +66 -0
  54. danceflow_stemlab-1.3.0/tests/test_bsroformer_adapter.py +30 -0
  55. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_codex_protocol.py +1 -0
  56. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_codex_release.py +1 -1
  57. danceflow_stemlab-1.3.0/tests/test_cue_integration.py +200 -0
  58. danceflow_stemlab-1.3.0/tests/test_cues.py +370 -0
  59. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_distribution_identity.py +7 -1
  60. danceflow_stemlab-1.3.0/tests/test_docker_contract.py +78 -0
  61. danceflow_stemlab-1.3.0/tests/test_evidence_models.py +126 -0
  62. danceflow_stemlab-1.3.0/tests/test_lyric_lrc.py +75 -0
  63. danceflow_stemlab-1.3.0/tests/test_midi_adapters.py +245 -0
  64. danceflow_stemlab-1.3.0/tests/test_midi_extraction.py +207 -0
  65. danceflow_stemlab-1.3.0/tests/test_midi_integration.py +151 -0
  66. danceflow_stemlab-1.3.0/tests/test_midi_registry.py +52 -0
  67. danceflow_stemlab-1.3.0/tests/test_spectrogram.py +55 -0
  68. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_web_frontend.py +5 -4
  69. danceflow_stemlab-1.3.0/tests/test_word_alignment.py +27 -0
  70. danceflow_stemlab-1.2.0/plugins/stemlab/.codex-plugin/plugin.json +0 -24
  71. danceflow_stemlab-1.2.0/src/stemlab/beats/beatthis.py +0 -25
  72. danceflow_stemlab-1.2.0/src/stemlab/bootstrap.py +0 -133
  73. danceflow_stemlab-1.2.0/src/stemlab/cli.py +0 -230
  74. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/.agents/plugins/marketplace.json +0 -0
  75. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/.github/workflows/codex-plugin.yml +0 -0
  76. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/.github/workflows/release.yml +0 -0
  77. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/LICENSE +0 -0
  78. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/docs/codex-plugin.md +0 -0
  79. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/docs/codex-publishing.md +0 -0
  80. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/plugins/stemlab/.mcp.json +0 -0
  81. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/plugins/stemlab/README.md +0 -0
  82. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/plugins/stemlab/mcp.json +0 -0
  83. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/scripts/build_codex_plugin.py +0 -0
  84. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/scripts/capture_loop_workflow.py +0 -0
  85. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/scripts/check_codex_timeline.py +0 -0
  86. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/scripts/loop_demo.py +0 -0
  87. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/scripts/prepare_codex_marketplace.py +0 -0
  88. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/scripts/publish_mcp_registry.py +0 -0
  89. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/setup.cfg +0 -0
  90. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/danceflow_stemlab.egg-info/dependency_links.txt +0 -0
  91. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/danceflow_stemlab.egg-info/entry_points.txt +0 -0
  92. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/danceflow_stemlab.egg-info/top_level.txt +0 -0
  93. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/__main__.py +0 -0
  94. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/__init__.py +0 -0
  95. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/harmony.py +0 -0
  96. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/loops.py +0 -0
  97. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/lyrics.py +0 -0
  98. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/rhythm.py +0 -0
  99. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/semantic_audio.py +0 -0
  100. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/semantic_text.py +0 -0
  101. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/song_map.py +0 -0
  102. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/sonic.py +0 -0
  103. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/structure.py +0 -0
  104. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/tempo_regimes.py +0 -0
  105. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/analysis/transcription.py +0 -0
  106. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/audio.py +0 -0
  107. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/beats/__init__.py +0 -0
  108. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/beats/base.py +0 -0
  109. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/beats/beattransformer.py +0 -0
  110. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/beats/common.py +0 -0
  111. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/codex/__init__.py +0 -0
  112. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/codex/__main__.py +0 -0
  113. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/codex/paths.py +0 -0
  114. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/codex/timeline.py +0 -0
  115. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/manifest.py +0 -0
  116. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/models.py +0 -0
  117. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/separators/__init__.py +0 -0
  118. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/separators/base.py +0 -0
  119. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/separators/common.py +0 -0
  120. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/separators/demucs.py +0 -0
  121. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/separators/openunmix.py +0 -0
  122. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/separators/scnet.py +0 -0
  123. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/server.py +0 -0
  124. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/sonic_visualiser.py +0 -0
  125. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/speech.py +0 -0
  126. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/util.py +0 -0
  127. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/vamp.py +0 -0
  128. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/vamp_runtime.py +0 -0
  129. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/web/app.js +0 -0
  130. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/web/arcadians-cover.jpg +0 -0
  131. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/web/arcadians-reference.json +0 -0
  132. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/web/index.html +0 -0
  133. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/web/style.css +0 -0
  134. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/web/timeline.css +0 -0
  135. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/src/stemlab/webui.py +0 -0
  136. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_analysis_registry.py +0 -0
  137. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_arcadians_fixture.py +0 -0
  138. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_audio_normalization.py +0 -0
  139. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_beat_consensus.py +0 -0
  140. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_beatnet_compat.py +0 -0
  141. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_branding.py +0 -0
  142. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_canonical.py +0 -0
  143. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_canonical_extended.py +0 -0
  144. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_codex_bridge.py +0 -0
  145. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_codex_jobs.py +0 -0
  146. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_codex_package.py +0 -0
  147. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_codex_timeline.py +0 -0
  148. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_deep_harmony.py +0 -0
  149. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_deep_lyrics.py +0 -0
  150. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_deep_sonic_rhythm.py +0 -0
  151. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_loop_integration.py +0 -0
  152. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_loops.py +0 -0
  153. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_manifest.py +0 -0
  154. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_models.py +0 -0
  155. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_repository_hygiene.py +0 -0
  156. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_server.py +0 -0
  157. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_song_map.py +0 -0
  158. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_sonic_visualiser.py +0 -0
  159. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_sonic_visualiser_workspace.py +0 -0
  160. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_speech_repetition.py +0 -0
  161. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_vamp.py +0 -0
  162. {danceflow_stemlab-1.2.0 → danceflow_stemlab-1.3.0}/tests/test_vamp_runtime.py +0 -0
@@ -13,3 +13,8 @@ include .github/workflows/release.yml
13
13
  include scripts/check_codex_timeline.py
14
14
  include scripts/loop_demo.py
15
15
  include scripts/capture_loop_workflow.py
16
+ include docs/midi.md
17
+ include scripts/smoke_midi.py
18
+ include docs/cue-alignment.md
19
+ include docs/evidence-models.md
20
+ include scripts/benchmark_evidence_corpus.py
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: danceflow-stemlab
3
- Version: 1.2.0
4
- Summary: StemLab audio timing analysis and loopable sections for creating Shorts videos; DanceFlow and WordPress DanceMoves
3
+ Version: 1.3.0
4
+ Summary: Local, evidence-led music analysis for stems, timing, structure, harmony, lyrics, and loopable sections for Shorts
5
5
  Author: Kieran Simkin
6
6
  Maintainer: Kieran Simkin
7
7
  License-Expression: MIT
@@ -49,6 +49,8 @@ Provides-Extra: speech
49
49
  Requires-Dist: faster-whisper; extra == "speech"
50
50
  Provides-Extra: beats
51
51
  Requires-Dist: beat-this>=1.1.0; extra == "beats"
52
+ Requires-Dist: madmom-prebuilt==0.17.post1; python_version >= "3.11" and extra == "beats"
53
+ Requires-Dist: mido>=1.2.6; extra == "beats"
52
54
  Provides-Extra: deep
53
55
  Requires-Dist: sentence-transformers<7,>=6.1; extra == "deep"
54
56
  Requires-Dist: all-in-one-infer>=3.1; extra == "deep"
@@ -56,6 +58,40 @@ Provides-Extra: semantic-nc
56
58
  Requires-Dist: muq; extra == "semantic-nc"
57
59
  Provides-Extra: amt
58
60
  Requires-Dist: basic-pitch<0.5,>=0.4; python_version < "3.12" and extra == "amt"
61
+ Provides-Extra: midi
62
+ Requires-Dist: pretty-midi<0.3,>=0.2.10; extra == "midi"
63
+ Requires-Dist: mido<2,>=1.3; extra == "midi"
64
+ Requires-Dist: psutil>=5.9; extra == "midi"
65
+ Provides-Extra: midi-piano
66
+ Requires-Dist: pretty-midi<0.3,>=0.2.10; extra == "midi-piano"
67
+ Requires-Dist: mido<2,>=1.3; extra == "midi-piano"
68
+ Requires-Dist: psutil>=5.9; extra == "midi-piano"
69
+ Requires-Dist: piano-transcription-inference==0.0.6; extra == "midi-piano"
70
+ Provides-Extra: midi-transkun
71
+ Requires-Dist: pretty-midi<0.3,>=0.2.10; extra == "midi-transkun"
72
+ Requires-Dist: mido<2,>=1.3; extra == "midi-transkun"
73
+ Requires-Dist: psutil>=5.9; extra == "midi-transkun"
74
+ Requires-Dist: transkun==2.0.1; extra == "midi-transkun"
75
+ Requires-Dist: setuptools<81; extra == "midi-transkun"
76
+ Provides-Extra: midi-mt3
77
+ Requires-Dist: pretty-midi<0.3,>=0.2.10; extra == "midi-mt3"
78
+ Requires-Dist: mido<2,>=1.3; extra == "midi-mt3"
79
+ Requires-Dist: psutil>=5.9; extra == "midi-mt3"
80
+ Requires-Dist: mt3-infer[torch]==0.2.0; extra == "midi-mt3"
81
+ Provides-Extra: evidence
82
+ Requires-Dist: psutil>=5.9; extra == "evidence"
83
+ Provides-Extra: evidence-vocals
84
+ Requires-Dist: psutil>=5.9; extra == "evidence-vocals"
85
+ Requires-Dist: fireredvad<0.1,>=0.0.2; extra == "evidence-vocals"
86
+ Provides-Extra: evidence-pitch
87
+ Requires-Dist: psutil>=5.9; extra == "evidence-pitch"
88
+ Requires-Dist: swift-f0[audio]<0.4,>=0.3; extra == "evidence-pitch"
89
+ Provides-Extra: evidence-align
90
+ Requires-Dist: psutil>=5.9; extra == "evidence-align"
91
+ Requires-Dist: qwen-asr; extra == "evidence-align"
92
+ Provides-Extra: evidence-chords
93
+ Requires-Dist: psutil>=5.9; extra == "evidence-chords"
94
+ Requires-Dist: lv-chordia; extra == "evidence-chords"
59
95
  Provides-Extra: server
60
96
  Requires-Dist: fastapi<1,>=0.115; extra == "server"
61
97
  Requires-Dist: uvicorn[standard]<1,>=0.34; extra == "server"
@@ -77,6 +113,8 @@ Requires-Dist: openunmix>=1.3.0; extra == "all"
77
113
  Requires-Dist: bs-roformer-infer>=0.1.5; extra == "all"
78
114
  Requires-Dist: faster-whisper; extra == "all"
79
115
  Requires-Dist: beat-this>=1.1.0; extra == "all"
116
+ Requires-Dist: madmom-prebuilt==0.17.post1; python_version >= "3.11" and extra == "all"
117
+ Requires-Dist: mido>=1.2.6; extra == "all"
80
118
  Requires-Dist: sentence-transformers<7,>=6.1; extra == "all"
81
119
  Requires-Dist: all-in-one-infer>=3.1; extra == "all"
82
120
  Requires-Dist: fastapi<1,>=0.115; extra == "all"
@@ -92,7 +130,11 @@ Dynamic: license-file
92
130
 
93
131
  > **Packaging identity:** the canonical project name is **StemLab**. StemLab is part of the **Dance Flow** project. The PyPI distribution is named `danceflow-stemlab` solely because Python package-registry names are globally unique. The Python import, CLI, GitHub repository and container image remain `stemlab`.
94
132
 
95
- StemLab provides **audio timing analysis and finds loopable sections for creating Shorts and other short-form videos**. It is the audio-analysis engine in Kieran Simkin's **DanceFlow** BPM and motion-response workflow. It separates and interprets a master track into synchronised stem, BPM/beat, structure, harmony, timbre, speech/lyric and semantic data. Those outputs can drive downstream motion-aware experiences, including the WordPress **DanceMoves** plugin, while StemLab remains usable as a standalone CLI, Python library, web service and container.
133
+ ## Synopsis
134
+
135
+ **StemLab is a local, evidence-led music analysis toolkit that turns a master recording into inspectable stems, timing, structure, harmony, lyric and sonic evidence, then finds complete-bar loopable sections for Shorts and other short-form videos.**
136
+
137
+ It combines independent separation and music-information-retrieval routes rather than treating any single model as the answer. Results remain traceable through source hashes, manifests, JSON/TSV/NPZ artefacts, portable Sonic Visualiser sessions and a shared React timeline for playback and comparison. StemLab can run as a CLI, Python library, web service, container or local Codex MCP plugin. It is the music-understanding layer of Kieran Simkin's **DanceFlow** workflow and can supply downstream motion systems such as the WordPress **DanceMoves** plugin, while remaining useful on its own.
96
138
 
97
139
  > **Model weights are not redistributed by this project.** They are fetched from their upstream registries/releases on first use. This avoids silently republishing checkpoints whose licensing may differ from the source code license, and lets upstream integrity metadata be used where available.
98
140
 
@@ -134,13 +176,19 @@ Relevant upstreams:
134
176
 
135
177
  For every successful separator, **every WAV it emits** is retained. Stem names are discovered from files rather than truncated to a hard-coded four-stem schema, which is important for MVSep Mega 53. For the master and every stem, StemLab writes both a PNG spectrogram and compressed `.npz` spectrogram data (time axis, frequency axis, dB matrix, FFT metadata).
136
178
 
179
+ Full-resolution spectrogram evidence stays in the `.npz`; the PNG renderer is bounded to 8,192 time frames so long tracks cannot expand into multi-gigabyte Matplotlib RGBA buffers. If an older run retained the NPZ but failed while drawing the PNG, repair it in place without rerunning models:
180
+
181
+ ```powershell
182
+ stemlab repair-spectrograms "path\to\analysis-results"
183
+ ```
184
+
137
185
  The preferred vocal stem is passed through the Silero VAD implementation bundled with `faster-whisper`. Speech regions are used to create a timeline-preserving `spoken_word.wav` (non-speech is zeroed rather than concatenated), then Whisper is run with word timestamps. Outputs include `whisper.json`, `speech_regions.json`, `transcript.txt`, `transcript.srt`, and `words.tsv`.
138
186
 
139
187
  Whisper runs in repetition-safe mode by default (`condition_on_previous_text=False`) to prevent a repeated syllable in one window contaminating later windows. `whisper.json` records that setting and includes repeated-token diagnostics. Use `--whisper-condition-on-previous-text` only for an explicit comparison run; a flagged transcript remains evidence requiring section-wise recovery or listening QA, not a trustworthy lyric source.
140
188
 
141
189
  Beat analysis runs:
142
190
 
143
- - **BeatNet** in offline/DBN mode when a compatible legacy environment is separately provisioned; it is not included in the current installable extras because its pinned NumPy/Numba requirements conflict with StemLab's core.
191
+ - **BeatNet** in offline/DBN mode through StemLab's checksum-verified runtime bootstrap. StemLab uses the maintained `madmom-prebuilt` wheel and bypasses only BeatNet 1.1.3's obsolete NumPy/Numba package metadata.
144
192
  - **Beat This!** using the `final0` checkpoint and its minimal postprocessor.
145
193
  - **Beat Transformer**, using the original released model code/checkpoints. The model was trained on five demixed mel streams, so StemLab maps BS-RoFormer-SW to vocals, drums, bass, piano, and `other + guitar`, makes 128-bin mel-power spectrograms at the original 44.1 kHz / 4096 FFT / 1024-hop settings, and averages all eight released fold checkpoints by default. It uses the original madmom DBN decoder if madmom is importable, otherwise a documented SciPy peak-picking fallback.
146
194
 
@@ -305,9 +353,128 @@ sample indexing, thresholds, limitations and reproducible screenshot examples.
305
353
 
306
354
  ![Loop selection and playback in the existing analysis frontend](docs/screenshots/loops-playing.png)
307
355
 
356
+ ## Audio-to-MIDI model comparison
357
+
358
+ MIDI extraction is an **optional, independent model pass**. It adds Transkun V2
359
+ and high-resolution note/pedal piano transcription, plus MR-MT3 and YourMT3
360
+ multi-instrument transcription, alongside Spotify Basic Pitch. Automatic source
361
+ selection uses piano/keyboard stems for the piano specialists, pitched stems for
362
+ Basic Pitch and the mix for MT3-family models. Missing stems are reported, never
363
+ silently substituted. The legacy `--basic-pitch` command remains supported.
364
+
365
+ ```bash
366
+ # Install the chosen runtime; the standard profiles do not install MIDI models.
367
+ python -m pip install -e ".[midi-transkun]"
368
+ stemlab midi-models
369
+
370
+ # Use an existing separated piano, without rerunning any earlier analysis.
371
+ stemlab midi analysis-master --model transkun
372
+
373
+ # Or transcribe a directly supplied piano recording to a new folder.
374
+ stemlab midi piano.wav -o midi-piano --model transkun
375
+
376
+ # Full mix comparison requires the separately installed midi-mt3 extra.
377
+ # Both requested checkpoints need explicit first-use download consent.
378
+ stemlab midi mix.wav -o midi-comparison --model mr_mt3 --model yourmt3 --allow-model-downloads
379
+ ```
380
+
381
+ Each model/source gets its original `.mid`, tempo-aware `notes.json` and
382
+ `notes.csv`, an optional real note `piano-roll.png`, source/checkpoint hashes,
383
+ package versions and a worker log. Native MIDI controllers, pitch bends, tempo
384
+ changes and drums are preserved. Note sample numbers are original-rate
385
+ **estimates**, not a claim that the transcription is sample-accurate ground truth.
386
+ The MIDI clock is not used to overwrite StemLab's measured beat grid.
387
+
388
+ New analyses can opt in with repeated `--midi-model` switches and
389
+ `--midi-allow-downloads`. Existing Codex installations gain a workspace-scoped
390
+ `stemlab_start_midi_scan` job tool after updating the Python installation and
391
+ restarting the session. Models remain optional and no Python dependencies are
392
+ automatically installed. Incompatible research runtimes can use separate
393
+ `--backend-python MODEL=PATH` interpreters.
394
+
395
+ See [the MIDI guide](docs/midi.md) for all models, installation choices, checkpoint
396
+ and licensing caveats, saved-stem targeting, Codex usage, exact output semantics,
397
+ real-inference smoke commands and test limitations. The React timeline remains
398
+ the analysis inspector; this patch adds no MIDI synthesizer or new interactive
399
+ piano-roll lane. Static note plots are not frontend screenshots.
400
+
401
+ ## Align timed musical cues to detected beats
402
+
403
+ Use saved analysis to snap an LRC cue file without rerunning models or editing audio:
404
+
405
+ ```bash
406
+ stemlab snap-cues analysis-master "musical cues.lrc" -o cue-review
407
+ stemlab snap-cues analysis-master "musical cues.lrc" -o cue-review-100ms --tolerance-ms 100
408
+ stemlab generate-cues analysis-master -o generated-cues --title "Song title"
409
+ ```
410
+
411
+ Only timestamps change: bracketed labels such as `[DROP: CHORUS 1]`, metadata,
412
+ encoding and line layout are preserved. A cue with **no detected beat within
413
+ ±150 ms** is highlighted as **REVIEW**, with its nearest-beat gap, and kept unchanged
414
+ by default. `--force-snap` moves distant cues too but retains their warnings.
415
+ `--downbeats` restricts targets to reported bar starts; `--beat-model` selects a
416
+ specific detector. No constant-tempo beats are invented to fill detection gaps.
417
+
418
+ Each new output folder contains the rewritten `.beat-snapped.lrc`, `report.json`,
419
+ a colour-coded `review.html`, and `review.txt`. Exact mode preserves the stored
420
+ beat timestamp; explicit millisecond/centisecond compatibility modes report
421
+ rounding. Source-rate sample-frame estimates are included when the rate is known.
422
+ Use `--fail-on-review` to write results and exit 2 when review is needed.
423
+ Generated section-cue files use a title-specific, WordPress-safe filename so
424
+ multiple releases can be uploaded and mapped without ambiguous duplicate names.
425
+ For the retained 3 October 2026 future-release batch,
426
+ `scripts/run-upcoming-full-cues.ps1` resumes full analyses without overwriting an
427
+ incomplete directory, and `scripts/summarize-upcoming-cues.ps1` reads each closed
428
+ manifest/report to produce one reproducible hash, cue-action and error-count row
429
+ per release. The summary script refuses missing or ambiguous generated LRCs.
430
+
431
+ For a new analysis, add `--snap-cues "musical cues.lrc"` and optionally
432
+ `--cue-tolerance-ms 100`. Cue alignment uses that run's detected events and appears
433
+ in `analysis.json`. See [the cue alignment guide](docs/cue-alignment.md) for exact
434
+ precision, offsets, all switches, safety rules and interpretation of warnings.
435
+
436
+ ## Complementary evidence models
437
+
438
+ StemLab now has an optional **evidence-model layer** for models that add a different
439
+ kind of musical evidence instead of duplicating the normal separation or MIDI
440
+ backends. Nothing in this layer is enabled by a normal profile.
441
+
442
+ ```bash
443
+ stemlab evidence-models
444
+
445
+ # Singing/speech/music activity + continuous pitch on saved vocals.
446
+ stemlab evidence analysis-master -o evidence-vocals \
447
+ --model firered_aed --model swift_f0 \
448
+ --model-path firered_aed=/models/FireRedVAD/AED
449
+
450
+ # Align approved lyrics without replacing them.
451
+ stemlab evidence analysis-master -o evidence-align \
452
+ --model qwen_forced_aligner --canonical-text lyrics.txt --allow-model-downloads
453
+
454
+ # Independent harmony evidence.
455
+ stemlab evidence analysis-master -o evidence-chords --model lv_chordia
456
+ ```
457
+
458
+ The built-in registry covers **FireRed AED**, **HeartTranscriptor**, **Qwen3
459
+ ForcedAligner**, **SwiftF0**, **SongFormer**, **lv-chordia** and **ADTOF PyTorch**.
460
+ It also exposes explicit external-runtime bridges for **GAME**, **SheetSage2**,
461
+ **MOSS-Music** and **AudioSep** so large or restricted research dependencies never
462
+ get silently bundled into StemLab. Outputs stay independent: singing activity,
463
+ forced alignment, pitch, structure, chords and drum hits are review evidence, not
464
+ a hidden combined ground-truth score.
465
+
466
+ Saved analyses automatically route vocal models to a preferred full vocal stem,
467
+ drum transcription to a drum stem, continuous pitch to pitched stems, and
468
+ structure/harmony models to the master. Missing specialist stems are reported.
469
+ Use `--backend-python MODEL=/path/to/python` for conflicting research environments.
470
+
471
+ See [the evidence-model guide](docs/evidence-models.md) for model terms, routing,
472
+ external bridges and interpretation rules. `scripts/benchmark_evidence_corpus.py`
473
+ probes an authorised evaluation collection without copying audio into the repo.
474
+
308
475
  ## Install
309
476
 
310
- Python 3.10 or 3.11 is recommended for the broad optional-model ecosystem. The `beats` and `all` extras install Beat This! but not BeatNet: BeatNet's current published NumPy/Numba pins conflict with StemLab's core Librosa requirement. The BeatNet adapter is retained for separately provisioned compatible legacy setups; a missing BeatNet result must not be mistaken for a successful detector run.
477
+ Python 3.11 is recommended for the broad optional-model ecosystem. The `beats` and `all` extras install Beat This! plus the compatible `madmom-prebuilt` decoder. BeatNet 1.1.3 itself still publishes obsolete NumPy/Numba dependency pins, so StemLab downloads its official pure-Python wheel separately, verifies the published SHA-256, and exposes only the BeatNet code and bundled model weights from its cache. This route is supported on Python 3.11-3.13; a missing BeatNet result must not be mistaken for a successful detector run.
311
478
 
312
479
  From PyPI, install the released StemLab distribution with:
313
480
 
@@ -330,6 +497,18 @@ SCNet and Beat Transformer are research repositories rather than stable pip infe
330
497
  stemlab bootstrap all
331
498
  ```
332
499
 
500
+ For BeatNet alone:
501
+
502
+ ```bash
503
+ pip install "danceflow-stemlab[beats]"
504
+ stemlab bootstrap beatnet
505
+ stemlab doctor
506
+ ```
507
+
508
+ `stemlab doctor` reports BeatNet as ready only when the normal package or the
509
+ verified StemLab cache can actually be found. `analyze --no-bootstrap` never
510
+ downloads BeatNet and records the unavailable backend instead.
511
+
333
512
  For only the Vamp analysis stack:
334
513
 
335
514
  ```bash
@@ -439,6 +618,7 @@ endpoints, events and the Arcadians reference workflow.
439
618
  - [Web service](docs/web.md)
440
619
  - [Containers](docs/containers.md)
441
620
  - [Publishing and releases](docs/publishing.md)
621
+ - [BeatNet compatibility](docs/beatnet.md)
442
622
  - [Changelog](CHANGELOG.md)
443
623
 
444
624
  ## Codex plugin and MCP server
@@ -1,89 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: danceflow-stemlab
3
- Version: 1.2.0
4
- Summary: StemLab audio timing analysis and loopable sections for creating Shorts videos; DanceFlow and WordPress DanceMoves
5
- Author: Kieran Simkin
6
- Maintainer: Kieran Simkin
7
- License-Expression: MIT
8
- Project-URL: Homepage, https://kieransimkin.co.uk/
9
- Project-URL: My Songs portfolio, https://kieransimkin.co.uk/my-songs/
10
- Project-URL: Arcadians showcase, https://kieransimkin.co.uk/arcadians/
11
- Project-URL: Repository, https://github.com/kieransimkin/stemlab
12
- Project-URL: Issues, https://github.com/kieransimkin/stemlab/issues
13
- Project-URL: Documentation, https://github.com/kieransimkin/stemlab/tree/main/docs
14
- Project-URL: Changelog, https://github.com/kieransimkin/stemlab/blob/main/CHANGELOG.md
15
- Project-URL: About Kieran, https://kieransimkin.co.uk/about-me/
16
- Project-URL: Contact, https://kieransimkin.co.uk/contact/
17
- Keywords: music,audio,MIR,source separation,BPM,rhythm,harmony,DanceFlow,DanceMoves,motion response,WordPress
18
- Classifier: Development Status :: 5 - Production/Stable
19
- Classifier: Programming Language :: Python :: 3
20
- Classifier: Programming Language :: Python :: 3.10
21
- Classifier: Programming Language :: Python :: 3.11
22
- Classifier: Programming Language :: Python :: 3.12
23
- Classifier: Programming Language :: Python :: 3.13
24
- Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
25
- Requires-Python: >=3.10
26
- Description-Content-Type: text/markdown
27
- License-File: LICENSE
28
- Requires-Dist: numpy
29
- Requires-Dist: scipy
30
- Requires-Dist: torch>=2.4
31
- Requires-Dist: torchaudio>=2.4
32
- Requires-Dist: soundfile>=0.12
33
- Requires-Dist: matplotlib
34
- Requires-Dist: typer>=0.12
35
- Requires-Dist: rich>=13.7
36
- Requires-Dist: platformdirs>=4.2
37
- Requires-Dist: librosa>=0.11
38
- Requires-Dist: pyloudnorm>=0.2
39
- Requires-Dist: cmudict>=1.1.3
40
- Provides-Extra: codex
41
- Requires-Dist: mcp<3,>=2.2; extra == "codex"
42
- Requires-Dist: fastapi<1,>=0.115; extra == "codex"
43
- Requires-Dist: uvicorn<1,>=0.34; extra == "codex"
44
- Provides-Extra: separation
45
- Requires-Dist: demucs>=4.0.1; extra == "separation"
46
- Requires-Dist: openunmix>=1.3.0; extra == "separation"
47
- Requires-Dist: bs-roformer-infer>=0.1.5; extra == "separation"
48
- Provides-Extra: speech
49
- Requires-Dist: faster-whisper; extra == "speech"
50
- Provides-Extra: beats
51
- Requires-Dist: beat-this>=1.1.0; extra == "beats"
52
- Provides-Extra: deep
53
- Requires-Dist: sentence-transformers<7,>=6.1; extra == "deep"
54
- Requires-Dist: all-in-one-infer>=3.1; extra == "deep"
55
- Provides-Extra: semantic-nc
56
- Requires-Dist: muq; extra == "semantic-nc"
57
- Provides-Extra: amt
58
- Requires-Dist: basic-pitch<0.5,>=0.4; python_version < "3.12" and extra == "amt"
59
- Provides-Extra: server
60
- Requires-Dist: fastapi<1,>=0.115; extra == "server"
61
- Requires-Dist: uvicorn[standard]<1,>=0.34; extra == "server"
62
- Requires-Dist: python-socketio<6,>=5.12; extra == "server"
63
- Provides-Extra: dev
64
- Requires-Dist: pytest>=8.0; extra == "dev"
65
- Requires-Dist: ruff>=0.6; extra == "dev"
66
- Requires-Dist: build>=1.2; extra == "dev"
67
- Requires-Dist: tomli>=2; python_version < "3.11" and extra == "dev"
68
- Requires-Dist: httpx2; extra == "dev"
69
- Provides-Extra: binary
70
- Requires-Dist: nuitka>=2.7; extra == "binary"
71
- Requires-Dist: ordered-set>=4.1; extra == "binary"
72
- Requires-Dist: zstandard>=0.23; extra == "binary"
73
- Requires-Dist: lazy-loader==0.4; extra == "binary"
74
- Provides-Extra: all
75
- Requires-Dist: demucs>=4.0.1; extra == "all"
76
- Requires-Dist: openunmix>=1.3.0; extra == "all"
77
- Requires-Dist: bs-roformer-infer>=0.1.5; extra == "all"
78
- Requires-Dist: faster-whisper; extra == "all"
79
- Requires-Dist: beat-this>=1.1.0; extra == "all"
80
- Requires-Dist: sentence-transformers<7,>=6.1; extra == "all"
81
- Requires-Dist: all-in-one-infer>=3.1; extra == "all"
82
- Requires-Dist: fastapi<1,>=0.115; extra == "all"
83
- Requires-Dist: uvicorn[standard]<1,>=0.34; extra == "all"
84
- Requires-Dist: python-socketio<6,>=5.12; extra == "all"
85
- Dynamic: license-file
86
-
87
1
  # StemLab
88
2
 
89
3
  <!-- mcp-name: io.github.kieransimkin/stemlab -->
@@ -92,7 +6,11 @@ Dynamic: license-file
92
6
 
93
7
  > **Packaging identity:** the canonical project name is **StemLab**. StemLab is part of the **Dance Flow** project. The PyPI distribution is named `danceflow-stemlab` solely because Python package-registry names are globally unique. The Python import, CLI, GitHub repository and container image remain `stemlab`.
94
8
 
95
- StemLab provides **audio timing analysis and finds loopable sections for creating Shorts and other short-form videos**. It is the audio-analysis engine in Kieran Simkin's **DanceFlow** BPM and motion-response workflow. It separates and interprets a master track into synchronised stem, BPM/beat, structure, harmony, timbre, speech/lyric and semantic data. Those outputs can drive downstream motion-aware experiences, including the WordPress **DanceMoves** plugin, while StemLab remains usable as a standalone CLI, Python library, web service and container.
9
+ ## Synopsis
10
+
11
+ **StemLab is a local, evidence-led music analysis toolkit that turns a master recording into inspectable stems, timing, structure, harmony, lyric and sonic evidence, then finds complete-bar loopable sections for Shorts and other short-form videos.**
12
+
13
+ It combines independent separation and music-information-retrieval routes rather than treating any single model as the answer. Results remain traceable through source hashes, manifests, JSON/TSV/NPZ artefacts, portable Sonic Visualiser sessions and a shared React timeline for playback and comparison. StemLab can run as a CLI, Python library, web service, container or local Codex MCP plugin. It is the music-understanding layer of Kieran Simkin's **DanceFlow** workflow and can supply downstream motion systems such as the WordPress **DanceMoves** plugin, while remaining useful on its own.
96
14
 
97
15
  > **Model weights are not redistributed by this project.** They are fetched from their upstream registries/releases on first use. This avoids silently republishing checkpoints whose licensing may differ from the source code license, and lets upstream integrity metadata be used where available.
98
16
 
@@ -134,13 +52,19 @@ Relevant upstreams:
134
52
 
135
53
  For every successful separator, **every WAV it emits** is retained. Stem names are discovered from files rather than truncated to a hard-coded four-stem schema, which is important for MVSep Mega 53. For the master and every stem, StemLab writes both a PNG spectrogram and compressed `.npz` spectrogram data (time axis, frequency axis, dB matrix, FFT metadata).
136
54
 
55
+ Full-resolution spectrogram evidence stays in the `.npz`; the PNG renderer is bounded to 8,192 time frames so long tracks cannot expand into multi-gigabyte Matplotlib RGBA buffers. If an older run retained the NPZ but failed while drawing the PNG, repair it in place without rerunning models:
56
+
57
+ ```powershell
58
+ stemlab repair-spectrograms "path\to\analysis-results"
59
+ ```
60
+
137
61
  The preferred vocal stem is passed through the Silero VAD implementation bundled with `faster-whisper`. Speech regions are used to create a timeline-preserving `spoken_word.wav` (non-speech is zeroed rather than concatenated), then Whisper is run with word timestamps. Outputs include `whisper.json`, `speech_regions.json`, `transcript.txt`, `transcript.srt`, and `words.tsv`.
138
62
 
139
63
  Whisper runs in repetition-safe mode by default (`condition_on_previous_text=False`) to prevent a repeated syllable in one window contaminating later windows. `whisper.json` records that setting and includes repeated-token diagnostics. Use `--whisper-condition-on-previous-text` only for an explicit comparison run; a flagged transcript remains evidence requiring section-wise recovery or listening QA, not a trustworthy lyric source.
140
64
 
141
65
  Beat analysis runs:
142
66
 
143
- - **BeatNet** in offline/DBN mode when a compatible legacy environment is separately provisioned; it is not included in the current installable extras because its pinned NumPy/Numba requirements conflict with StemLab's core.
67
+ - **BeatNet** in offline/DBN mode through StemLab's checksum-verified runtime bootstrap. StemLab uses the maintained `madmom-prebuilt` wheel and bypasses only BeatNet 1.1.3's obsolete NumPy/Numba package metadata.
144
68
  - **Beat This!** using the `final0` checkpoint and its minimal postprocessor.
145
69
  - **Beat Transformer**, using the original released model code/checkpoints. The model was trained on five demixed mel streams, so StemLab maps BS-RoFormer-SW to vocals, drums, bass, piano, and `other + guitar`, makes 128-bin mel-power spectrograms at the original 44.1 kHz / 4096 FFT / 1024-hop settings, and averages all eight released fold checkpoints by default. It uses the original madmom DBN decoder if madmom is importable, otherwise a documented SciPy peak-picking fallback.
146
70
 
@@ -305,9 +229,128 @@ sample indexing, thresholds, limitations and reproducible screenshot examples.
305
229
 
306
230
  ![Loop selection and playback in the existing analysis frontend](docs/screenshots/loops-playing.png)
307
231
 
232
+ ## Audio-to-MIDI model comparison
233
+
234
+ MIDI extraction is an **optional, independent model pass**. It adds Transkun V2
235
+ and high-resolution note/pedal piano transcription, plus MR-MT3 and YourMT3
236
+ multi-instrument transcription, alongside Spotify Basic Pitch. Automatic source
237
+ selection uses piano/keyboard stems for the piano specialists, pitched stems for
238
+ Basic Pitch and the mix for MT3-family models. Missing stems are reported, never
239
+ silently substituted. The legacy `--basic-pitch` command remains supported.
240
+
241
+ ```bash
242
+ # Install the chosen runtime; the standard profiles do not install MIDI models.
243
+ python -m pip install -e ".[midi-transkun]"
244
+ stemlab midi-models
245
+
246
+ # Use an existing separated piano, without rerunning any earlier analysis.
247
+ stemlab midi analysis-master --model transkun
248
+
249
+ # Or transcribe a directly supplied piano recording to a new folder.
250
+ stemlab midi piano.wav -o midi-piano --model transkun
251
+
252
+ # Full mix comparison requires the separately installed midi-mt3 extra.
253
+ # Both requested checkpoints need explicit first-use download consent.
254
+ stemlab midi mix.wav -o midi-comparison --model mr_mt3 --model yourmt3 --allow-model-downloads
255
+ ```
256
+
257
+ Each model/source gets its original `.mid`, tempo-aware `notes.json` and
258
+ `notes.csv`, an optional real note `piano-roll.png`, source/checkpoint hashes,
259
+ package versions and a worker log. Native MIDI controllers, pitch bends, tempo
260
+ changes and drums are preserved. Note sample numbers are original-rate
261
+ **estimates**, not a claim that the transcription is sample-accurate ground truth.
262
+ The MIDI clock is not used to overwrite StemLab's measured beat grid.
263
+
264
+ New analyses can opt in with repeated `--midi-model` switches and
265
+ `--midi-allow-downloads`. Existing Codex installations gain a workspace-scoped
266
+ `stemlab_start_midi_scan` job tool after updating the Python installation and
267
+ restarting the session. Models remain optional and no Python dependencies are
268
+ automatically installed. Incompatible research runtimes can use separate
269
+ `--backend-python MODEL=PATH` interpreters.
270
+
271
+ See [the MIDI guide](docs/midi.md) for all models, installation choices, checkpoint
272
+ and licensing caveats, saved-stem targeting, Codex usage, exact output semantics,
273
+ real-inference smoke commands and test limitations. The React timeline remains
274
+ the analysis inspector; this patch adds no MIDI synthesizer or new interactive
275
+ piano-roll lane. Static note plots are not frontend screenshots.
276
+
277
+ ## Align timed musical cues to detected beats
278
+
279
+ Use saved analysis to snap an LRC cue file without rerunning models or editing audio:
280
+
281
+ ```bash
282
+ stemlab snap-cues analysis-master "musical cues.lrc" -o cue-review
283
+ stemlab snap-cues analysis-master "musical cues.lrc" -o cue-review-100ms --tolerance-ms 100
284
+ stemlab generate-cues analysis-master -o generated-cues --title "Song title"
285
+ ```
286
+
287
+ Only timestamps change: bracketed labels such as `[DROP: CHORUS 1]`, metadata,
288
+ encoding and line layout are preserved. A cue with **no detected beat within
289
+ ±150 ms** is highlighted as **REVIEW**, with its nearest-beat gap, and kept unchanged
290
+ by default. `--force-snap` moves distant cues too but retains their warnings.
291
+ `--downbeats` restricts targets to reported bar starts; `--beat-model` selects a
292
+ specific detector. No constant-tempo beats are invented to fill detection gaps.
293
+
294
+ Each new output folder contains the rewritten `.beat-snapped.lrc`, `report.json`,
295
+ a colour-coded `review.html`, and `review.txt`. Exact mode preserves the stored
296
+ beat timestamp; explicit millisecond/centisecond compatibility modes report
297
+ rounding. Source-rate sample-frame estimates are included when the rate is known.
298
+ Use `--fail-on-review` to write results and exit 2 when review is needed.
299
+ Generated section-cue files use a title-specific, WordPress-safe filename so
300
+ multiple releases can be uploaded and mapped without ambiguous duplicate names.
301
+ For the retained 3 October 2026 future-release batch,
302
+ `scripts/run-upcoming-full-cues.ps1` resumes full analyses without overwriting an
303
+ incomplete directory, and `scripts/summarize-upcoming-cues.ps1` reads each closed
304
+ manifest/report to produce one reproducible hash, cue-action and error-count row
305
+ per release. The summary script refuses missing or ambiguous generated LRCs.
306
+
307
+ For a new analysis, add `--snap-cues "musical cues.lrc"` and optionally
308
+ `--cue-tolerance-ms 100`. Cue alignment uses that run's detected events and appears
309
+ in `analysis.json`. See [the cue alignment guide](docs/cue-alignment.md) for exact
310
+ precision, offsets, all switches, safety rules and interpretation of warnings.
311
+
312
+ ## Complementary evidence models
313
+
314
+ StemLab now has an optional **evidence-model layer** for models that add a different
315
+ kind of musical evidence instead of duplicating the normal separation or MIDI
316
+ backends. Nothing in this layer is enabled by a normal profile.
317
+
318
+ ```bash
319
+ stemlab evidence-models
320
+
321
+ # Singing/speech/music activity + continuous pitch on saved vocals.
322
+ stemlab evidence analysis-master -o evidence-vocals \
323
+ --model firered_aed --model swift_f0 \
324
+ --model-path firered_aed=/models/FireRedVAD/AED
325
+
326
+ # Align approved lyrics without replacing them.
327
+ stemlab evidence analysis-master -o evidence-align \
328
+ --model qwen_forced_aligner --canonical-text lyrics.txt --allow-model-downloads
329
+
330
+ # Independent harmony evidence.
331
+ stemlab evidence analysis-master -o evidence-chords --model lv_chordia
332
+ ```
333
+
334
+ The built-in registry covers **FireRed AED**, **HeartTranscriptor**, **Qwen3
335
+ ForcedAligner**, **SwiftF0**, **SongFormer**, **lv-chordia** and **ADTOF PyTorch**.
336
+ It also exposes explicit external-runtime bridges for **GAME**, **SheetSage2**,
337
+ **MOSS-Music** and **AudioSep** so large or restricted research dependencies never
338
+ get silently bundled into StemLab. Outputs stay independent: singing activity,
339
+ forced alignment, pitch, structure, chords and drum hits are review evidence, not
340
+ a hidden combined ground-truth score.
341
+
342
+ Saved analyses automatically route vocal models to a preferred full vocal stem,
343
+ drum transcription to a drum stem, continuous pitch to pitched stems, and
344
+ structure/harmony models to the master. Missing specialist stems are reported.
345
+ Use `--backend-python MODEL=/path/to/python` for conflicting research environments.
346
+
347
+ See [the evidence-model guide](docs/evidence-models.md) for model terms, routing,
348
+ external bridges and interpretation rules. `scripts/benchmark_evidence_corpus.py`
349
+ probes an authorised evaluation collection without copying audio into the repo.
350
+
308
351
  ## Install
309
352
 
310
- Python 3.10 or 3.11 is recommended for the broad optional-model ecosystem. The `beats` and `all` extras install Beat This! but not BeatNet: BeatNet's current published NumPy/Numba pins conflict with StemLab's core Librosa requirement. The BeatNet adapter is retained for separately provisioned compatible legacy setups; a missing BeatNet result must not be mistaken for a successful detector run.
353
+ Python 3.11 is recommended for the broad optional-model ecosystem. The `beats` and `all` extras install Beat This! plus the compatible `madmom-prebuilt` decoder. BeatNet 1.1.3 itself still publishes obsolete NumPy/Numba dependency pins, so StemLab downloads its official pure-Python wheel separately, verifies the published SHA-256, and exposes only the BeatNet code and bundled model weights from its cache. This route is supported on Python 3.11-3.13; a missing BeatNet result must not be mistaken for a successful detector run.
311
354
 
312
355
  From PyPI, install the released StemLab distribution with:
313
356
 
@@ -330,6 +373,18 @@ SCNet and Beat Transformer are research repositories rather than stable pip infe
330
373
  stemlab bootstrap all
331
374
  ```
332
375
 
376
+ For BeatNet alone:
377
+
378
+ ```bash
379
+ pip install "danceflow-stemlab[beats]"
380
+ stemlab bootstrap beatnet
381
+ stemlab doctor
382
+ ```
383
+
384
+ `stemlab doctor` reports BeatNet as ready only when the normal package or the
385
+ verified StemLab cache can actually be found. `analyze --no-bootstrap` never
386
+ downloads BeatNet and records the unavailable backend instead.
387
+
333
388
  For only the Vamp analysis stack:
334
389
 
335
390
  ```bash
@@ -439,6 +494,7 @@ endpoints, events and the Arcadians reference workflow.
439
494
  - [Web service](docs/web.md)
440
495
  - [Containers](docs/containers.md)
441
496
  - [Publishing and releases](docs/publishing.md)
497
+ - [BeatNet compatibility](docs/beatnet.md)
442
498
  - [Changelog](CHANGELOG.md)
443
499
 
444
500
  ## Codex plugin and MCP server