batchalign 0.8.2.post13__tar.gz → 0.8.2.post15__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 (158) hide show
  1. {batchalign-0.8.2.post13/batchalign.egg-info → batchalign-0.8.2.post15}/PKG-INFO +17 -7
  2. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/analysis/compare.py +150 -34
  3. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/diarization/pyannote.py +18 -2
  4. batchalign-0.8.2.post15/batchalign/version +3 -0
  5. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15/batchalign.egg-info}/PKG-INFO +17 -7
  6. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign.egg-info/requires.txt +5 -5
  7. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/setup.py +5 -5
  8. batchalign-0.8.2.post13/batchalign/version +0 -3
  9. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/LICENSE +0 -0
  10. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/MANIFEST.in +0 -0
  11. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/README.md +0 -0
  12. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/__init__.py +0 -0
  13. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/__main__.py +0 -0
  14. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/cli/__init__.py +0 -0
  15. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/cli/bench.py +0 -0
  16. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/cli/cache.py +0 -0
  17. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/cli/cli.py +0 -0
  18. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/cli/dispatch.py +0 -0
  19. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/constants.py +0 -0
  20. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/document.py +0 -0
  21. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/errors.py +0 -0
  22. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/formats/__init__.py +0 -0
  23. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/formats/base.py +0 -0
  24. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/formats/chat/__init__.py +0 -0
  25. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/formats/chat/file.py +0 -0
  26. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/formats/chat/generator.py +0 -0
  27. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/formats/chat/lexer.py +0 -0
  28. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/formats/chat/parser.py +0 -0
  29. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/formats/chat/utils.py +0 -0
  30. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/formats/textgrid/__init__.py +0 -0
  31. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/formats/textgrid/file.py +0 -0
  32. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/formats/textgrid/generator.py +0 -0
  33. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/formats/textgrid/parser.py +0 -0
  34. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/__init__.py +0 -0
  35. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/audio_io.py +0 -0
  36. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/resolve.py +0 -0
  37. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/speaker/__init__.py +0 -0
  38. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/speaker/config.yaml +0 -0
  39. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/speaker/infer.py +0 -0
  40. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/speaker/utils.py +0 -0
  41. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/training/__init__.py +0 -0
  42. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/training/run.py +0 -0
  43. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/training/utils.py +0 -0
  44. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/utils.py +0 -0
  45. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/utterance/__init__.py +0 -0
  46. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/utterance/cantonese_infer.py +0 -0
  47. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/utterance/dataset.py +0 -0
  48. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/utterance/execute.py +0 -0
  49. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/utterance/infer.py +0 -0
  50. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/utterance/prep.py +0 -0
  51. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/utterance/train.py +0 -0
  52. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/wave2vec/__init__.py +0 -0
  53. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/wave2vec/infer_fa.py +0 -0
  54. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/whisper/__init__.py +0 -0
  55. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/whisper/infer_asr.py +0 -0
  56. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/models/whisper/infer_fa.py +0 -0
  57. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/__init__.py +0 -0
  58. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/analysis/__init__.py +0 -0
  59. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/analysis/eval.py +0 -0
  60. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/__init__.py +0 -0
  61. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2chinese.py +0 -0
  62. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/__init__.py +0 -0
  63. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/deu.py +0 -0
  64. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/ell.py +0 -0
  65. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/eng.py +0 -0
  66. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/eus.py +0 -0
  67. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/fra.py +0 -0
  68. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/hrv.py +0 -0
  69. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/ind.py +0 -0
  70. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/jpn.py +0 -0
  71. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/nld.py +0 -0
  72. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/por.py +0 -0
  73. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/spa.py +0 -0
  74. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/num2lang/tha.py +0 -0
  75. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/oai_whisper.py +0 -0
  76. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/rev.py +0 -0
  77. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/utils.py +0 -0
  78. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/whisper.py +0 -0
  79. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/asr/whisperx.py +0 -0
  80. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/avqi/__init__.py +0 -0
  81. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/avqi/engine.py +0 -0
  82. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/base.py +0 -0
  83. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/cache.py +0 -0
  84. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/cleanup/__init__.py +0 -0
  85. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/cleanup/cleanup.py +0 -0
  86. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/cleanup/disfluencies.py +0 -0
  87. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/cleanup/parse_support.py +0 -0
  88. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/cleanup/retrace.py +0 -0
  89. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/cleanup/support/filled_pauses.eng +0 -0
  90. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/cleanup/support/replacements.eng +0 -0
  91. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/cleanup/support/test.test +0 -0
  92. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/diarization/__init__.py +0 -0
  93. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/dispatch.py +0 -0
  94. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/fa/__init__.py +0 -0
  95. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/fa/wave2vec_fa.py +0 -0
  96. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/fa/whisper_fa.py +0 -0
  97. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/morphosyntax/__init__.py +0 -0
  98. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/morphosyntax/coref.py +0 -0
  99. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/morphosyntax/en/irr.py +0 -0
  100. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/morphosyntax/fr/apm.py +0 -0
  101. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/morphosyntax/fr/apmn.py +0 -0
  102. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/morphosyntax/fr/case.py +0 -0
  103. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/morphosyntax/ja/verbforms.py +0 -0
  104. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/morphosyntax/ud.py +0 -0
  105. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/opensmile/__init__.py +0 -0
  106. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/opensmile/engine.py +0 -0
  107. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/pipeline.py +0 -0
  108. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/segmentation/__init__.py +0 -0
  109. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/segmentation/cantonese_seg.py +0 -0
  110. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/speaker/__init__.py +0 -0
  111. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/speaker/nemo_speaker.py +0 -0
  112. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/translate/__init__.py +0 -0
  113. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/translate/gtrans.py +0 -0
  114. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/translate/seamless.py +0 -0
  115. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/translate/utils.py +0 -0
  116. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/utr/__init__.py +0 -0
  117. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/utr/rev_utr.py +0 -0
  118. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/utr/utils.py +0 -0
  119. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/utr/whisper_utr.py +0 -0
  120. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/utterance/__init__.py +0 -0
  121. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/pipelines/utterance/ud_utterance.py +0 -0
  122. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/__init__.py +0 -0
  123. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/cli/test_dispatch_memory.py +0 -0
  124. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/conftest.py +0 -0
  125. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/formats/chat/test_chat_file.py +0 -0
  126. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/formats/chat/test_chat_generator.py +0 -0
  127. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/formats/chat/test_chat_lexer.py +0 -0
  128. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/formats/chat/test_chat_parser.py +0 -0
  129. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/formats/chat/test_chat_utils.py +0 -0
  130. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/formats/textgrid/test_textgrid.py +0 -0
  131. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/models/test_audio_io.py +0 -0
  132. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/models/test_audio_lazy.py +0 -0
  133. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/pipelines/analysis/test_eval.py +0 -0
  134. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/pipelines/asr/test_asr_pipeline.py +0 -0
  135. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/pipelines/asr/test_asr_utils.py +0 -0
  136. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/pipelines/cache/__init__.py +0 -0
  137. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/pipelines/cache/test_cache.py +0 -0
  138. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/pipelines/cleanup/test_disfluency.py +0 -0
  139. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/pipelines/cleanup/test_parse_support.py +0 -0
  140. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/pipelines/fa/test_fa_pipeline.py +0 -0
  141. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/pipelines/fa/test_fa_short_segments.py +0 -0
  142. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/pipelines/fixures.py +0 -0
  143. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/pipelines/test_pipeline.py +0 -0
  144. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/pipelines/test_pipeline_models.py +0 -0
  145. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/tests/test_document.py +0 -0
  146. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/utils/__init__.py +0 -0
  147. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/utils/abbrev.py +0 -0
  148. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/utils/compounds.py +0 -0
  149. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/utils/config.py +0 -0
  150. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/utils/device.py +0 -0
  151. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/utils/dp.py +0 -0
  152. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/utils/names.py +0 -0
  153. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign/utils/utils.py +0 -0
  154. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign.egg-info/SOURCES.txt +0 -0
  155. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign.egg-info/dependency_links.txt +0 -0
  156. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign.egg-info/entry_points.txt +0 -0
  157. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/batchalign.egg-info/top_level.txt +0 -0
  158. {batchalign-0.8.2.post13 → batchalign-0.8.2.post15}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: batchalign
