diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..f684de0 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "ms-python.python", + "ms-python.debugpy" + ] +} \ No newline at end of file diff --git a/LICENSE b/LICENSE index cad8b56..a583980 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -The Clear BSD License +# The Clear BSD License -Copyright (c) [xxxx]-[xxxx] [Owner Organization] +Copyright (c) 2025-2026 Renato Xavier da Silveira Rosa All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met: diff --git a/README.md b/README.md index 5348bc1..8703307 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,33 @@ # epub-tts -Python project to gather several projects that convert EPUB files to audiobooks (M4B giles, mostly), with different TTS backends. \ No newline at end of file +Python project to gather several projects that convert EPUB files to audiobooks (M4B files, mostly), with different TTS backends. + +# Requirements + +Recent Python (>=3.11), pip (>=22.3), some sort of virtula environment recommended (such as the builtin venv package), and a Rust compatible platform (avoid embedded systems which do not have pre-built binaries for the compiled requirements, e.g., Android's Termux try to build everything from sources and fails miserably when doing so). + +# Installation + +1. [Optional] Create virtual environment anywhere, e.g.: `python -m venv .venv` and activate it. + - See your virtual environment package's documentation, such as [`venv`](https://docs.python.org/3/library/venv.html) + - A virtual environment may be “activated” using a script in its binary directory (`bin` on POSIX; `Scripts` on Windows). + - Example: `source .venv/bin/activate` or `.venv\Scripts\Activate.ps1` + +2. Install depedencies with `pip install .`, which should read the `[dependencies]` section in [pyproject.toml](./pyproject.toml) or `pip install -e '.[dev]'` to install in editable mode, including `dev` dependencies section (`[optional-depedencies]`). + +3. Test install running `epub-tts --version` + - Make sure the venv is activated or that pip installed the package in your PATH + +# + +# Citation + +There is no need for academic citation specifics, just mention this project's URL and author, according to [LICENSE](./LICENSE). + +# License + +See [LICENSE](./LICENSE). + +# Agents + +See [AGENTS.md](./AGENTS.md). diff --git a/epub-tts.code-workspace b/epub-tts.code-workspace new file mode 100644 index 0000000..876a149 --- /dev/null +++ b/epub-tts.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..6ed704c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,127 @@ +[build-system] +requires = ["setuptools>=61.0.0", "setuptools-scm[simple]>=9.2"] +build-backend = "setuptools.build_meta" + +[project] +name = "epub-tts" +dynamic = ["version"] +description = "Python project to gather several projects that convert EPUB files to audiobooks (M4B files, mostly), with different TTS backends." +readme = "README.md" +# Minimum could probably be 3.10, but wasn't tested +requires-python = ">=3.11" +license = "BSD-3-Clause-Clear" +license-files = ["LICENSE"] +authors = [ + { name = "Renato Xavier da Silveira Rosa", email = "renatoxsr@gmail.com" } +] + +classifiers = [ + "Programming Language :: Python :: 3", + "Development Status :: 3 - Alpha", + "Operating System :: OS Independent", + "Environment :: Console", + "Environment :: GPU", + "Topic :: Multimedia :: Sound/Audio :: Sound Synthesis", + "Topic :: Text Processing :: Filters", + "Topic :: File Formats" +] + +dependencies = [ + "requests>=2.28.0", +] + +[project.optional-dependencies] +dev = [ + "ruff>=0.4", +] + +[project.urls] +Homepage = "https://git.silveirarosa.com/renatoxsr/epub-tts" +Issues = "https://git.silveirarosa.com/renatoxsr/epub-tts/issues" + +[project.scripts] +epub-tts = "epub_tts.__main__:main" + +# SETUPTOOLS +[tool.setuptools.packages.find] +where = ["src"] + +[tool.setuptools.dynamic] +#version = {attr = "epub_tts.__version__"} + +[tool.setuptools_scm] + +# RUFF +[tool.ruff] + +# Target Python version +target-version = "py311" + +# Same as Black default +indent-width = 4 + +# # Standard Line Length Limits +# - 79 Characters: The strict PEP 8 official standard for code. It prevents horizontal wrapping or scrolling on older terminals and ensures high code readability. +# - 72 Characters: The PEP 8 official standard strictly reserved for docstrings and comments. +# - 88 Characters: The default standard used by Black, a highly popular, uncompromising Python code formatter. +# - 99 Characters: The maximum limit permitted by PEP 8 for internal or team-based projects if the team explicitly agrees to a longer limit. +# - 100 to 120 Characters: A very common relaxed standard used in enterprise environments, large open-source projects, and default setups for modern IDEs like JetBrains +line-length = 88 + +# Exclude a variety of commonly ignored directories. +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".ipynb_checkpoints", + ".mypy_cache", + ".nox", + ".pants.d", + ".pyenv", + ".pytest_cache", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + ".vscode", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "site-packages", + "venv", +] + +[tool.ruff.lint] +# select = [...] # See the Default Rules page for the full listing. +ignore = [] + +# Allow fix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] +unfixable = [] + +# Enable Pyflakes (F) and Flake8 (E/W) codes +select = ["E", "F", "I"] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +[tool.ruff.format] + +# Use double quotes (like Black) +quote-style = "double" + +# Like Black, indent with spaces, rather than tabs. +indent-style = "space" + +# Like Black, respect magic trailing commas. +skip-magic-trailing-comma = false + +# Like Black, automatically detect the appropriate line ending. +line-ending = "auto" \ No newline at end of file diff --git a/src/epub_tts/__init__.py b/src/epub_tts/__init__.py new file mode 100644 index 0000000..2c3ac1c --- /dev/null +++ b/src/epub_tts/__init__.py @@ -0,0 +1,14 @@ +#!/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) + +# importlib.metadata from the standard library (added in Python 3.8) +# or the importlib_metadata backport for earlier versions: +from importlib.metadata import version, PackageNotFoundError + +try: + __version__ = version("epub-tts") +except PackageNotFoundError: + # package is not installed + pass diff --git a/src/epub_tts/__main__.py b/src/epub_tts/__main__.py new file mode 100644 index 0000000..facd6d7 --- /dev/null +++ b/src/epub_tts/__main__.py @@ -0,0 +1,25 @@ +#!/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 +from argparse import ArgumentParser + + +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__}") + p.add_argument("-i","--input", help="Input EPUB file", required=True) + p.add_argument("-o","--output", help="Output audio file", required=True) + p.add_argument("-l","--language", help="Language to use for TTS") + p.add_argument("-v","--voice", help="Voice to use for TTS") + + args = p.parse_args(args or sys.argv[1:]) + print(f"Converting {args.input} to {args.output} using voice {args.voice}, language {args.language}, ...") + + + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file