py-roller 0.4.0__py3-none-any.whl

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 (56) hide show
  1. py_roller-0.4.0.dist-info/METADATA +472 -0
  2. py_roller-0.4.0.dist-info/RECORD +56 -0
  3. py_roller-0.4.0.dist-info/WHEEL +5 -0
  4. py_roller-0.4.0.dist-info/entry_points.txt +2 -0
  5. py_roller-0.4.0.dist-info/top_level.txt +1 -0
  6. pyroller/__init__.py +2 -0
  7. pyroller/aligner/__init__.py +10 -0
  8. pyroller/aligner/base.py +16 -0
  9. pyroller/aligner/common.py +470 -0
  10. pyroller/aligner/global_dp_v1.py +432 -0
  11. pyroller/aligner/registry.py +33 -0
  12. pyroller/batch.py +482 -0
  13. pyroller/cli/__init__.py +1 -0
  14. pyroller/cli/__main__.py +4 -0
  15. pyroller/cli/config.py +141 -0
  16. pyroller/cli/main.py +383 -0
  17. pyroller/domain/__init__.py +35 -0
  18. pyroller/domain/models.py +360 -0
  19. pyroller/filter/__init__.py +15 -0
  20. pyroller/filter/base.py +16 -0
  21. pyroller/filter/chain.py +64 -0
  22. pyroller/filter/dereverb_nara_wpe.py +155 -0
  23. pyroller/filter/noise_gate.py +151 -0
  24. pyroller/filter/registry.py +46 -0
  25. pyroller/logging_utils.py +48 -0
  26. pyroller/parser/__init__.py +16 -0
  27. pyroller/parser/base.py +15 -0
  28. pyroller/parser/en_arpabet.py +63 -0
  29. pyroller/parser/mul_ipa.py +99 -0
  30. pyroller/parser/registry.py +71 -0
  31. pyroller/parser/zh_pinyin.py +59 -0
  32. pyroller/parser/zh_router_pinyin.py +114 -0
  33. pyroller/pipeline/__init__.py +3 -0
  34. pyroller/pipeline/runner.py +616 -0
  35. pyroller/process_control.py +100 -0
  36. pyroller/progress.py +117 -0
  37. pyroller/splitter/__init__.py +4 -0
  38. pyroller/splitter/base.py +17 -0
  39. pyroller/splitter/demucs.py +61 -0
  40. pyroller/transcriber/__init__.py +16 -0
  41. pyroller/transcriber/base.py +16 -0
  42. pyroller/transcriber/en_whisperx.py +194 -0
  43. pyroller/transcriber/mms_phonetic.py +365 -0
  44. pyroller/transcriber/mul_wav2vec2_phoneme.py +330 -0
  45. pyroller/transcriber/registry.py +103 -0
  46. pyroller/transcriber/whisperx.py +202 -0
  47. pyroller/utils/__init__.py +4 -0
  48. pyroller/utils/ids.py +7 -0
  49. pyroller/utils/json.py +25 -0
  50. pyroller/utils/text.py +1294 -0
  51. pyroller/utils/time.py +30 -0
  52. pyroller/writer/__init__.py +12 -0
  53. pyroller/writer/ass_karaoke.py +139 -0
  54. pyroller/writer/base.py +12 -0
  55. pyroller/writer/lrc.py +97 -0
  56. pyroller/writer/registry.py +41 -0