3
- Version: 0.8.2.post13
3
+ Version: 0.8.2.post15
4
4
  Summary: Python Speech Language Sample Analysis
5
5
  Author: Brian MacWhinney, Houjun Liu
6
6
  Author-email: macw@cmu.edu, houjun@cmu.edu
@@ -19,15 +19,15 @@ Requires-Dist: platformdirs>=4.3.0
19
19
  Requires-Dist: filelock>=3.0.0
20
20
  Requires-Dist: nltk>=3.8
21
21
  Requires-Dist: praatio<6.1.0,>=6.0.0
22
- Requires-Dist: torch>=2.10.0
23
- Requires-Dist: torchaudio>=2.10.0
22
+ Requires-Dist: torch<2.9,>=2.7
23
+ Requires-Dist: torchaudio<2.9,>=2.7
24
24
  Requires-Dist: soundfile>=0.12.0
25
25
  Requires-Dist: pydub
26
26
  Requires-Dist: plotly>=5.3.0
27
- Requires-Dist: transformers>=4.38.2
27
+ Requires-Dist: transformers<5,>=4.38.2
28
28
  Requires-Dist: tokenizers>=0.14.1
29
29
  Requires-Dist: numba>=0.61.0
30
- Requires-Dist: numpy<=2.2
30
+ Requires-Dist: numpy<2.3,>=1.24
31
31
  Requires-Dist: pycountry>=22.3
