Files
epub-tts/src/epub_tts/tts_aedocw.py
T
2026-08-10 16:37:59 -03:00

126 lines
3.8 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2025-2026 Renato Xavier da Silveira Rosa
# Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
# See [LICENSE](./LICENSE) or [BSD-3-Clause-Clear](https://spdx.org/licenses/BSD-3-Clause-Clear.html)
"""Backends for the aedocw collection of EPUB->TTS repositories.
This module defines subclasses of GenericTTSBackend that provide sane
default backend command names for the aedocw repositories available on
GitHub: epub2tts, epub2tts-edge, epub2tts-chatterbox and epub2tts-kokoro.
The vendored packages are run in isolated virtual environments when the
corresponding console script is not available in the current environment.
"""
from .tts_generic import GenericTTSBackend
from . import logger, PathLike
class AedocwBackend(GenericTTSBackend):
"""Generic aedocw backend wrapper.
Parameters:
repo: repository name (one of the keys in _CMD_MAP)
backend_cmd: explicit command/executable to use (overrides repo mapping)
language: optional language code
voice: optional voice name
The GenericTTSBackend stores the default command name in self.backend_cmd,
but the vendored adapters may still run the package in their own venv if
the console script is not present.
"""
FLAGS = {
"speaker": "--speaker",
"voice": "--speaker",
"language": "--language",
"cover": "--cover",
}
INTERMEDIATE_TXT = True
INTERMEDIATE_CALL = GenericTTSBackend._replace_map
def gen_input_flag(self, input_path) -> list[str]:
"""Return backend flag for input file or directory."""
p = self._normalize_path(input_path)
return [str(p)] # epub2tts-edge expects a single path, no flag
gen_output_flag = None
class AedocwEpub2TTS(AedocwBackend):
"""Backend configured for github.com/aedocw/epub2tts."""
pass
class AedocwEpub2TTSEdge(AedocwBackend):
"""Backend configured for github.com/aedocw/epub2tts-edge."""
DEFAULT_SPEAKER = "en-US-AndrewNeural"
CMD = ["-c", "from epub2tts_edge import main;main()"]
REPO = "epub2tts-edge"
class TTSEdge(AedocwEpub2TTSEdge):
"""Backward-compatible edge backend wrapper."""
pass
class AedocwChatterbox(AedocwBackend):
"""Backend configured for github.com/aedocw/epub2tts-chatterbox."""
DEFAULT_SAMPLE = "none"
class AedocwKokoro(AedocwBackend):
"""Backend configured for github.com/aedocw/epub2tts-kokoro."""
#DEFAULT_SPEAKER = "af_heart"
DEFAULT_SPEAKER = "am_liam"
CMD = ["-c", "from epub2tts_kokoro import main;main()"]
REPO = "epub2tts-kokoro"
FLAGS = {
"--speaker": "voice", # str, default="af_heart"
"--cover": "cover", # str, default=None
"--paragraphpause": "long_pause", # int, default=600 (ms)
"--speed": "speed", # float, default=1.3
}
DEFAULT_FLAGS = {
"voice": "am_liam",
"cover": None,
"long_pause": 600,
"speed": 1.3,
}
def get_speakers(self) -> list[str]:
"""Return list of available speakers."""
return ["af_heart", "af_joy", "af_sad", "af_angry", "af_fear", "af_surprise"]
def gen_speaker_samples(
self,
samples: list =None,
output_path: PathLike=None,
) -> list[str]:
"""Generate sample speakers audio in output_path."""
result = self._build_command("gen_samples.py", *samples, output_path=output_path)
return [str(self._normalize_path(s)) for s in samples]
class Epub2TTS(AedocwBackend):
"""Backward-compatible chatterbox backend wrapper."""
pass
__all__ = [
"AedocwBackend",
"AedocwEpub2TTS",
"AedocwEpub2TTSEdge",
"AedocwChatterbox",
"AedocwKokoro",
"TTSEdge",
"Epub2TTS",
]