@@ -0,0 +1,472 @@
1
+ Metadata-Version: 2.4
2
+ Name: py-roller
3
+ Version: 0.4.0
4
+ Summary: Composable lyric-audio alignment pipeline with staged execution, batch processing, and LRC/ASS export.
5
+ Author: OpenAI scaffolding for David Peterson
6
+ License: MIT
7
+ Keywords: lyrics,subtitle,karaoke,alignment,audio,lrc,ass,cli,batch,transcription
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Intended Audience :: End Users/Desktop
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Multimedia :: Sound/Audio
19
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
20
+ Classifier: Topic :: Text Processing
21
+ Classifier: Topic :: Utilities
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: pypinyin>=0.50.0
25
+ Requires-Dist: opencc-python-reimplemented>=0.1.7
26
+ Requires-Dist: pronouncing>=0.2.0
27
+ Requires-Dist: phonemizer>=3.3.0
28
+ Requires-Dist: gruut[ar,ru]>=2.4.0
29
+ Requires-Dist: PyYAML>=6.0
30
+ Requires-Dist: tqdm>=4.66.0
31
+ Provides-Extra: audio
32
+ Requires-Dist: demucs>=4.0.1; extra == "audio"
33
+ Requires-Dist: whisperx>=3.1.1; extra == "audio"
34
+ Requires-Dist: torch>=2.2.0; extra == "audio"
35
+ Requires-Dist: librosa>=0.10.0; extra == "audio"
36
+ Requires-Dist: transformers>=4.39.0; extra == "audio"
37
+ Requires-Dist: numpy>=1.24.0; extra == "audio"
38
+ Requires-Dist: soundfile>=0.12.1; extra == "audio"
39
+ Requires-Dist: scipy>=1.10.0; extra == "audio"
40
+ Requires-Dist: bottleneck>=1.3.8; extra == "audio"
41
+ Requires-Dist: nara_wpe>=0.0.11; extra == "audio"
42
+
43
+ # py-roller
44
+
45
+ `py-roller` is a CLI Solution for automatic rolling lyrics generating.
46
+
47
+ To be specific, `py-roller` is a composable lyric-audio alignment pipeline CLI for staged execution, batch processing, and LRC/ASS export. Designed to support multiple transcriber back-ends including WhisperX and wav2vec2.
48
+
49
+ - Package name: `py-roller`
50
+ - CLI command: `py-roller`
51
+ - Python import package: `pyroller`
52
+
53
+ ## Quick overview
54
+
55
+ `py-roller` treats alignment as a contiguous stage chain:
56
+
57
+ ```text
58
+ s -> f -> t -> p -> a -> w
59
+ splitter -> filter -> transcriber -> parser -> aligner -> writer
60
+ ```
61
+
62
+ Core modes:
63
+
64
+ - `run`: execute one contiguous stage chain for one task
65
+ - `batch`: execute the same contiguous stage chain across many tasks
66
+
67
+ Core artifact types:
68
+
69
+ - input audio / lyrics
70
+ - intermediate vocal and filtered audio
71
+ - `timed_units`
72
+ - `parsed_lyrics`
73
+ - `alignment_result`
74
+ - written outputs such as LRC or ASS
75
+
76
+ ## Installation
77
+
78
+ From source:
79
+
80
+ ```bash
81
+ pip install .
82
+ ```
83
+
84
+ With audio backends and heavy model dependencies:
85
+
86
+ ```bash
87
+ pip install .[audio]
88
+ ```
89
+
90
+ After installation, the CLI command is:
91
+
92
+ ```bash
93
+ py-roller
94
+ ```
95
+
96
+ ## Quick start
97
+
98
+ ### Full pipeline: audio + lyrics -> LRC
99
+
100
+ ```bash
101
+ py-roller run \
102
+ --stages s,f,t,p,a,w \
103
+ --audio ./song.mp3 \
104
+ --lyrics ./song.txt \
105
+ --filter-chain noise_gate,dereverb \
106
+ --output-written ./song.lrc
107
+ --language zh # Choose as you like
108
+ ```
109
+
110
+ ### Start from a prepared vocal track
111
+
112
+ ```bash
113
+ py-roller run \
114
+ --stages t,p,a,w \
115
+ --audio ./vocals.wav \
116
+ --lyrics ./song.txt \
117
+ --writer-backend ass_karaoke \
118
+ --output-written ./song.ass
119
+ --language zh # Choose as you like
120
+ ```
121
+
122
+ ### Batch processing by stem
123
+
124
+ ```bash
125
+ py-roller batch \
126
+ --stages t,p,a,w \
127
+ --audio ./audio_dir \
128
+ --lyrics ./lyrics_dir \
129
+ --output-written ./out_dir
130
+ --language zh # Choose as you like
131
+ ```
132
+
133
+ ## Core execution model
134
+
135
+ ### Contiguous stage chains only
136
+
137
+ The CLI only accepts contiguous subchains of the canonical order.
138
+
139
+ Valid examples:
140
+
141
+ - `s,f,t,p,a,w`
142
+ - `t,p,a,w`
143
+ - `a,w`
144
+ - `w`
145
+
146
+ Invalid examples:
147
+
148
+ - `s,t,w`
149
+ - `s,p,a`
150
+
151
+ ### Legal chain starts
152
+
153
+ Explicit artifact inputs are only valid at the correct chain start:
154
+
155
+ - `--audio` is valid when the chain starts at `s`, `f`, or `t`
156
+ - `--lyrics` is valid when the chain includes `p`
157
+ - `--timed-units` and `--parsed-lyrics` are only valid when the chain starts at `a`
158
+ - `--alignment-result` is only valid when the chain starts at `w`
159
+
160
+ ### Final outputs vs intermediate artifacts
161
+
162
+ Final user-requested outputs are only the explicit `--output-*` paths:
163
+
164
+ - `--output-vocal-audio`
165
+ - `--output-filtered-audio`
166
+ - `--output-timed-units`
167
+ - `--output-parsed-lyrics`
168
+ - `--output-alignment-result`
169
+ - `--output-written`
170
+
171
+ Everything else created under `--intermediate` is treated as intermediate state.
172
+
173
+ ## Common workflows
174
+
175
+ ### Start from raw audio
176
+
177
+ Use the full chain when you want splitting, filtering, transcription, alignment, and final writing in one command.
178
+
179
+ ```bash
180
+ py-roller run \
181
+ --stages s,f,t,p,a,w \
182
+ --audio ./song.mp3 \
183
+ --lyrics ./song.txt \
184
+ --output-written ./song.lrc
185
+ ```
186
+
187
+ ### Start from filtered or vocal audio
188
+
189
+ Skip splitter/filter when you already have a suitable track for transcription.
190
+
191
+ ```bash
192
+ py-roller run \
193
+ --stages t,p,a,w \
194
+ --audio ./vocals.wav \
195
+ --lyrics ./song.txt \
196
+ --output-written ./song.lrc
197
+ ```
198
+
199
+ ### Start from aligner artifacts
200
+
201
+ ```bash
202
+ py-roller run \
203
+ --stages a,w \
204
+ --timed-units ./song.timed_units.json \
205
+ --parsed-lyrics ./song.parsed_lyrics.json \
206
+ --output-written ./song.lrc
207
+ ```
208
+
209
+ ### Rewrite only from an existing alignment result
210
+
211
+ ```bash
212
+ py-roller run \
213
+ --stages w \
214
+ --alignment-result ./song.alignment.json \
215
+ --writer-backend ass_karaoke \
216
+ --output-written ./song.ass
217
+ ```
218
+
219
+ ## Backend defaults
220
+
221
+ Default backend selection is language-aware. Please note that the default selection of language is "mul" which works poorly when tested on both Chinese and English, please use the `--language` flag to specify the desired language if the language is directly supported.
222
+
223
+ ### Transcriber defaults
224
+
225
+ - `zh` -> `mms_phonetic`
226
+ - `en` -> `whisperx`
227
+ - `mul` -> `wav2vec2_phoneme`
228
+
229
+ ### Parser defaults
230
+
231
+ - `zh` -> `zh_router_pinyin`
232
+ - `en` -> `en_arpabet`
233
+ - `mul` -> `mul_ipa`
234
+
235
+ ### Other defaults
236
+
237
+ - aligner backend -> `global_dp_v1`
238
+ - writer backend -> `lrc_ms`
239
+ - language -> `mul`
240
+ - `reserve_spacing` -> enabled
241
+ - `cleanup` -> `on-success`
242
+
243
+ ## Writer behavior
244
+
245
+ ### LRC
246
+
247
+ The default writer is `lrc_ms` which writes LRC lines with millisecond precision. Other supported writer backends are:
248
+
249
+ - `lrc_cs`: writes LRC lines with centiscond precision
250
+ - `lrc_compressed`: writes LRC lines with millisecond precision, but compresses consecutive lines with the same timestamp
251
+ - `ass_karaoke`: see below
252
+
253
+ ### ASS karaoke
254
+
255
+ `ass_karaoke` writes ASS dialogue lines with karaoke timing tags.
256
+
257
+ Current defaults:
258
+
259
+ - structural / spacing lines are skipped by default
260
+ - display end time prefers matched unit timing instead of blindly extending to the next line
261
+ - unmatched lines receive a short visible duration fallback
262
+
263
+ Example:
264
+
265
+ ```bash
266
+ py-roller run \
267
+ --stages w \
268
+ --alignment-result ./song.alignment.json \
269
+ --writer-backend ass_karaoke \
270
+ --output-written ./song.ass
271
+ ```
272
+
273
+ ## Progress reporting
274
+
275
+ The project exposes a reusable progress-reporting interface so CLI and future GUI frontends can share the same stage updates.
276
+
277
+ Current behavior:
278
+
279
+ - splitter: Demucs progress plus wrapper stage progress
280
+ - filter: phase progress
281
+ - transcriber: phase progress
282
+ - aligner: phase progress plus DP row progress
283
+
284
+ In single-task `run`, progress is shown as CLI progress bars when the terminal supports it. In `batch`, per-task progress is logged to avoid multiple workers fighting for one terminal.
285
+
286
+ ## Intermediate files and cleanup
287
+
288
+ Intermediate files live under:
289
+
290
+ ```text
291
+ --intermediate/<task-id>/splitter
292
+ --intermediate/<task-id>/filter
293
+ --intermediate/<task-id>/logs
294
+ ```
295
+
296
+ Default intermediate root:
297
+
298
+ ```text
299
+ <system temp>/py-roller-artifacts
300
+ ```
301
+
302
+ Cleanup policy:
303
+
304
+ - `--cleanup on-success` keeps successful runs tidy by removing per-task intermediate directories
305
+ - `--cleanup never` keeps intermediate audio and logs for inspection
306
+
307
+ ## Batch mode
308
+
309
+ `batch` uses the same stage semantics as `run`, but applies them to many tasks.
310
+
311
+ ### Directory pairing
312
+
313
+ Directory mode currently supports:
314
+
315
+ ```text
316
+ --pair-by stem
317
+ ```
318
+
319
+ Default candidate globs:
320
+
321
+ - `--audio-glob "*.mp3"`
322
+ - `--lyrics-glob "*.txt"`
323
+
324
+ Matching is non-recursive.
325
+
326
+ Example:
327
+
328
+ ```bash
329
+ py-roller batch \
330
+ --stages t,p,a,w \
331
+ --audio ./audio_dir \
332
+ --lyrics ./lyrics_dir \
333
+ --output-written ./out_dir
334
+ ```
335
+
336
+ ### Batch controls
337
+
338
+ - `--jobs N`: maximum number of parallel workers
339
+ - `--continue-on-error`: keep processing remaining tasks after failures
340
+ - `--skip-existing`: skip tasks whose declared final outputs already exist
341
+ - `--manifest jobs.yaml`: load explicit per-task paths from YAML instead of pairing by stem
342
+
343
+ ### Parallelism guidance
344
+
345
+ `--jobs` controls how many tasks run at the same time. This is separate from any model-level batch size.
346
+
347
+ Recommended starting point:
348
+
349
+ - CPU-only: `--jobs 1` or `--jobs 2`
350
+ - single GPU: usually `--jobs 1`
351
+
352
+ ## YAML manifest format
353
+
354
+ Manifest mode is useful when filenames do not match cleanly by stem.
355
+
356
+ The manifest defines per-task input and output paths only. It does not override stage selection, language, backend choice, filter settings, jobs, or other batch-level options.
357
+
358
+ Supported top-level forms:
359
+
360
+ ```yaml
361
+ tasks:
362
+ - id: song01
363
+ audio: ./audio/song01_master.mp3
364
+ lyrics: ./lyrics/song01_final.txt
365
+ output_written: ./out/song01.lrc
366
+ ```
367
+
368
+ or:
369
+
370
+ ```yaml
371
+ - id: song01
372
+ audio: ./audio/song01_master.mp3
373
+ lyrics: ./lyrics/song01_final.txt
374
+ output_written: ./out/song01.lrc
375
+ ```
376
+
377
+ Allowed manifest input keys:
378
+
379
+ - `audio`
380
+ - `lyrics`
381
+ - `timed_units`
382
+ - `parsed_lyrics`
383
+ - `alignment_result`
384
+
385
+ Allowed manifest output keys:
386
+
387
+ - `output_vocal_audio`
388
+ - `output_filtered_audio`
389
+ - `output_timed_units`
390
+ - `output_parsed_lyrics`
391
+ - `output_alignment_result`
392
+ - `output_written`
393
+
394
+ Optional helper key:
395
+
396
+ - `id`
397
+
398
+ Validation rules:
399
+
400
+ - each task must be a mapping
401
+ - unknown keys are rejected
402
+ - inputs must match the selected chain start
403
+ - outputs must be valid final outputs for the selected chain
404
+ - task ids / stems must be unique
405
+ - final output paths must not conflict across tasks
406
+ - relative paths are resolved relative to the manifest file location
407
+
408
+ ## YAML config for default CLI options
409
+
410
+ Use `--config` to load YAML defaults.
411
+
412
+ Priority order:
413
+
414
+ ```text
415
+ built-in defaults < config YAML < explicit CLI arguments
416
+ ```
417
+
418
+ Section model:
419
+
420
+ - `shared`: defaults applied to both `run` and `batch`
421
+ - `run`: currently no extra keys beyond `shared`
422
+ - `batch`: defaults for batch-only options such as `jobs` and `skip_existing`
423
+
424
+ Example:
425
+
426
+ ```yaml
427
+ shared:
428
+ language: mul
429
+ reserve_spacing: true
430
+ writer_backend: lrc_ms
431
+ intermediate: ./tmp/py-roller-artifacts
432
+ cleanup: on-success
433
+ transcriber_device: cpu
434
+ splitter_demucs_model: htdemucs
435
+ filter_chain:
436
+ - noise_gate
437
+ - dereverb
438
+
439
+ batch:
440
+ jobs: 2
441
+ audio_glob: "*.mp3"
442
+ lyrics_glob: "*.txt"
443
+ continue_on_error: true
444
+ ```
445
+
446
+ `filter_chain` can be written either as a comma-separated string or as a YAML list.
447
+
448
+ ## Troubleshooting
449
+
450
+ ### Interruption and child process cleanup
451
+
452
+ Batch fail-fast actively stops launching further work after the first task failure when `--continue-on-error` is not set, and worker cleanup includes a Windows-specific process-tree branch.
453
+
454
+ For older runs or already orphaned processes, Linux/macOS cleanup examples are still useful:
455
+
456
+ ```bash
457
+ pkill -TERM -f 'python .*pyroller'
458
+ pkill -TERM -f 'demucs.separate|demucs'
459
+ ```
460
+
461
+ If anything still survives:
462
+
463
+ ```bash
464
+ pkill -KILL -f 'python .*pyroller'
465
+ pkill -KILL -f 'demucs.separate|demucs'
466
+ ```
467
+
468
+ Inspect candidates first with:
469
+
470
+ ```bash
471
+ ps -ef | grep -E 'pyroller|demucs'
472
+ ```
@@ -0,0 +1,56 @@
1
+ pyroller/__init__.py,sha256=64K32e0xATU23z-GeH9rS9ddPNCMeQkDCaCwcY3DId4,48
2
+ pyroller/batch.py,sha256=DEsSE1ey2mT3XaG4v0imxPUD2B6CHvG3u-jFMEQXumo,20757
3
+ pyroller/logging_utils.py,sha256=00gnuiPy4D5uJZfc-nSZvAhuWQaWXY5N5EqI2osOyEA,1421
4
+ pyroller/process_control.py,sha256=Q2Bq8_d_MhIlThW0GVaJsxu753gH_OZ1byjLF1PnSzY,2850
5
+ pyroller/progress.py,sha256=x5mfdu-vwjcFQB-23V9unGbF6ZM0NBgFDgI26efesKg,3841
6
+ pyroller/aligner/__init__.py,sha256=FSVjun6xZ3Slbo9ng-yL7U9IKMoFVu1DJvmodxZ3nGE,250
7
+ pyroller/aligner/base.py,sha256=dhzbgfvfzgtgR9iTsFEt1a6tqdDS3MGRvia0fCXEluc,525
8
+ pyroller/aligner/common.py,sha256=WDyVfnFbVYTIRhtWNyR31g6sGA1J9-0HOrPYluMrM7Q,19779
9
+ pyroller/aligner/global_dp_v1.py,sha256=tw0pHTL8MnQRyOKjZ22h8vazRHt8MOInf023YTOC_Cs,19484
10
+ pyroller/aligner/registry.py,sha256=VPEBA3fDqMisep76imvkt5RDVTNOmbnZXJ4v9v5VKeQ,1177
11
+ pyroller/cli/__init__.py,sha256=juqd9PbXs4yg45zMJ7BHAOPQjb7sgEbWE9InBtGZhfo,24
12
+ pyroller/cli/__main__.py,sha256=Vdhw8YA1K3wPMlbJQYL5WqvRzAKVeZ16mZQFO9VRmCo,62
13
+ pyroller/cli/config.py,sha256=PPZQ7r-3ghdmnI8YxzR-QbtTBAqvev0gWQ50J650S60,4654
14
+ pyroller/cli/main.py,sha256=elY1zb_K7I-XnlaSizBcbhowf0h0yAJiT4myygCKey0,20088
15
+ pyroller/domain/__init__.py,sha256=Rj6FczbbzQEja5sVHFC1veL8MUDr0cMYfYFwI1iA_5I,625
16
+ pyroller/domain/models.py,sha256=CMTcrosugCoCjiY37LmUR_vXWMDd1ZIgE2MwVXmC5rQ,11460
17
+ pyroller/filter/__init__.py,sha256=iD6kpwk8uYpx8ICkJ0RQI31nScLMHOo3VCJmCRsiTK0,468
18
+ pyroller/filter/base.py,sha256=BvF4fGoY8ItU57QDulQEsJsxxbDTBmFjZyFtQl8h2qs,437
19
+ pyroller/filter/chain.py,sha256=grGLtOj64YprNY8aEkE5nHNSy2ZqXf41GpAnCEhDQ8A,2664
20
+ pyroller/filter/dereverb_nara_wpe.py,sha256=yw69rNBPt1d4H1FRnnLHoSKWg3DAganbQHP5fP4zdak,6337
21
+ pyroller/filter/noise_gate.py,sha256=WxDMXt52jM9b3DC8fObioskXjlZFWfeD-uJ8r3J9vkQ,6277
22
+ pyroller/filter/registry.py,sha256=a9OzjfgQtZbT5oRddUqNoTIeZZsX6CCLOsIZS0PtftY,1607
23
+ pyroller/parser/__init__.py,sha256=Gb7DuzGDhHw0G_MU1WXNH_qeUCxFyYB28aOn7qgBR4Q,495
24
+ pyroller/parser/base.py,sha256=SRE0488whfClcEb0CgICPGiXpt_ZYeC2TtDYdGn7NgY,395
25
+ pyroller/parser/en_arpabet.py,sha256=4GaDEUfJOBmcIFyRLHeuIapza3ojCuGd1Zvu4ynoY7U,2395
26
+ pyroller/parser/mul_ipa.py,sha256=n8Jkqo8oA0IPz66qM-xpLhDJATEsQseSBI7dTd4zfaM,4083
27
+ pyroller/parser/registry.py,sha256=jLuU0TlRDWDo3LRjPbciOBK_6dYXodXfezwrWRFkLpI,2408
28
+ pyroller/parser/zh_pinyin.py,sha256=3nPcHEkz5d-qgFcyw8k1p9UcGrkXf8JUtjNxWBwpQu4,2373
29
+ pyroller/parser/zh_router_pinyin.py,sha256=F0i1uPY2_kpZJ1s6R7dRvGEHrw20R9FLR5hT2iLQeJw,5102
30
+ pyroller/pipeline/__init__.py,sha256=srlFTEmAMjemWzNBF-izsChRjEfafq2T6DmLng4HmIw,85
31
+ pyroller/pipeline/runner.py,sha256=EhHMcq3n9qcXisG1KEVYAjSzG4b6OSvHDlwbT8Jhox4,31704
32
+ pyroller/splitter/__init__.py,sha256=ZaGX8V-WAzK4uMtoRSXuXDqbQ5DPQ16xbQQgFGhJWNg,104
33
+ pyroller/splitter/base.py,sha256=fe-xvficdywlu73o1HR8nCa_s-Tv-RKIZOrQCa28O1E,445
34
+ pyroller/splitter/demucs.py,sha256=sTIIIs39y3q1dqO2BYfBSPNl4Uu5EtKz4PdDQrQCtsw,2059
35
+ pyroller/transcriber/__init__.py,sha256=woIGykFLxMyiXHGo028o_KdAlbKZEtx5BGiM_ejIXNM,578
36
+ pyroller/transcriber/base.py,sha256=6gEiGLW5My2OzgLiF90Ckr-m3CivzDgY60y5c-sCnzI,540
37
+ pyroller/transcriber/en_whisperx.py,sha256=RAylTY4dgIncpVwsBof3tvLwhh_jfpjpSIWTQrv4uGI,8048
38
+ pyroller/transcriber/mms_phonetic.py,sha256=qZCbOs8VrLe64nOxkRxB9f88Jg2keTbuFDjF0eVXJes,15120
39
+ pyroller/transcriber/mul_wav2vec2_phoneme.py,sha256=sacRB5KLojsu1bgOf4VsdXONkDD6F7Mce3ZbfcuB32g,12826
40
+ pyroller/transcriber/registry.py,sha256=tcW6hHBkMCAA4qEz2yo-GirQTW1ZWah46QV1I5Hpuwg,3955
41
+ pyroller/transcriber/whisperx.py,sha256=dC7NdAZZChw4q3c2DTyoy9P6HnDCh52r0S-qdz7_Nek,8215
42
+ pyroller/utils/__init__.py,sha256=wBvwwcI-PRMSG9moT_mL87KdVJlfRAOHsz3CCQsMmpg,91
43
+ pyroller/utils/ids.py,sha256=1FmjmDsRf6wzM5EVolA-212xCZIYrSzjnro-3EO27UM,130
44
+ pyroller/utils/json.py,sha256=q6mpIj06upA8mIjsBuZSc4WLDxCgTd7Y8S4hJj3K3Jo,654
45
+ pyroller/utils/text.py,sha256=IyUPks1yy24i1JK4SnWI7WNQoro6zsAsR8BLspPusgo,37072
46
+ pyroller/utils/time.py,sha256=PlTlSTj1qqzvEJC-JqEfjmJk68zyaG5p71j8Nl37aKw,942
47
+ pyroller/writer/__init__.py,sha256=kIrq2Ej-KdqpVMJbeslHJT6UzSGeDGGkErWdl--LM2I,289
48
+ pyroller/writer/ass_karaoke.py,sha256=HA3IYLETCH119IKduWksLqcMzSHf1RmccTaphx5Qu0o,5376
49
+ pyroller/writer/base.py,sha256=kW-r_emRzojlBjsX0vLnyU-kARYeU-ZFsqw8AV-MBjM,313
50
+ pyroller/writer/lrc.py,sha256=kwWWqddSYjAaWEbjUgkDu8pyxw56uQ0JqI6YxCWOSaI,4002
51
+ pyroller/writer/registry.py,sha256=Ollbm3c_-AEa8AW0Oy_oy5M2BiPlaYMExOia40dV37A,1643
52
+ py_roller-0.4.0.dist-info/METADATA,sha256=l1QCkhoFcAYqU6ao0wKdTGwb2KZHUeW4zPmvEyEe618,11560
53
+ py_roller-0.4.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
54
+ py_roller-0.4.0.dist-info/entry_points.txt,sha256=leTOy5j6XuYvi7W2Ao_-aYVQJXAu-GQXTi35EWoD5xU,53
55
+ py_roller-0.4.0.dist-info/top_level.txt,sha256=CPPRlFDCiTdYsa0ok7daAxQYUR33XtDodyju4qogpis,9
56
+ py_roller-0.4.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ py-roller = pyroller.cli.main:main
@@ -0,0 +1 @@
1
+ pyroller
pyroller/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ __all__ = ["__version__"]
2
+ __version__ = "0.4.0"
@@ -0,0 +1,10 @@
1
+ from .base import Aligner
2
+ from .global_dp_v1 import GlobalDPAligner
3
+ from .registry import build_aligner, list_available_aligner_backends
4
+
5
+ __all__ = [
6
+ "Aligner",
7
+ "GlobalDPAligner",
8
+ "build_aligner",
9
+ "list_available_aligner_backends",
10
+ ]
@@ -0,0 +1,16 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
4
+
5
+ from pyroller.domain import AlignmentResult, ParsedLyrics, TranscriptionResult
6
+ from pyroller.progress import ProgressReporter
7
+
8
+
9
+ class Aligner(ABC):
10
+ name = "aligner"
11
+ accepts = ("timed_units", "parsed_lyrics")
12
+ produces = "alignment_result"
13
+
14
+ @abstractmethod
15
+ def align(self, transcription: TranscriptionResult, parsed_lyrics: ParsedLyrics, progress: ProgressReporter | None = None) -> AlignmentResult:
16
+ raise NotImplementedError