- Remove _srt_time() and _ass_time() methods from ConversionThread
- Use _format_timestamp() from infrastructure/subtitle_writer.py instead
- Supports both SRT (ass=False) and ASS (ass=True) formats
- All existing tests pass
- Extract unified split pattern logic to domain/split_pattern.py
- Add get_split_pattern() function with language and subtitle_mode support
- Remove duplicated logic from pyqt/conversion.py
- Update pyqt/conversion.py to use domain.split_pattern.get_split_pattern
- Add tests/test_split_pattern.py with 20 tests covering English, CJK, Spanish, French, and pattern structure
- Create KokoroBackend class implementing TTSBackend protocol
- Move all KPipeline interaction inside KokoroBackend
- Update LoadPipelineThread to create backend via create_backend()
- Update ConversionThread and VoicePreviewThread to accept backend
- Replace np_module/kpipeline_class parameters with single backend
- Add 24 unit tests for KokoroBackend
- KPipeline is now an internal implementation detail of KokoroBackend
The upstream project moved PyQt code to abogen/pyqt/ subdirectory, making the
original feature commits non-mergeable. This commit re-applies both features
to the new file locations.
Voice Marker feature (<<VOICE:voice_name>> syntax):
- subtitle_utils.py: Added _VOICE_MARKER_PATTERN, _VOICE_MARKER_SEARCH_PATTERN,
validate_voice_name(), split_text_by_voice_markers() (with valid/invalid counts)
- pyqt/conversion.py: Added load_voice_cached(), voice marker pre-processing before
chapter loop, inner voice segment loop wrapping spaCy+TTS block, updated imports
- pyqt/gui.py: Added Insert Voice Marker button and insert_voice_marker() to TextboxDialog
Word Substitution feature (text preprocessing before TTS):
- word_substitution.py: New module (word replacements, ALL CAPS, numerals, punctuation)
- pyqt/conversion.py: apply_word_substitutions() call after clean_text()
- pyqt/gui.py: WordSubstitutionsDialog, word_sub_combo, Settings button,
on_word_sub_changed(), show_word_sub_dialog(), config persistence, queue restore
- pyqt/queued_item.py: 6 new word substitution fields
- pyqt/queue_manager_gui.py: 6 fields added to OVERRIDE_FIELDS and get_current_attributes()
Note: num2words>=0.5.13 was already added to pyproject.toml by upstream.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>