mirror of
https://github.com/denizsafak/abogen.git
synced 2026-07-18 13:40:27 +02:00
feat: Enhance voice resolution and logging in conversion job for improved feedback and performance
This commit is contained in:
@@ -79,11 +79,15 @@ def run_conversion_job(job: Job) -> None:
|
|||||||
chapter_dir = audio_dir / "chapters"
|
chapter_dir = audio_dir / "chapters"
|
||||||
chapter_dir.mkdir(parents=True, exist_ok=True)
|
chapter_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
voice = _resolve_voice(pipeline, job)
|
voice_spec = job.voice or ""
|
||||||
|
cached_voice = None
|
||||||
|
if "*" not in voice_spec:
|
||||||
|
cached_voice = _resolve_voice(pipeline, voice_spec, job.use_gpu)
|
||||||
processed_chars = 0
|
processed_chars = 0
|
||||||
subtitle_index = 1
|
subtitle_index = 1
|
||||||
current_time = 0.0
|
current_time = 0.0
|
||||||
total_chapters = len(extraction.chapters)
|
total_chapters = len(extraction.chapters)
|
||||||
|
job.add_log(f"Detected {total_chapters} chapter{'s' if total_chapters != 1 else ''}")
|
||||||
|
|
||||||
for idx, chapter in enumerate(extraction.chapters, start=1):
|
for idx, chapter in enumerate(extraction.chapters, start=1):
|
||||||
canceller()
|
canceller()
|
||||||
@@ -106,18 +110,27 @@ def run_conversion_job(job: Job) -> None:
|
|||||||
fmt=job.separate_chapters_format,
|
fmt=job.separate_chapters_format,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
voice_choice = cached_voice if cached_voice is not None else _resolve_voice(
|
||||||
|
pipeline, voice_spec, job.use_gpu
|
||||||
|
)
|
||||||
|
|
||||||
|
segments_emitted = 0
|
||||||
|
|
||||||
for segment in pipeline(
|
for segment in pipeline(
|
||||||
chapter.text,
|
chapter.text,
|
||||||
voice=voice,
|
voice=voice_choice,
|
||||||
speed=job.speed,
|
speed=job.speed,
|
||||||
split_pattern=SPLIT_PATTERN,
|
split_pattern=SPLIT_PATTERN,
|
||||||
):
|
):
|
||||||
canceller()
|
canceller()
|
||||||
graphemes = segment.graphemes.strip()
|
graphemes_raw = getattr(segment, "graphemes", "") or ""
|
||||||
if not graphemes:
|
graphemes = graphemes_raw.strip()
|
||||||
|
|
||||||
|
audio = _to_float32(getattr(segment, "audio", None))
|
||||||
|
if audio.size == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
audio = _to_float32(segment.audio)
|
segments_emitted += 1
|
||||||
if chapter_sink:
|
if chapter_sink:
|
||||||
chapter_sink.write(audio)
|
chapter_sink.write(audio)
|
||||||
if audio_sink:
|
if audio_sink:
|
||||||
@@ -128,9 +141,13 @@ def run_conversion_job(job: Job) -> None:
|
|||||||
job.processed_characters = processed_chars
|
job.processed_characters = processed_chars
|
||||||
if job.total_characters:
|
if job.total_characters:
|
||||||
job.progress = min(processed_chars / job.total_characters, 0.999)
|
job.progress = min(processed_chars / job.total_characters, 0.999)
|
||||||
job.add_log(f"{processed_chars:,}/{job.total_characters or '—'}: {graphemes[:80]}")
|
else:
|
||||||
|
job.progress = 0.0 if processed_chars == 0 else 0.999
|
||||||
|
|
||||||
if subtitle_writer and audio_sink:
|
preview_text = graphemes or (graphemes_raw[:80] if graphemes_raw else "[silence]")
|
||||||
|
job.add_log(f"{processed_chars:,}/{job.total_characters or '—'}: {preview_text[:80]}")
|
||||||
|
|
||||||
|
if subtitle_writer and audio_sink and graphemes:
|
||||||
subtitle_writer.write_segment(
|
subtitle_writer.write_segment(
|
||||||
index=subtitle_index,
|
index=subtitle_index,
|
||||||
text=graphemes,
|
text=graphemes,
|
||||||
@@ -144,9 +161,19 @@ def run_conversion_job(job: Job) -> None:
|
|||||||
|
|
||||||
if chapter_sink:
|
if chapter_sink:
|
||||||
chapter_sink_stack.close()
|
chapter_sink_stack.close()
|
||||||
|
|
||||||
|
if chapter_audio_path is not None:
|
||||||
job.result.artifacts[f"chapter_{idx:02d}"] = chapter_audio_path
|
job.result.artifacts[f"chapter_{idx:02d}"] = chapter_audio_path
|
||||||
chapter_paths.append(chapter_audio_path)
|
chapter_paths.append(chapter_audio_path)
|
||||||
|
|
||||||
|
if segments_emitted == 0:
|
||||||
|
job.add_log(
|
||||||
|
f"No audio segments were generated for chapter {idx}.",
|
||||||
|
level="warning",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
job.add_log(f"Finished chapter {idx} with {segments_emitted} segments.")
|
||||||
|
|
||||||
if (
|
if (
|
||||||
audio_sink
|
audio_sink
|
||||||
and job.merge_chapters_at_end
|
and job.merge_chapters_at_end
|
||||||
@@ -340,16 +367,27 @@ def _build_ffmpeg_command(path: Path, fmt: str, metadata: Optional[Dict[str, str
|
|||||||
return base
|
return base
|
||||||
|
|
||||||
|
|
||||||
def _resolve_voice(pipeline, job: Job):
|
def _resolve_voice(pipeline, voice_spec: str, use_gpu: bool):
|
||||||
if "*" in job.voice:
|
if "*" in voice_spec:
|
||||||
return get_new_voice(pipeline, job.voice, job.use_gpu)
|
return get_new_voice(pipeline, voice_spec, use_gpu)
|
||||||
return job.voice
|
return voice_spec
|
||||||
|
|
||||||
|
|
||||||
def _to_float32(audio_segment) -> np.ndarray:
|
def _to_float32(audio_segment) -> np.ndarray:
|
||||||
if hasattr(audio_segment, "numpy"):
|
if audio_segment is None:
|
||||||
return audio_segment.numpy().astype("float32")
|
return np.zeros(0, dtype="float32")
|
||||||
return np.asarray(audio_segment, dtype="float32")
|
|
||||||
|
tensor = audio_segment
|
||||||
|
if hasattr(tensor, "detach"):
|
||||||
|
tensor = tensor.detach()
|
||||||
|
if hasattr(tensor, "cpu"):
|
||||||
|
try:
|
||||||
|
tensor = tensor.cpu()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
if hasattr(tensor, "numpy"):
|
||||||
|
return np.asarray(tensor.numpy(), dtype="float32").reshape(-1)
|
||||||
|
return np.asarray(tensor, dtype="float32").reshape(-1)
|
||||||
|
|
||||||
|
|
||||||
class SubtitleWriter:
|
class SubtitleWriter:
|
||||||
|
|||||||
Reference in New Issue
Block a user