batchalign 0.8.2.post7__tar.gz → 0.8.2.post9__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.post7/batchalign.egg-info → batchalign-0.8.2.post9}/PKG-INFO +2 -1
  2. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/cli/cli.py +26 -0
  3. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/cli/dispatch.py +8 -0
  4. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/document.py +11 -8
  5. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/analysis/compare.py +3 -1
  6. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/dispatch.py +6 -0
  7. batchalign-0.8.2.post9/batchalign/pipelines/segmentation/__init__.py +15 -0
  8. batchalign-0.8.2.post9/batchalign/pipelines/segmentation/cantonese_seg.py +109 -0
  9. batchalign-0.8.2.post9/batchalign/version +3 -0
  10. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9/batchalign.egg-info}/PKG-INFO +2 -1
  11. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign.egg-info/SOURCES.txt +2 -0
  12. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign.egg-info/requires.txt +1 -0
  13. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/setup.py +1 -0
  14. batchalign-0.8.2.post7/batchalign/version +0 -3
  15. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/LICENSE +0 -0
  16. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/MANIFEST.in +0 -0
  17. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/README.md +0 -0
  18. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/__init__.py +0 -0
  19. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/__main__.py +0 -0
  20. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/cli/__init__.py +0 -0
  21. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/cli/bench.py +0 -0
  22. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/cli/cache.py +0 -0
  23. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/constants.py +0 -0
  24. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/errors.py +0 -0
  25. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/formats/__init__.py +0 -0
  26. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/formats/base.py +0 -0
  27. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/formats/chat/__init__.py +0 -0
  28. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/formats/chat/file.py +0 -0
  29. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/formats/chat/generator.py +0 -0
  30. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/formats/chat/lexer.py +0 -0
  31. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/formats/chat/parser.py +0 -0
  32. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/formats/chat/utils.py +0 -0
  33. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/formats/textgrid/__init__.py +0 -0
  34. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/formats/textgrid/file.py +0 -0
  35. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/formats/textgrid/generator.py +0 -0
  36. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/formats/textgrid/parser.py +0 -0
  37. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/__init__.py +0 -0
  38. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/audio_io.py +0 -0
  39. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/resolve.py +0 -0
  40. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/speaker/__init__.py +0 -0
  41. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/speaker/config.yaml +0 -0
  42. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/speaker/infer.py +0 -0
  43. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/speaker/utils.py +0 -0
  44. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/training/__init__.py +0 -0
  45. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/training/run.py +0 -0
  46. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/training/utils.py +0 -0
  47. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/utils.py +0 -0
  48. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/utterance/__init__.py +0 -0
  49. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/utterance/cantonese_infer.py +0 -0
  50. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/utterance/dataset.py +0 -0
  51. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/utterance/execute.py +0 -0
  52. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/utterance/infer.py +0 -0
  53. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/utterance/prep.py +0 -0
  54. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/utterance/train.py +0 -0
  55. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/wave2vec/__init__.py +0 -0
  56. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/wave2vec/infer_fa.py +0 -0
  57. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/whisper/__init__.py +0 -0
  58. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/whisper/infer_asr.py +0 -0
  59. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/models/whisper/infer_fa.py +0 -0
  60. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/__init__.py +0 -0
  61. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/analysis/__init__.py +0 -0
  62. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/analysis/eval.py +0 -0
  63. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/__init__.py +0 -0
  64. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2chinese.py +0 -0
  65. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/__init__.py +0 -0
  66. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/deu.py +0 -0
  67. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/ell.py +0 -0
  68. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/eng.py +0 -0
  69. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/eus.py +0 -0
  70. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/fra.py +0 -0
  71. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/hrv.py +0 -0
  72. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/ind.py +0 -0
  73. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/jpn.py +0 -0
  74. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/nld.py +0 -0
  75. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/por.py +0 -0
  76. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/spa.py +0 -0
  77. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/num2lang/tha.py +0 -0
  78. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/oai_whisper.py +0 -0
  79. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/rev.py +0 -0
  80. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/utils.py +0 -0
  81. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/whisper.py +0 -0
  82. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/asr/whisperx.py +0 -0
  83. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/avqi/__init__.py +0 -0
  84. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/avqi/engine.py +0 -0
  85. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/base.py +0 -0
  86. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/cache.py +0 -0
  87. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/cleanup/__init__.py +0 -0
  88. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/cleanup/cleanup.py +0 -0
  89. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/cleanup/disfluencies.py +0 -0
  90. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/cleanup/parse_support.py +0 -0
  91. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/cleanup/retrace.py +0 -0
  92. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/cleanup/support/filled_pauses.eng +0 -0
  93. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/cleanup/support/replacements.eng +0 -0
  94. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/cleanup/support/test.test +0 -0
  95. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/diarization/__init__.py +0 -0
  96. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/diarization/pyannote.py +0 -0
  97. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/fa/__init__.py +0 -0
  98. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/fa/wave2vec_fa.py +0 -0
  99. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/fa/whisper_fa.py +0 -0
  100. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/morphosyntax/__init__.py +0 -0
  101. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/morphosyntax/coref.py +0 -0
  102. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/morphosyntax/en/irr.py +0 -0
  103. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/morphosyntax/fr/apm.py +0 -0
  104. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/morphosyntax/fr/apmn.py +0 -0
  105. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/morphosyntax/fr/case.py +0 -0
  106. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/morphosyntax/ja/verbforms.py +0 -0
  107. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/morphosyntax/ud.py +0 -0
  108. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/opensmile/__init__.py +0 -0
  109. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/opensmile/engine.py +0 -0
  110. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/pipeline.py +0 -0
  111. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/speaker/__init__.py +0 -0
  112. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/speaker/nemo_speaker.py +0 -0
  113. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/translate/__init__.py +0 -0
  114. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/translate/gtrans.py +0 -0
  115. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/translate/seamless.py +0 -0
  116. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/translate/utils.py +0 -0
  117. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/utr/__init__.py +0 -0
  118. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/utr/rev_utr.py +0 -0
  119. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/utr/utils.py +0 -0
  120. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/utr/whisper_utr.py +0 -0
  121. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/utterance/__init__.py +0 -0
  122. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/pipelines/utterance/ud_utterance.py +0 -0
  123. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/__init__.py +0 -0
  124. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/cli/test_dispatch_memory.py +0 -0
  125. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/conftest.py +0 -0
  126. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/formats/chat/test_chat_file.py +0 -0
  127. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/formats/chat/test_chat_generator.py +0 -0
  128. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/formats/chat/test_chat_lexer.py +0 -0
  129. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/formats/chat/test_chat_parser.py +0 -0
  130. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/formats/chat/test_chat_utils.py +0 -0
  131. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/formats/textgrid/test_textgrid.py +0 -0
  132. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/models/test_audio_io.py +0 -0
  133. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/models/test_audio_lazy.py +0 -0
  134. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/pipelines/analysis/test_eval.py +0 -0
  135. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/pipelines/asr/test_asr_pipeline.py +0 -0
  136. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/pipelines/asr/test_asr_utils.py +0 -0
  137. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/pipelines/cache/__init__.py +0 -0
  138. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/pipelines/cache/test_cache.py +0 -0
  139. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/pipelines/cleanup/test_disfluency.py +0 -0
  140. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/pipelines/cleanup/test_parse_support.py +0 -0
  141. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/pipelines/fa/test_fa_pipeline.py +0 -0
  142. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/pipelines/fa/test_fa_short_segments.py +0 -0
  143. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/pipelines/fixures.py +0 -0
  144. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/pipelines/test_pipeline.py +0 -0
  145. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/pipelines/test_pipeline_models.py +0 -0
  146. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/tests/test_document.py +0 -0
  147. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/utils/__init__.py +0 -0
  148. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/utils/abbrev.py +0 -0
  149. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/utils/compounds.py +0 -0
  150. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/utils/config.py +0 -0
  151. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/utils/device.py +0 -0
  152. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/utils/dp.py +0 -0
  153. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/utils/names.py +0 -0
  154. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign/utils/utils.py +0 -0
  155. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign.egg-info/dependency_links.txt +0 -0
  156. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign.egg-info/entry_points.txt +0 -0
  157. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/batchalign.egg-info/top_level.txt +0 -0
  158. {batchalign-0.8.2.post7 → batchalign-0.8.2.post9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: batchalign
3
- Version: 0.8.2.post7
3
+ Version: 0.8.2.post9
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
@@ -42,6 +42,7 @@ Requires-Dist: rich-click>=1.7.0
42
42
  Requires-Dist: typing-extensions
43
43
  Requires-Dist: num2words
44
44
  Requires-Dist: tiktoken
45
+ Requires-Dist: pycantonese
45
46
  Requires-Dist: blobfile
46
47
  Requires-Dist: sentencepiece
47
48
  Requires-Dist: googletrans
@@ -348,6 +348,32 @@ def utseg(ctx, in_dir, out_dir, lang, num_speakers, **kwargs):
348
348
  in_dir, out_dir,
349
349
  loader, writer, C)
