diff options
| author | historia <historiavg@proton.me> | 2026-08-20 23:50:37 -0400 |
|---|---|---|
| committer | historia <historiavg@proton.me> | 2026-08-20 23:50:37 -0400 |
| commit | 38c8fdcba7ce54ad0ad76be9ef0748df1c55ebc1 (patch) | |
| tree | 911e031ee0e4b902fcd3954df3838a920416e8a3 /converter | |
| parent | 5c3df0a434059bd0d541bda35a51e49e3c44dd55 (diff) | |
| download | tts-audiobook-generator-38c8fdcba7ce54ad0ad76be9ef0748df1c55ebc1.tar.gz | |
feat: make_audiocpp_server_json.py takes an argument. remove chunk wording with audiocpp backend.
Diffstat (limited to 'converter')
| -rw-r--r-- | converter/audio.py | 14 | ||||
| -rw-r--r-- | converter/converter.py | 40 | ||||
| -rw-r--r-- | converter/tts.py | 16 |
3 files changed, 52 insertions, 18 deletions
diff --git a/converter/audio.py b/converter/audio.py index 01f78ab..d1dc28b 100644 --- a/converter/audio.py +++ b/converter/audio.py @@ -425,11 +425,19 @@ def combine_chunks(total_chunks: int, output_path: Path, if intermediate: logger.info("Chapter audio saved (intermediate): %s (%d/%d chunks)", output_path, len(chunk_files), total_chunks) - print(f"[INFO] Saved chapter audio (intermediate): {output_path.name} " - f"({len(chunk_files)}/{total_chunks} chunks)") + if len(chunk_files) == 1 and total_chunks == 1: + print(f"[INFO] Saved chapter audio (intermediate): " + f"{output_path.name}") + else: + print(f"[INFO] Saved chapter audio (intermediate): {output_path.name} " + f"({len(chunk_files)}/{total_chunks} chunks)") else: logger.info("Audiobook saved: %s (%d/%d chunks)", output_path, len(chunk_files), total_chunks) - print(f"[INFO] Saved audiobook: {output_path.name} ({len(chunk_files)}/{total_chunks} chunks)") + if len(chunk_files) == 1 and total_chunks == 1: + print(f"[INFO] Saved audiobook: {output_path.name}") + else: + print(f"[INFO] Saved audiobook: {output_path.name} " + f"({len(chunk_files)}/{total_chunks} chunks)") if speed_path is not None: logger.info("Saved speed-adjusted audiobook (%gx): %s", speed, speed_path) diff --git a/converter/converter.py b/converter/converter.py index de302ad..0ae1506 100644 --- a/converter/converter.py +++ b/converter/converter.py @@ -410,9 +410,10 @@ class AudiobookConverter: also dumped there, and every request/response is logged. """ total_chunks = len(chunks) - print(f"\n{'=' * 50}") - print(f"PROCESSING {total_chunks} CHUNKS") - print(f"{'=' * 50}") + if self.client_chunks: + print(f"\n{'=' * 50}") + print(f"PROCESSING {total_chunks} CHUNKS") + print(f"{'=' * 50}") results: Dict[int, Optional[Path]] = {} for chunk_num, chunk_text in enumerate(chunks, 1): @@ -433,7 +434,8 @@ class AudiobookConverter: destination = f" -> {copied.name}" if copied else "" logger.debug("Chunk %d/%d response in %.1fs%s", chunk_num, total_chunks, elapsed, destination) - print(f"[OK] Chunk {chunk_num:3d}/{total_chunks} completed") + if self.client_chunks: + print(f"[OK] Chunk {chunk_num:3d}/{total_chunks} completed") logger.info("+ Chunk %d/%d completed", chunk_num, total_chunks) else: logger.error("Chunk %d/%d failed", chunk_num, total_chunks) @@ -443,10 +445,11 @@ class AudiobookConverter: logger.error("Chunk %d/%d error: %s", chunk_num, total_chunks, exc) successful_chunks = sum(1 for path in results.values() if path) - print(f"\n{'=' * 50}") - print("CHUNK PROCESSING COMPLETE") - print(f"Successful: {successful_chunks}/{total_chunks}") - print(f"{'=' * 50}") + if self.client_chunks: + print(f"\n{'=' * 50}") + print("CHUNK PROCESSING COMPLETE") + print(f"Successful: {successful_chunks}/{total_chunks}") + print(f"{'=' * 50}") logger.info("Chunk processing completed: %d/%d chunks", successful_chunks, total_chunks) return results @@ -508,7 +511,19 @@ class AudiobookConverter: BACKEND_AUDIOCPP: "audio.cpp server", } backend = backend_labels.get(self.backend, "Qwen API") - print(f"[INFO] Processing {total_chunks} chunks via {backend}...") + if self.client_chunks: + print(f"[INFO] Processing {total_chunks} chunks via {backend}...") + else: + # The whole request is sent at once and the server does its + # own long-form chunking, so the chunk vocabulary does not + # apply; warn that this one request can take a very long time. + subject = (f"chapter {chapter[0]}/{chapter[1]}" + if chapter is not None else "text") + print(f"[INFO] Sending the {subject} to the {backend} as a " + "single request...") + print("[NOTE] It is expected for this to take a very long " + "time: the server synthesizes the entire request before " + "returning any audio.") results = self._synthesize_chunks(chunks, debug_dir=debug_dir) successful_chunks = sum(1 for path in results.values() if path) @@ -534,8 +549,11 @@ class AudiobookConverter: logger.info("Chapter %d/%d converted in %dm %ds (%d/%d chunks)", chapter[0], chapter[1], minutes, seconds, successful_chunks, total_chunks) - print(f"[INFO] Chapter {chapter[0]}/{chapter[1]} converted " - f"({successful_chunks}/{total_chunks} chunks)") + if self.client_chunks: + print(f"[INFO] Chapter {chapter[0]}/{chapter[1]} converted " + f"({successful_chunks}/{total_chunks} chunks)") + else: + print(f"[INFO] Chapter {chapter[0]}/{chapter[1]} converted") else: logger.info("Conversion completed in %dm %ds: %s", minutes, seconds, output_path) else: diff --git a/converter/tts.py b/converter/tts.py index 1a41643..0d867a2 100644 --- a/converter/tts.py +++ b/converter/tts.py @@ -363,15 +363,21 @@ class _BaseTTSClient: return None @contextlib.contextmanager - def _chunk_heartbeat(self, chunk_num: int): - """Print a periodic "still working" message while a chunk generates.""" + def _chunk_heartbeat(self, chunk_num: int, label: Optional[str] = None): + """Print a periodic "still working" message while a request generates. + + ``label`` overrides the default "Chunk {chunk_num}" subject, for + backends that send one request per chapter without client-side + chunking (the audio.cpp default) where "chunk" would be misleading. + """ stop = threading.Event() + subject = label if label is not None else f"Chunk {chunk_num}" def _beat(): start = time.time() while not stop.wait(config.HEARTBEAT_INTERVAL_SECONDS): elapsed = time.time() - start - print(f"[...] Chunk {chunk_num} still generating — " + print(f"[...] {subject} still generating — " f"{int(elapsed // 60)}m {int(elapsed % 60)}s elapsed", flush=True) thread = threading.Thread(target=_beat, daemon=True) @@ -1170,7 +1176,9 @@ class AudioCppTTSClient(_BaseTTSClient): output_path: Optional[Path] = None with tempfile.TemporaryDirectory(prefix="tts_parts_") as parts_dir, \ - self._chunk_heartbeat(chunk_num): + self._chunk_heartbeat( + chunk_num, + label=None if self.chunk_text else "Request"): part_paths = [] for sub_num, sub_text in enumerate(sub_texts, 1): wav = self._request_wav_with_retry( |
