126 lines
3.8 KiB
Python
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",
|
|
]
|