aboutsummaryrefslogtreecommitdiff
path: root/app/converter
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-08-27 19:00:44 -0400
committerhistoria <historiavg@proton.me>2026-08-27 19:00:44 -0400
commit5611f709367677b77a482aa8e396fd3bc6a0ab26 (patch)
treec19f8ffa5a199d65ebb2c44ffaa7fc3feff3f078 /app/converter
parent5ecf7711f3457587a00859b04e239d1d7de3ca2f (diff)
downloadtts-audiobook-generator-5611f709367677b77a482aa8e396fd3bc6a0ab26.tar.gz
feat: flags for converting individual book files --input-book --output-book
Diffstat (limited to 'app/converter')
-rw-r--r--app/converter/converter.py54
1 files changed, 38 insertions, 16 deletions
diff --git a/app/converter/converter.py b/app/converter/converter.py
index d2d06b9..e1649c2 100644
--- a/app/converter/converter.py
+++ b/app/converter/converter.py
@@ -788,6 +788,8 @@ class AudiobookConverter:
output_format: str,
instructions: Optional[str] = None,
confirm: Optional[Callable[[str, bool], bool]] = None,
+ book_files: Optional[List[Path]] = None,
+ output_name: Optional[str] = None,
) -> Tuple[List[Path], List[Tuple[Path, str]]]:
"""Discover books and ask every overwrite question up front.
@@ -801,35 +803,55 @@ class AudiobookConverter:
nothing to convert) never waits on a slow server handshake.
CONFIRM replaces the console ``input()`` prompt (the hub passes a
TUI yes/no dialog).
+
+ BOOK_FILES overrides the books-folder scan with an explicit list
+ (a single --input-file book; still filtered to supported formats),
+ and OUTPUT_NAME overrides the computed output name with a verbatim
+ base name (--output-file's stem, no narrator tag or stem-collision
+ suffix). Both default to the directory-scan behavior.
"""
- book_files = sorted(
- f for f in BOOKS_FOLDER.iterdir()
- if f.is_file() and f.suffix.lower() in SUPPORTED_FORMATS
- )
+ if book_files is None:
+ book_files = sorted(
+ f for f in BOOKS_FOLDER.iterdir()
+ if f.is_file() and f.suffix.lower() in SUPPORTED_FORMATS
+ )
+ else:
+ book_files = sorted(
+ f for f in book_files
+ if f.is_file() and f.suffix.lower() in SUPPORTED_FORMATS
+ )
if not book_files:
return [], []
print(f"[INFO] Found {len(book_files)} books to convert")
- # Avoid output collisions when two books share a stem (e.g. dune.txt + dune.epub).
- stem_counts: Dict[str, int] = Counter(book_file.stem for book_file in book_files)
+ # Compute the output name each book would produce. An explicit
+ # name (--output-file) is used verbatim for the single book;
+ # otherwise names carry the narrator tag and a stem-collision
+ # suffix when two books share a stem (e.g. dune.txt + dune.epub).
+ if output_name is not None:
+ names = [(book_files[0], output_name)]
+ else:
+ stem_counts: Dict[str, int] = Counter(book_file.stem for book_file in book_files)
+ narrator_tag = AudiobookConverter.compute_narrator_tag(
+ backend, voice, voice_mode, voice_clone_ref_audio, instructions)
+ names = []
+ for book_file in book_files:
+ name = book_file.stem
+ if stem_counts[book_file.stem] > 1:
+ name = f"{book_file.stem}_{book_file.suffix.lstrip('.')}"
+ names.append((book_file, f"{name}_{narrator_tag}"))
# Ask every overwrite question up front, before any conversion
# starts, so the rest of the run is unattended.
planned: List[Tuple[Path, str]] = []
- narrator_tag = AudiobookConverter.compute_narrator_tag(
- backend, voice, voice_mode, voice_clone_ref_audio, instructions)
- for book_file in book_files:
- output_name = book_file.stem
- if stem_counts[book_file.stem] > 1:
- output_name = f"{book_file.stem}_{book_file.suffix.lstrip('.')}"
- output_name = f"{output_name}_{narrator_tag}"
- existing = find_existing_outputs(output_name, output_format)
- if existing and not prompt_overwrite(existing, output_name,
+ for book_file, name in names:
+ existing = find_existing_outputs(name, output_format)
+ if existing and not prompt_overwrite(existing, name,
confirm=confirm):
print(f"[INFO] Skipping {book_file.name} (existing output kept)")
continue
- planned.append((book_file, output_name))
+ planned.append((book_file, name))
return book_files, planned
# ------------------------------------------------------------------