- Create TTSBackend abstract base class with minimal contract
- Implement KokoroTTSBackend that maintains existing behavior
- Update conversion_runner.py to use new interface
- No behavioral changes, GUI unchanged, no new features
fix: catch OverflowError in emit_text for very large numbers
Fixes#145
When text contains a very large number (e.g. a long decimal from a binary
hash), misaki's pipeline calls num2words() which raises OverflowError and
crashes the entire job. Wrap the segment iterator in try/except so the
chunk is skipped gracefully with a warning log instead of terminating.
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>
The app was crashing after importing a .txt and clicking convert because of a missing import. Fixed the imports and removed the legacy abogen.conversion module which doesn't seem necessary anymore.
The 'abogen' command now launches the PyQt6 desktop GUI which requires
display libraries not available in Docker containers. Changed the Docker
CMD to use 'abogen-web' which launches the Flask web UI.
Extracts out a BaseBookParser, PDFParser and MarkdownParser class from book_handler logic
The basic contract is that the parser classes populate 4 attributes that are used by the book_handler logic
- content_texts
- content_lengths
- book_metatdata
- processed_nav_structures (used by the method get_chapters on the BaseBookParser class)
Adds tests to validate the changes as well in tests/
Run tests from the abogen dir as follows
```bash
python -m unittest discover
```