#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (c) 2025-2026 Renato Xavier da Silveira Rosa # See [LICENSE](./LICENSE) or [BSD-3-Clause-Clear](https://spdx.org/licenses/BSD-3-Clause-Clear.html) import sys <<<<<<< HEAD from pathlib import Path from argparse import ArgumentParser # Pip packages from dotenv import load_dotenv # Local imports from . import tts_aedocw, tts_generic #from . import tts_kokoro from . import log, PathLike from .utils import check_env # Setup env load_dotenv() # load environment variables from .env file if present # Globals WHICH = ["ffmpeg"] # Neded in $PATH BACKENDS = { # keys are the backend names, values are the corresponding TTS classes "default": tts_generic.GenericTTSBackend, "edge": tts_aedocw.TTSEdge, # aedocw-backed implementations — these expect the corresponding # package "console scripts"/entrypoints to be available in the # environment (or an explicit backend_cmd to be provided). "epub2tts": tts_aedocw.AedocwEpub2TTS, "epub2tts-edge": tts_aedocw.AedocwEpub2TTSEdge, "epub2tts-chatterbox": tts_aedocw.AedocwChatterbox, "epub2tts-kokoro": tts_aedocw.AedocwKokoro, "generic-epub2tts": tts_aedocw.Epub2TTS, #"kokoro": tts_kokoro.KokoroBackend, } def main(args=None): p = ArgumentParser(description="Convert EPUB to audio using TTS") p.add_argument( "--version", help="Show version and exit", action="version", version=f"%(prog)s {__import__('epub_tts').__version__}", ) # Input options and processing p.add_argument("-i", "--input", nargs="+", required=True, help="Input EPUB file") p.add_argument("-r", "--replace", action="append", nargs=2, help="Replace text in the intermediate output. " "Specify pairs of old_text new_text. " "Can be used multiple times.") p.add_argument("--check-env",action="store_true", help="Check the runtime environment and exit") p.add_argument("-b", "--backend", default="default", choices=BACKENDS.keys(), help="Backend to use for TTS") # Output options p.add_argument("-o", "--output", help="Output audio file", required=True) p.add_argument("-c", "--cover", help="Path to cover image to embed or use " "for output metadata") # Speech options p.add_argument("-l", "--language", help="Language to use for TTS (see your " "backend's documentation for available voices)") p.add_argument("-v", "--voice", help="Voice to use for TTS (see your backend's " "documentation for available voices)") p.add_argument("--speed", type=float, default=1.0, help="Playback speed multiplier (default: 1.0) " "(not all backends support this)") p.add_argument("--short-pause", type=int, default=None, help="Short pause duration in milliseconds between " "phrases or sentences (not all backends support this)") p.add_argument("--long-pause", type=int, default=None, help="Long pause duration in milliseconds between " "sections or paragraphs (not all backends support this)") p.add_argument("--notitles", action="store_true", help="Do not read chapter titles") # Parse args = p.parse_args(args or sys.argv[1:]) setattr(args, 'replace_map', {old: new for old, new in args.replace} if args.replace else None) log(args) # Execute actions if args.check_env: check_env() engine = BACKENDS[args.backend](**vars(args)) if len(args.input) > 1 and not output_dest.is_dir(): log(f"Output must be a directory when multiple input files are provided", level="error") sys.exit(1) for file in args.input: log(file) if not Path(file).exists(): log(f"Input file {file} does not exist", level="error") sys.exit(1) output_dest = Path(args.output) engine.run( file, output_dest, **vars(args), ) ======= from .cli import cli >>>>>>> dev if __name__ == "__main__": sys.exit(cli())