350
350
 
351
+ #################### SEGMENT ################################
352
+
353
+ @batchalign.command()
354
+ @common_options
355
+ @click.option("--lang",
356
+ help="sample language in three-letter ISO 3166-1 alpha-3 code",
357
+ show_default=True,
358
+ default="yue",
359
+ type=str)
360
+ @click.option("--merge-abbrev/--no-merge-abbrev",
361
+ default=False, help="Merge abbreviations in output. Default: no.")
362
+ @click.pass_context
363
+ def segment(ctx, in_dir, out_dir, lang, **kwargs):
364
+ """Perform word segmentation on transcripts (Cantonese)."""
365
+ from batchalign.formats.chat import CHATFile
366
+
367
+ def loader(file):
368
+ return CHATFile(path=os.path.abspath(file)).doc
369
+
370
+ def writer(doc, output):
371
+ CHATFile(doc=doc).write(output, merge_abbrev=kwargs.get("merge_abbrev", False))
372
+
373
+ _dispatch("segment", lang, 1, ["cha"], ctx,
374
+ in_dir, out_dir,
375
+ loader, writer, C)
376
+
351
377
  #################### BENCHMARK ################################
352
378
 
353
379
  @batchalign.command()
@@ -70,6 +70,7 @@ POOL_SAFE_ENGINES = {
70
70
  "replacement",
71
71
  "ngram",
72
72
  "compare_analysis_engine",
73
+ "cantonese_seg",
73
74
  }