32
32
  Requires-Dist: stanza[transformers]>=1.10.1
33
33
  Requires-Dist: scipy~=1.11
@@ -50,7 +50,7 @@ Requires-Dist: openai-whisper
50
50
  Requires-Dist: llvmlite>=0.44.0
51
51
  Requires-Dist: praat-parselmouth==0.4.6
52
52
  Requires-Dist: opensmile>=2.5.0
53
- Requires-Dist: pyannote.audio
53
+ Requires-Dist: pyannote.audio<4,>=3.4.0
54
54
  Requires-Dist: onnxruntime
55
55
  Requires-Dist: certifi>=2025.10.5
56
56
  Provides-Extra: dev
@@ -63,6 +63,16 @@ Requires-Dist: accelerate~=0.27; extra == "train"
63
63
  Provides-Extra: docs
64
64
  Requires-Dist: mkdocs-material; extra == "docs"
65
65
  Requires-Dist: mkdocs-click; extra == "docs"
66
+ Dynamic: author
67
+ Dynamic: author-email
68
+ Dynamic: classifier
69
+ Dynamic: description
70
+ Dynamic: description-content-type
71
+ Dynamic: license-file
72
+ Dynamic: provides-extra
73
+ Dynamic: requires-dist
74
+ Dynamic: requires-python
75
+ Dynamic: summary
66
76
 
67
77
  # TalkBank | Batchalign2
68
78
 
@@ -152,19 +152,34 @@ def match_fn(x, y):
152
152
  # --- End of eval.py duplicates ---
153
153
 
154
154
 
