121 lines
4.3 KiB
Python
121 lines
4.3 KiB
Python
#!/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())
|