74
75
 
75
76
  warnings.filterwarnings('ignore', category=UserWarning, message='TypedStorage is deprecated')
@@ -234,6 +235,11 @@ def _run_pipeline_for_file(command, pipeline, file, output, loader_info, writer_
234
235
  with open(json_path, 'w') as f:
235
236
  _json.dump(metrics, f)
236
237
 
238
+ elif command == "segment":
239
+ doc = CHATFile(path=os.path.abspath(file)).doc
240
+ doc = pipeline(doc, callback=progress_callback)
241
+ CHATFile(doc=doc).write(output)
242
+
237
243
  elif command == "opensmile":
238
244
  from batchalign.document import Document
239
245
  doc = Document.new(media_path=file, lang=local_kwargs.get("lang", kwargs.get("lang", "eng")))
@@ -386,6 +392,7 @@ Cmd2Task = {
386
392
  "translate": "translate",
387
393
  "opensmile": "opensmile",
388
394
  "compare": "compare,compare_analysis",
395
+ "segment": "segment",
389
396
  }
390
397
 
391
398
  # this is the main runner used by all functions
@@ -406,6 +413,7 @@ def _dispatch(command, lang, num_speakers,
406
413
  "benchmark",
407
414
  "opensmile",
408
415
  "compare",
416
+ "segment",
409
417
  }
410
418
  if command in worker_handled:
411
419
  # Avoid pickling CLI-local loader/writer functions when the worker
@@ -27,14 +27,15 @@ class Task(IntEnum):
27
27
  DISFLUENCY_ANALYSIS = 6
28
28
  RETRACE_ANALYSIS = 7
29
29
  UTTERANCE_TIMING_RECOVERY = 8 # "bulletize"
30
- FORCED_ALIGNMENT = 9
31
- FEATURE_EXTRACT = 10
32
- MORPHOSYNTAX = 11
33
- COREF = 12
34
- WER = 13
35
- TRANSLATE = 14
36
- COMPARE = 15
37
- COMPARE_ANALYSIS = 16
30
+ WORD_SEGMENTATION = 9
31
+ FORCED_ALIGNMENT = 10
32
+ FEATURE_EXTRACT = 11
33
+ MORPHOSYNTAX = 12
34
+ COREF = 13
35
+ WER = 14
36
+ TRANSLATE = 15
37
+ COMPARE = 16
38
+ COMPARE_ANALYSIS = 17
38
39
 
39
40
 
40
41
  DEBUG__G = 0
@@ -51,6 +52,7 @@ TypeMap = {
51
52
  Task.SPEAKER_RECOGNITION: TaskType.PROCESSING,
52
53
  Task.UTTERANCE_SEGMENTATION: TaskType.PROCESSING,
53
54
  Task.UTTERANCE_TIMING_RECOVERY: TaskType.PROCESSING,
55
+ Task.WORD_SEGMENTATION: TaskType.PROCESSING,
54
56
  Task.FORCED_ALIGNMENT: TaskType.PROCESSING,
55
57
  Task.MORPHOSYNTAX: TaskType.PROCESSING,
56
58
  Task.FEATURE_EXTRACT: TaskType.ANALYSIS,
@@ -73,6 +75,7 @@ TaskFriendlyName = {
73
75
  Task.SPEAKER_RECOGNITION: "Speaker Recognition",
74
76
  Task.UTTERANCE_SEGMENTATION: "Utterance Segmentation",
75
77
  Task.UTTERANCE_TIMING_RECOVERY: "Utterance Timing Recovery",
78
+ Task.WORD_SEGMENTATION: "Word Segmentation",
76
79
  Task.FORCED_ALIGNMENT: "Forced Alignment",
77
80
  Task.MORPHOSYNTAX: "Morpho-Syntax",
78
81
  Task.FEATURE_EXTRACT: "Feature Extraction",
@@ -287,6 +287,8 @@ class CompareEngine(BatchalignEngine):
287
287
  for form_idx, form in enumerate(utt.content):
288
288
  if form.text.strip() in MOR_PUNCT + ENDING_PUNCT:
289
289
  continue
290
+ if _get_pos(form) == "PUNCT":
291
+ continue
290
292
  if form.text.strip().lower() in fillers:
291
293
  continue
292
294
  main_info.append((utt_idx, form_idx, form))
@@ -303,7 +305,7 @@ class CompareEngine(BatchalignEngine):
303
305
  for utt_idx, utt in enumerate(gold_utterances):
304
306
  gold_punct[utt_idx] = []
305
307
  for form_idx, form in enumerate(utt.content):
306
- if form.text.strip() in MOR_PUNCT + ENDING_PUNCT:
308
+ if form.text.strip() in MOR_PUNCT + ENDING_PUNCT or _get_pos(form) == "PUNCT":
307
309
  gold_punct[utt_idx].append((form_idx, form))
308
310
  continue
309
311
  if form.text.strip().lower() in fillers:
@@ -16,6 +16,7 @@ DEFAULT_PACKAGES = {
16
16
  "asr": "whisper_oai",
17
17
  "utr": "whisper_utr",
18
18
  "fa": "whisper_fa",
19
+ "segment": "cantonese_seg",
19
20
  "speaker": "pyannote",
20
21
  "morphosyntax": "stanza",
21
22
  "disfluency": "replacement",
@@ -56,6 +57,8 @@ def resolve_engine_specs(pkg_str, lang, num_speakers=None, **arg_overrides):
56
57
  if "fa" in packages:
57
58
  if "utr" not in packages:
58
59
  packages.append("utr")
60
+ if "segment" not in packages and lang == "yue":
61
+ packages.append("segment")
59
62
 
60
63
  overrides = LANGUAGE_OVERRIDE_PACKAGES.get(lang, {})
61
64
  specs = []
@@ -123,6 +126,9 @@ def dispatch_pipeline(pkg_str, lang, num_speakers=None, **arg_overrides):
123
126
  elif engine == "ngram":
124
127
  from batchalign.pipelines.cleanup import NgramRetraceEngine
125
128
  engines.append(NgramRetraceEngine())
129
+ elif engine == "cantonese_seg":
130
+ from batchalign.pipelines.segmentation import CantoneseSegmentationEngine
131
+ engines.append(CantoneseSegmentationEngine())
126
132
  elif engine == "whisper_fa":
127
133
  from batchalign.pipelines.fa import WhisperFAEngine
128
134
  engines.append(WhisperFAEngine())
@@ -0,0 +1,15 @@
1
+ """
2
+ Segmentation Pipeline Module
3
+
4
+ Provides engines for word segmentation of unsegmented text.
5
+ Uses lazy loading to avoid importing heavy dependencies until needed.
6
+ """
7
+
8
+ def __getattr__(name):
9
+ """Lazy loading for segmentation engines."""
10
+ if name == 'CantoneseSegmentationEngine':
11
+ from .cantonese_seg import CantoneseSegmentationEngine
12
+ return CantoneseSegmentationEngine
13
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
14
+
15
+ __all__ = ['CantoneseSegmentationEngine']
@@ -0,0 +1,109 @@
1
+ from batchalign.document import *
2
+ from batchalign.pipelines.base import *
3
+ from batchalign.utils.dp import *
4
+ from batchalign.constants import *
5
+
6
+ import logging
7
+ L = logging.getLogger("batchalign")
8
+
9
+
10
+ class CantoneseSegmentationEngine(BatchalignEngine):
11
+ tasks = [Task.WORD_SEGMENTATION]
12
+
13
+ def __init__(self):
14
+ import pycantonese
15
+ self.__segment = pycantonese.segment
16
+
17
+ def process(self, doc: Document, **kwargs):
18
+ # no-op for non-Cantonese
19
+ if "yue" not in doc.langs:
20
+ L.debug("CantoneseSegmentation: skipping non-Cantonese document.")
21
+ return doc
22
+
23
+ for ut in doc.content:
24
+ if not isinstance(ut, Utterance):
25
+ continue
26
+
27
+ # separate regular words from punctuation/features at the end
28
+ regular_forms = []
29
+ trailing = []
30
+ for f in ut.content:
31
+ if f.type in (TokenType.PUNCT, TokenType.FEAT, TokenType.ANNOT):
32
+ trailing.append(f)
33
+ else:
34
+ # if we already started collecting trailing punct,
35
+ # but hit another regular token, flush trailing back
36
+ if trailing:
37
+ regular_forms.extend(trailing)
38
+ trailing = []
39
+ regular_forms.append(f)
40
+
41
+ if not regular_forms:
42
+ continue
43
+
44
+ # combine all regular token text (no spaces for CJK)
45
+ original_text = "".join(f.text for f in regular_forms)
46
+ if not original_text.strip():
47
+ continue
48
+
49
+ # run pycantonese segmentation
50
+ segmented_words = self.__segment(original_text)
51
+
52
+ # use character-level DP alignment to map segmented words
53
+ # back onto original tokens
54
+ #
55
+ # reference: chars from original tokens, payload = index into regular_forms
56
+ ref_targets = []
57
+ for i, f in enumerate(regular_forms):
58
+ for ch in f.text:
59
+ ref_targets.append(ReferenceTarget(ch, payload=i))
60
+
61
+ # payload: chars from segmented words, payload = index into segmented_words
62
+ pay_targets = []
63
+ for i, word in enumerate(segmented_words):
64
+ for ch in word:
65
+ pay_targets.append(PayloadTarget(ch, payload=i))
66
+
67
+ alignments = align(pay_targets, ref_targets, tqdm=False)
68
+
69
+ # build a mapping: segmented word index -> list of original token indices
70
+ seg_to_orig: dict[int, list[int]] = {}
71
+ for elem in alignments:
72
+ if isinstance(elem, Match):
73
+ seg_to_orig.setdefault(elem.payload, []).append(elem.reference_payload)
74
+
75
+ # construct new Form objects from segmented words
76
+ new_forms = []
77
+ for seg_idx, word in enumerate(segmented_words):
78
+ orig_indices = seg_to_orig.get(seg_idx, [])
79
+
80
+ # inherit timing: start from first orig, end from last orig
81
+ time = None
82
+ if orig_indices:
83
+ first_time = regular_forms[orig_indices[0]].time
84
+ last_time = regular_forms[orig_indices[-1]].time
85
+ if first_time is not None and last_time is not None:
86
+ time = (first_time[0], last_time[1])
87
+ elif first_time is not None:
88
+ time = first_time
89
+ elif last_time is not None:
90
+ time = last_time
91
+
92
+ # determine token type from the first matched original
93
+ token_type = TokenType.REGULAR
94
+ if orig_indices:
95
+ token_type = regular_forms[orig_indices[0]].type
96
+
97
+ new_forms.append(Form(
98
+ text=word,
99
+ time=time,
100
+ type=token_type,
101
+ ))
102
+
103
+ # re-append trailing punctuation/features
104
+ new_forms.extend(trailing)
105
+ ut.content = new_forms
106
+ # clear cached text so _detokenize() regenerates from new Forms
107
+ ut.text = None
108
+
109
+ return doc
@@ -0,0 +1,3 @@
1
+ 0.8.2-post.9
2
+ April 02 2026
3
+ segment
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: batchalign
3
- Version: 0.8.2.post7
3
+ Version: 0.8.2.post9
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
@@ -42,6 +42,7 @@ Requires-Dist: rich-click>=1.7.0
42
42
  Requires-Dist: typing-extensions
43
43
  Requires-Dist: num2words
44
44
  Requires-Dist: tiktoken
45
+ Requires-Dist: pycantonese
45
46
  Requires-Dist: blobfile
46
47
  Requires-Dist: sentencepiece
47
48
  Requires-Dist: googletrans
@@ -107,6 +107,8 @@ batchalign/pipelines/morphosyntax/fr/case.py
107
107
  batchalign/pipelines/morphosyntax/ja/verbforms.py
108
108
  batchalign/pipelines/opensmile/__init__.py
109
109
  batchalign/pipelines/opensmile/engine.py
110
+ batchalign/pipelines/segmentation/__init__.py
111
+ batchalign/pipelines/segmentation/cantonese_seg.py
110
112
  batchalign/pipelines/speaker/__init__.py
111
113
  batchalign/pipelines/speaker/nemo_speaker.py
112
114
  batchalign/pipelines/translate/__init__.py
@@ -26,6 +26,7 @@ rich-click>=1.7.0
26
26
  typing-extensions
27
27
  num2words
28
28
  tiktoken
29
+ pycantonese
29
30
  blobfile
30
31
  sentencepiece
31
32
  googletrans
@@ -58,6 +58,7 @@ setup(
58
58
  "typing-extensions",
59
59
  "num2words",
60
60
  "tiktoken",
61
+ "pycantonese",
61
62
  "blobfile",
62
63
  "sentencepiece",
63
64
  "googletrans",
@@ -1,3 +0,0 @@
1
- 0.8.2-post.7
2
- April 01 2026
3
- more compare updates