155
- def _find_best_segment(gold_tokens, main_tokens, mfn):
155
+ def _find_best_segment(gold_tokens, main_tokens, main_utts, mfn):
156
156
  """Find a rough window using bag-of-words overlap.
157
157
 
158
158
  The rough pass is order-invariant: it scores contiguous windows by token
159
159
  multiset overlap with the gold utterance, ignoring order. To keep common
160
160
  words from swallowing later transcript material, it only considers windows
161
- near the gold utterance length. Among equally good windows it prefers the
162
- one with the most Levenshtein alignment matches (so order is respected and
163
- cross-utterance fragments that happen to be dense don't beat in-utterance
164
- matches), then fewer non-matching (wasted) tokens, then the latest one as
165
- a final tiebreaker (so CHI repetitions / self-corrections beat earlier INV
166
- tokens). The caller then runs the full Levenshtein aligner inside that
167
- window to produce token annotations.
161
+ near the gold utterance length.
162
+
163
+ Each candidate window is *projected* to its majority source main utt
164
+ before scoring leading and trailing tokens that came from a different
165
+ main utt are stripped before the bag-of-words overlap is computed, so
166
+ cross-utterance bleed can't inflate the score. Without this projection
167
+ a window that straddles two main utterances can outscore both clean
168
+ same-utt windows (we have seen 10/10 vs the correct 9/10) by counting
169
+ matching tokens drawn from both sides; the post-pass snap would correct
170
+ the boundary, but only after that misleading score has already won.
171
+
172
+ Tiebreaking, in order:
173
+
174
+ 1. **Levenshtein align matches** (order-respecting).
175
+ 2. **Latest end position** — repetitions and self-corrections are often
176
+ the intended match while earlier occurrences are example / prompt
177
+ utterances, so a later window beats an earlier one even when it
178
+ carries more disfluences. (This swaps the priority of end vs.
179
+ waste relative to the original implementation: leaner first
180
+ occurrences should not silently win over later self-corrections.)
181
+ 3. **Lower waste** (``window_span - overlap``) — when end is also tied,
182
+ prefer the cleaner window.
168
183
  """
169
184
  if not gold_tokens or not main_tokens:
170
185
  return 0, 0
@@ -182,47 +197,49 @@ def _find_best_segment(gold_tokens, main_tokens, mfn):
182
197
  best_align_matches = -1
183
198
 
184
199
  for span in range(min_window, max_window + 1):
185
- window_counts = Counter(main_tokens[:span])
186
- overlap = sum(min(window_counts[token], gold_counts[token]) for token in window_counts)
187
-
188
200
  for start in range(0, main_len - span + 1):
189
- if start > 0:
190
- left = main_tokens[start - 1]
191
- right = main_tokens[start + span - 1]
192
-
193
- overlap -= min(window_counts[left], gold_counts[left])
194
- window_counts[left] -= 1
195
- overlap += min(window_counts[left], gold_counts[left])
201
+ end = start + span
196
202
 
197
- overlap -= min(window_counts[right], gold_counts[right])
198
- window_counts[right] += 1
199
- overlap += min(window_counts[right], gold_counts[right])
203
+ # Project to majority source-utt by trimming non-majority
204
+ # tokens at both ends. Score is computed on the projected
205
+ # window so cross-utt bleed can't inflate the bag overlap.
206
+ window_utts = main_utts[start:end]
207
+ majority = Counter(window_utts).most_common(1)[0][0]
208
+ ts = start
209
+ while ts < end and main_utts[ts] != majority:
210
+ ts += 1
211
+ te = end
212
+ while te > ts and main_utts[te - 1] != majority:
213
+ te -= 1
214
+ if te <= ts:
215
+ continue
200
216
 
217
+ window = main_tokens[ts:te]
218
+ window_counts = Counter(window)
219
+ overlap = sum(min(window_counts[t], gold_counts[t]) for t in window_counts)
201
220
  score = overlap / gold_len
202
- waste = span - overlap # non-matching tokens in the window
203
- end = start + span
221
+ waste = (te - ts) - overlap
204
222
 
205
- # Alignment-based match count (Levenshtein) as tiebreaker
206
- window = main_tokens[start:end]
207
223
  alignment = align(window, gold_tokens, False, mfn)
208
224
  align_matches = sum(1 for item in alignment if isinstance(item, Match))
209
225
 
210
226
  if score > best_score:
211
- best = (start, end)
227
+ best = (ts, te)
212
228
  best_score = score
213
229
  best_waste = waste
214
230
  best_align_matches = align_matches
215
231
  elif score == best_score:
216
232
  if align_matches > best_align_matches:
217
- best = (start, end)
233
+ best = (ts, te)
218
234
  best_waste = waste
219
235
  best_align_matches = align_matches
220
236
  elif align_matches == best_align_matches:
221
- if best_waste is None or waste < best_waste:
222
- best = (start, end)
237
+ if te > best[1]:
238
+ best = (ts, te)
239
+ best_waste = waste
240
+ elif te == best[1] and (best_waste is None or waste < best_waste):
241
+ best = (ts, te)
223
242
  best_waste = waste
224
- elif waste == best_waste and end > best[1]:
225
- best = (start, end)
226
243
 
227
244
  # If no tokens overlap at all, return an empty window so the caller
228
245
  # doesn't consume main tokens that belong to a later gold utterance.
@@ -232,6 +249,85 @@ def _find_best_segment(gold_tokens, main_tokens, mfn):
232
249
  return best
233
250
 
234
251
 
252
+ def _snap_window_to_majority_utt(abs_start, abs_end, search_start,
253
+ conformed_main, main_map, main_info,
254
+ gold_tokens, mfn):
255
+ """Snap a rough window to the boundaries of its majority source utt.
256
+
257
+ The bag-of-words rough pass picks a window that maximises multiset
258
+ overlap with the gold utterance. Two failure modes follow from that:
259
+
260
+ 1. **Trailing overshoot.** The window grows past the natural endpoint
261
+ to grab a stray matching token from the *next* gold utterance,
262
+ which then starves that next utterance and cascades misalignment.
263
+ 2. **Leading skip.** A genuine leading main token (e.g. main "she" vs
264
+ gold "he", a substitution) doesn't match anything in gold's bag, so
265
+ the rough pass picks a window starting one position later. The
266
+ skipped token then falls into the gap between iterations and is
267
+ lost — neither this utterance nor the next picks it up.
268
+
269
+ Both are detectable from the source main-utterance index already
270
+ carried in ``main_info``: tokens that share the window's majority utt
271
+ belong with this gold utterance; tokens from a different utt do not.
272
+
273
+ *Trailing* is the easy direction: pull ``abs_end`` inward while the
274
+ last token isn't from the majority utt — that strips next-utt bleed.
275
+
276
+ *Leading* needs more care. Walking left through every same-utt token
277
+ would break the bag-of-words ``latest end position`` tiebreaker that
278
+ the rough pass relies on for repetitions (e.g. main "the cat sat the
279
+ cat sat" / gold "the cat sat" — the first copy is often a prompt /
280
+ example utterance, and the rough pass deliberately picks the second).
281
+ So we bound the leftward walk by the count of *leading*
282
+ Extra(REFERENCE) items in the alignment: that's the number of gold
283
+ tokens unmatched at the start, which is exactly the room for
284
+ substitution material to the left. A clean second-occurrence
285
+ repetition aligns with zero leading REFs, so no extension occurs.
286
+ A leading substitution like main "she" vs gold "he" yields one
287
+ leading REF, so we pull in exactly that one token.
288
+
289
+ Source-utt awareness rather than alignment shape is the signal for
290
+ the trailing trim: a pure-Extra(PAYLOAD)-tail rule would also clip
291
+ legitimate intra-utt end-of-utterance substitutions (main "slept" vs
292
+ gold "sat") because DP often places the unmatched main token last.
293
+ """
294
+ if abs_end <= abs_start:
295
+ return abs_start, abs_end
296
+
297
+ window_utts = [
298
+ main_info[main_map[abs_start + k]][0]
299
+ for k in range(abs_end - abs_start)
300
+ ]
301
+ majority = Counter(window_utts).most_common(1)[0][0]
302
+
303
+ while abs_end > abs_start and main_info[main_map[abs_end - 1]][0] != majority:
304
+ abs_end -= 1
305
+
306
+ if abs_end <= abs_start:
307
+ return abs_start, abs_end
308
+
309
+ # Leading extension is bounded by the number of unmatched gold tokens
310
+ # at the start of the alignment. This preserves the latest-tiebreaker
311
+ # for repetitions while still recovering leading substitutions.
312
+ window_main = conformed_main[abs_start:abs_end]
313
+ alignment = align(window_main, gold_tokens, False, mfn)
314
+ leading_refs = 0
315
+ for item in alignment:
316
+ if isinstance(item, Extra) and item.extra_type == ExtraType.REFERENCE:
317
+ leading_refs += 1
318
+ else:
319
+ break
320
+
321
+ extended = 0
322
+ while (extended < leading_refs
323
+ and abs_start > search_start
324
+ and main_info[main_map[abs_start - 1]][0] == majority):
325
+ abs_start -= 1
326
+ extended += 1
327
+
328
+ return abs_start, abs_end
329
+
330
+
235
331
  def _best_rotation(window_tokens, gold_tokens, mfn):
236
332
  """Find the cyclic rotation of *window_tokens* that maximises matches.
237
333
 
@@ -357,6 +453,11 @@ class CompareEngine(BatchalignEngine):
357
453
  conformed_main, main_map = conform_with_mapping(main_words, conform)
358
454
  conformed_gold, gold_map = conform_with_mapping(gold_words, conform)
359
455
 
456
+ # Source main-utterance index for each conformed main token. Used
457
+ # both inside the rough search (to score windows on their effective
458
+ # post-trim form) and afterwards by the snap pass.
459
+ main_utts = [main_info[idx][0] for idx in main_map]
460
+
360
461
  # --- 4. Partition conformed gold tokens by utterance ---
361
462
  gold_utt_tokens = {i: [] for i in range(len(gold_utterances))}
362
463
  gold_utt_maps = {i: [] for i in range(len(gold_utterances))}
@@ -386,11 +487,27 @@ class CompareEngine(BatchalignEngine):
386
487
  continue
387
488
 
388
489
  remaining_main = conformed_main[search_start:]
389
- win_start, win_end = _find_best_segment(g_tokens, remaining_main, match_fn)
490
+ remaining_utts = main_utts[search_start:]
491
+ win_start, win_end = _find_best_segment(
492
+ g_tokens, remaining_main, remaining_utts, match_fn
493
+ )
390
494
 
391
495
  abs_start = search_start + win_start
392
496
  abs_end = search_start + win_end
393
497
 
498
+ # Snap the rough window to the source main-utterance boundary
499
+ # of its majority — extends leftward (bounded by leading
500
+ # alignment-REF count, so the latest-tiebreaker for in-utt
501
+ # repetitions is preserved) to absorb leading substitutions
502
+ # the bag-of-words pass skipped, and trims trailing tokens
503
+ # that bled in from the next main utt.
504
+ abs_start, abs_end = _snap_window_to_majority_utt(
505
+ abs_start, abs_end, search_start,
506
+ conformed_main, main_map, main_info,
507
+ g_tokens, match_fn,
508
+ )
509
+ window_main = conformed_main[abs_start:abs_end]
510
+
394
511
  # Collect unique main forms in the window (deduplicate
395
512
  # across conformed expansions that map to the same form)
396
513
  seen_main = set()
@@ -404,9 +521,8 @@ class CompareEngine(BatchalignEngine):
404
521
 
405
522
  # Align the chosen window against this gold utterance,
406
523
  # trying cyclic rotations to avoid spurious del/ins pairs.
407
- window_main = conformed_main[abs_start:abs_end]
408
524
  window_len = len(window_main)
409
- rotation = _best_rotation(window_main, g_tokens, match_fn)
525
+ rotation = _best_rotation(window_main, g_tokens, match_fn) if window_len > 0 else 0
410
526
  if rotation > 0:
411
527
  window_main = window_main[rotation:] + window_main[:rotation]
412
528
  utt_alignment = align(window_main, g_tokens, False, match_fn)
@@ -47,9 +47,25 @@ class PyannoteEngine(BatchalignEngine):
47
47
 
48
48
  def process(self, doc: Document, **kwargs) -> Document:
49
49
  if self.pipe is None:
50
- from pyannote.audio import Pipeline
51
- self.pipe = Pipeline.from_pretrained("talkbank/dia-fork")
50
+ # torch>=2.6 defaults torch.load(weights_only=True), which rejects
51
+ # pyannote 3.x checkpoints that pickle TorchVersion/Specifications/etc.
52
+ # The pyannote checkpoint comes from a trusted HF repo, so force
53
+ # weights_only=False for the duration of the pipeline load.
54
+ import torch
55
+ _orig_torch_load = torch.load
56
+ def _patched_load(*args, **kwargs):
57
+ kwargs["weights_only"] = False
58
+ return _orig_torch_load(*args, **kwargs)
59
+ torch.load = _patched_load
60
+ try:
61
+ from pyannote.audio import Pipeline
62
+ self.pipe = Pipeline.from_pretrained("talkbank/dia-fork")
63
+ finally:
64
+ torch.load = _orig_torch_load
52
65
  assert doc.media != None and doc.media.url != None, f"We cannot diarize something that doesn't have a media path! Provided media tier='{doc.media}'"
66
+ if not doc.tiers:
67
+ L.warning("Skipping diarization: upstream ASR produced no tiers/utterances.")
68
+ return doc
53
69
  res = self.pipe(doc.media.url, num_speakers=self.num_speakers)
54
70
 
55
71
  speakers = list(set([int(i[-1].split("_")[-1])
@@ -0,0 +1,3 @@
1
+ 0.8.2-post.15
2
+ May 2nd 2026
3
+ more compare fixes
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: batchalign
3
- Version: 0.8.2.post13
3
+ Version: 0.8.2.post15
4
4
  Summary: Python Speech Language Sample Analysis
5
5
  Author: Brian MacWhinney, Houjun Liu
6
6
  Author-email: macw@cmu.edu, houjun@cmu.edu
@@ -19,15 +19,15 @@ Requires-Dist: platformdirs>=4.3.0
19
19
  Requires-Dist: filelock>=3.0.0
20
20
  Requires-Dist: nltk>=3.8
21
21
  Requires-Dist: praatio<6.1.0,>=6.0.0
22
- Requires-Dist: torch>=2.10.0
23
- Requires-Dist: torchaudio>=2.10.0
22
+ Requires-Dist: torch<2.9,>=2.7
23
+ Requires-Dist: torchaudio<2.9,>=2.7
24
24
  Requires-Dist: soundfile>=0.12.0
25
25
  Requires-Dist: pydub
26
26
  Requires-Dist: plotly>=5.3.0
27
- Requires-Dist: transformers>=4.38.2
27
+ Requires-Dist: transformers<5,>=4.38.2
28
28
  Requires-Dist: tokenizers>=0.14.1
29
29
  Requires-Dist: numba>=0.61.0
30
- Requires-Dist: numpy<=2.2
30
+ Requires-Dist: numpy<2.3,>=1.24
31
31
  Requires-Dist: pycountry>=22.3
32
32
  Requires-Dist: stanza[transformers]>=1.10.1
33
33
  Requires-Dist: scipy~=1.11
@@ -50,7 +50,7 @@ Requires-Dist: openai-whisper
50
50
  Requires-Dist: llvmlite>=0.44.0
51
51
  Requires-Dist: praat-parselmouth==0.4.6
52
52
  Requires-Dist: opensmile>=2.5.0
53
- Requires-Dist: pyannote.audio
53
+ Requires-Dist: pyannote.audio<4,>=3.4.0
54
54
  Requires-Dist: onnxruntime
55
55
  Requires-Dist: certifi>=2025.10.5
56
56
  Provides-Extra: dev
@@ -63,6 +63,16 @@ Requires-Dist: accelerate~=0.27; extra == "train"
63
63
  Provides-Extra: docs
64
64
  Requires-Dist: mkdocs-material; extra == "docs"
65
65
  Requires-Dist: mkdocs-click; extra == "docs"
66
+ Dynamic: author
67
+ Dynamic: author-email
68
+ Dynamic: classifier
69
+ Dynamic: description
70
+ Dynamic: description-content-type
71
+ Dynamic: license-file
72
+ Dynamic: provides-extra
73
+ Dynamic: requires-dist
74
+ Dynamic: requires-python
75
+ Dynamic: summary
66
76
 
67
77
  # TalkBank | Batchalign2
68
78
 
@@ -3,15 +3,15 @@ platformdirs>=4.3.0
3
3
  filelock>=3.0.0
4
4
  nltk>=3.8
5
5
  praatio<6.1.0,>=6.0.0
6
- torch>=2.10.0
7
- torchaudio>=2.10.0
6
+ torch<2.9,>=2.7
7
+ torchaudio<2.9,>=2.7
8
8
  soundfile>=0.12.0
9
9
  pydub
10
10
  plotly>=5.3.0
11
- transformers>=4.38.2
11
+ transformers<5,>=4.38.2
12
12
  tokenizers>=0.14.1
13
13
  numba>=0.61.0
14
- numpy<=2.2
14
+ numpy<2.3,>=1.24
15
15
  pycountry>=22.3
16
16
  stanza[transformers]>=1.10.1
17
17
  scipy~=1.11
@@ -34,7 +34,7 @@ openai-whisper
34
34
  llvmlite>=0.44.0
35
35
  praat-parselmouth==0.4.6
36
36
  opensmile>=2.5.0
37
- pyannote.audio
37
+ pyannote.audio<4,>=3.4.0
38
38
  onnxruntime
39
39
  certifi>=2025.10.5
40
40
 
@@ -31,8 +31,8 @@ setup(
31
31
  "filelock>=3.0.0",
32
32
  "nltk>=3.8",
33
33
  "praatio>=6.0.0,<6.1.0",
34
- "torch>=2.10.0",
35
- "torchaudio>=2.10.0", # Only uses transforms/functional/pipelines (I/O via soundfile)
34
+ "torch>=2.7,<2.9",
35
+ "torchaudio>=2.7,<2.9", # <2.9: keep list_audio_backends; <2.10: keep AudioMetaData — needed by pyannote.audio 3.x (torch.load weights_only patched in batchalign.pipelines.diarization.pyannote)
36
36
  "soundfile>=0.12.0", # Audio I/O backend (replaces torchaudio.load/save/info)
37
37
  # "pyAudioAnalysis",
38
38
  # "hmmlearn==0.3.0",
@@ -40,10 +40,10 @@ setup(
40
40
  "pydub",
41
41
  # "imblearn",
42
42
  "plotly>=5.3.0",
43
- "transformers>=4.38.2",
43
+ "transformers>=4.38.2,<5",
44
44
  "tokenizers>=0.14.1",
45
45
  "numba>=0.61.0",
46
- "numpy<=2.2",
46
+ "numpy>=1.24,<2.3",
47
47
  "pycountry>=22.3",
48
48
  "stanza[transformers]>=1.10.1",
49
49
  "scipy~=1.11",
@@ -66,7 +66,7 @@ setup(
66
66
  "llvmlite>=0.44.0",
67
67
  "praat-parselmouth==0.4.6",
68
68
  "opensmile>=2.5.0",
69
- "pyannote.audio",
69
+ "pyannote.audio>=3.4.0,<4",
70
70
  "onnxruntime",
71
71
  "certifi>=2025.10.5"
72
72
  ],
@@ -1,3 +0,0 @@
1
- 0.8.2-post.13
2
- April 17 2026
3
- compare update, again